Att bevara VPN-klientens adress hela vägen till applikationen gör att varje logglinje och varje post i tillåtelselistan betyder samma sak. Att skriva om den vid molngränsen gör routingtabellen enklare och loggarna mindre användbara. Ingen av de två valen är fel i sig, och argumentet som avgör saken handlar sällan om prestanda. Tre villkor avgör: om applikationen måste veta vilken människa som anslöt, om molntyget accepterar den källa du tänker skicka, och vem som är villig att ta ansvar för returvägen efteråt.

Tre villkor avgör

Börja med applikationens krav, inte med nätverksdiagrammet. Om auktorisering eller revision beror på den enskilda klientadressen är bevarandet ett funktionellt krav och översättning en regression. Om applikationen bara behöver veta att trafiken kom via fjärråtkomstvägen räcker en översatt adress och den är mycket billigare att driva.

Det andra villkoret är mekaniskt. Ett virtuellt nätverk litar inte automatiskt på ett paket som hävdar en adress som inte tilldelats det sändande gränssnittet. De flesta molntyg upprätthåller det, på olika sätt och under olika namn, och en design som ignorerar det ser korrekt ut i ett diagram och tappas tyst i produktion.

Det tredje är organisatoriskt. Att bevara källor innebär att routingtabellen för applikationens subnät måste peka tillbaka mot gatewayen för klientprefixet, och varje team som lägger till ett subnät senare måste hålla den rutten konsekvent. Det är en liten kostnad en gång, och en återkommande kostnad över dussintals konton. Bestäm vem som betalar den innan du lovar beteendet.

En rutt är inte tillstånd att spoofa

Att lägga till en returrutt talar om för ditt subnät vart svaren ska gå. Det talar inte om för tyget att instansen som vidarebefordrar paketen får skicka dem med en främmande källa. På AWS är den relevanta kontrollen käll- och destinationskontroll, och den syns per instans:

aws ec2 describe-instances --instance-ids i-0a1b2c3d4e5f60718 \
  --query "Reservations[].Instances[].SourceDestCheck"
aws ec2 modify-instance-attribute --instance-id i-0a1b2c3d4e5f60718 \
  --no-source-dest-check

Stäng av den bara för instansen vars dokumenterade jobb är vidarebefordran, och inte för något annat. Varje applikations-VM som behåller kontrollen på är en maskin mindre som kan användas för att skicka trafik med en lånad källa. Om din plattform inte är AWS, leta efter motsvarande anti-spoofing- eller tillåtna adressinställning i stället för att anta att beteendet följer med.

En snabb paketinsamling avgör frågan snabbare än att läsa konsolen. Om svaren går ut och klienten aldrig ser dem är det tyget som slänger den förfalskade källan, och inte applikationen som misslyckas.

Vad översättning köper, och vad den kostar

Att skriva om källan vid gatewayen tar bort returvägsproblemet. Applikationen ser en adress som den redan vet hur den ska nå, och klientprefixet behöver aldrig dyka upp i en molnroutingtabell. På Linux är regeln en rad, och det är värt att skriva den smalaste version du kan:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 172.20.8.0/24 -o ens5 -j SNAT --to-source 10.40.3.10

Lägg märke till vad applikationen nu registrerar: 10.40.3.10 för varje användare, på varje anslutning, för alltid. Varje adresstillåtelselista byggd på det värdet ger nu åtkomst till hela fjärråtkomstpopulationen, och varje incidentgranskning måste gå tillbaka till gatewayen för att svara på vem det var.

Lösningen är inte att överge översättning, den är att sluta låtsas att adressen är en identitet. Bär klientens identitet i ett autentiserat fält, logga den vid gatewayen tillsammans med den översatta tupeln, och låt applikationen koppla sig på den. Utan kopplingsnyckeln förvandlar översättningen ett nätverksproblem till ett permanent forensiskt problem.

Reläet är ett annat gränssnitt

En omvänd proxy framför applikationen kringgår frågan om den routade vägen helt. Proxyn öppnar sin egen backendanslutning, så klientprefixet behöver aldrig vara routbart inne i det virtuella nätverket, och applikationen kan ta emot identitet i en header som proxyn sätter.

Den headern är bara pålitlig när backend accepterar den från proxyn och från ingenting annat. I nginx-termer betyder det att namnge den betrodda parten uttryckligen i stället för att tro på vad som helst som kommer:

set_real_ip_from 10.40.3.10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Varje klient som kan nå backend direkt kan förfalska samma header, så backend måste vara onåbar utom via proxyn. Det är ett brandväggsfaktum, inte en konfigurationsåsikt, och det är antagandet folk hoppar över när de kopierar utdraget.

Reläet ändrar också vad du köper. Du får en identitet på applikationsnivå och en naturlig plats att logga den; du avstår från allmängiltighet, eftersom varje nytt protokoll behöver sitt eget proxy-stöd. För HTTP-tjänster är den handeln oftast bra, och för allt som inte är HTTP är den oftast inte tillgänglig alls.

Skriv ned vad varje gräns ser

Vad du än väljer bör designgranskningen sluta med en tabell som namnger källadressen och den bevisbara identiteten vid varje hopp. Utan den producerar den första incidenten tre team som var och en beskriver en annan klient.

BoundarySource the next hop seesWhat is actually proven
Client to gateway172.20.8.14A certificate or credential was presented
Gateway to app subnet, preserved172.20.8.14The same session, if the return route exists
Gateway to app subnet, translated10.40.3.10Only that traffic came through the gateway
Proxy to backend10.40.3.10 plus a headerThe proxy asserted an identity it authenticated

Välj sedan. Bevara när applikationens auktorisering verkligen beror på klientadressen och du kan ta ansvar för rutten. Översätt när den inte gör det och du kan bära identitet utanför bandet, och använd AWS vägledning för vidarebefordrande instanser för de plattformsspecifika vidarebefordringsinställningarna. Gripa efter ett relä när tjänsten talar HTTP och du vill att identitet ska sluta vara en adress.

Relaterade artiklar