Sokkelmodpart kontra videresendt header: hvilken adresse kan du stole på?
Sokkelmodparten og en videresendt header er forskellige beviser. Sammenlign, hvad hver af dem beviser, og stol kun på headeren gennem en proxkæde, du selv kontrollerer.
En anmodning, der ankommer til din applikation, bærer to slags adressebeviser: den modpart, der åbnede netværksforbindelsen, og et HTTP-felt, der hævder en tidligere klients adresse. De besvarer forskellige spørgsmål. Sokkelmodparten observeres, mens headeren hævdes af den, der skrev den, og ingen af dem bør lydløst erstatte den anden i en log eller en adgangsregel. Sammenligningen nedenfor holder dem adskilt og viser derefter det eneste arrangement, hvor headeren bliver brugbar.
Beskriv stien, før du sammenligner noget:
Client -> approved reverse proxy -> application originI det arrangement er oprindelsens sokkelmodpart normalt proxen, og en videresendt header kan bære proxens påstand om klienten. Dens værdi kommer fra det kontrollerede forhold til den proxy, ikke fra headerens navn.
To slags adressebeviser
Sokkelmodparten er et faktum om én TCP-forbindelse: noget fuldførte et håndtryk fra den adresse. Det er ikke nødvendigvis det menneske, den enhed eller den konto, du bekymrer dig om, fordi en VPN eller en Tor-udgang legitimt kan være den kilde, en tjeneste observerer. Den er stadig den eneste adresse, værten selv har bekræftet, og det er hele dens værdi.
Et videresendelsesfelt er metadata om en kæde. X-Forwarded-For, X-Real-IP og det standardiserede felt Forwarded kan skrives af enhver klient, der når et endepunkt, som gentager dem, så deres troværdighed afhænger helt af, hvem der fik lov at sætte dem.
Behold begge i anmodningskonteksten under forskellige navne. En applikation, der overskriver modparten med headeren, mister evnen til senere at rekonstruere en tillidsfejl, og det er netop, når du har brug for den.
En header omdirigerer aldrig forbindelsen
At skrive en adresse i et videresendelsesfelt ændrer ikke kilden til den TCP-forbindelse, der ankommer til serveren, og det ændrer ikke routing nogen steder på stien. Almindelig VPN-routing eller kilde-NAT leverer trafik uden nogen HTTP-header overhovedet. På samme måde omskriver en transitgateway ikke en korrekt beskyttet HTTPS-udveksling uden at ændre TLS-endepunktets arrangement.
Den omvendte fejl er lige så almindelig: HTTPS gør ikke en klientleveret videresendt header sand. Det beskytter transporten af en falsk påstand præcis lige så godt som af en sand.
Hvis en kollega foreslår en headerændring for at løse et routingproblem, er diagnosen allerede gået galt. Ret stien, eller ret den proxykonfiguration, der skriver headeren.
Navngiv den proxy, der må hævde
To regler gør et videresendelsesfelt brugbart, og begge er konfiguration frem for kode. Kanten normaliserer eller dropper alt, hvad der kommer udefra, efter sin egen dokumenterede adfærd for disse felter. Oprindelsen tager derefter en erstatningsadresse fra den proxysti, du navngav, og fra intet andet. Den anden regel gælder kun, så længe klienter ikke kan nå oprindelsen på anden vis, fordi en oprindelse, der svarer på både direkte og proxyede anmodninger, ikke aner, hvilken af dem den betjener.
NGINX-modulet til rigtig IP viser opdelingen tydeligt. set_real_ip_from navngiver de afsendere, hvis påstand tæller, og real_ip_header siger, hvilket felt der bærer den; det første udfører tilliden, det andet siger kun, hvor man skal kigge.
set_real_ip_from 10.20.0.0/24;
real_ip_header X-Forwarded-For;
# real_ip_recursive off - take the rightmost value in the field
# real_ip_recursive on - walk the list back past every trusted address
En headerudvælgelsesdirektiv alene fastslår stadig intet om, hvem der sendte værdien.
Transportsikkerhed skal løbe hele vejen mellem de komponenter, du stoler på. En kant, der normaliserer korrekt, mister den værdi i det øjeblik, et ubeskyttet hop længere nede lader en anden redigere påstanden, mens den rejser.
Håndtér kæder med flere hop bevidst
Flere proxier kræver en eksplicit kædemodel. Tag ikke den venstreste eller højreste kommaseparerede værdi, fordi et blogindlæg gjorde det; find ud af, hvilke af dine proxier der tilføjer, hvilke der erstatter, og hvilke der bevarer det indgående felt. NGINX kan for eksempel gå listen baglæns gennem sit betroede sæt og stoppe ved den første adresse, det ikke ejer, og det er det produkts regel snarere end en lov, som hvert framework følger. Læs din egen proxys dokumentation med de samme to spørgsmål: hvilken værdi vælger den, og hvilke afsendere tror den på?
Skriv kæden ned: hoprækkefølge, hvilket hop der sætter feltet, og hvilket hop der fjerner indgående kopier. Opbevar derefter notatet ved siden af proxykonfigurationen, ikke kun i billetten. Test det derefter ved at sende en anmodning med en forfalsket header gennem den godkendte valideringsproces og bekræfte, at oprindelsen ignorerer den.
Når du tilføjer et hop, skal du gennemgå det dokument. En ny lastbalancer, der indsættes foran den betroede proxy, kan ændre, hvilken adresse der vinder, uden at nogen redigerer applikationen.
Behold begge observationer i loggen
Hvor diagnostik er tilladt, skal du logge forbindelsens modpart og den normaliserede klientadresse som to separate felter og kun tilføje de videresendelsesmetadata, som formålet faktisk har brug for. Bevis derefter implementeringen med to anmodninger: en proxyet, der bør registrere begge værdier fornuftigt, og et forsøg direkte på oprindelsen, som skal afvises.
Husk, hvad parret betyder. Headere tilføjer kontekst fra en komponent, du valgte at stole på; modparten forbliver den eneste adresse, din vært faktisk så. Ingen af dem er bevis for individuel identitet, og et design, der behandler en af dem som bevis, vil tage fejl om nogen.