Vraag nginx real_ip_header en X-Forwarded-For lijkt fout


De wikipedia-beschrijving van de HTTP-header X-Forwarded-For is:

X-Forwarded-For: client1, proxy1, proxy2, ...

De nginx-documentatie voor de richtlijn real_ip_header leest, gedeeltelijk:

Deze richtlijn stelt de naam in van de kop die wordt gebruikt voor het overdragen van het vervangende IP-adres.
  In het geval van X-Forwarded-For gebruikt deze module de laatste ip in de X-Forwarded-For-header voor vervanging. [Nadruk mijn]

Deze twee beschrijvingen lijken op gespannen voet te staan ​​met elkaar. In ons scenario, de X-Forwarded-For header is precies zoals beschreven - het "echte" IP-adres van de client is de meest linkse invoer. Evenzo is het gedrag van nginx het gebruik van de rechts- de meeste waarde - wat uiteraard slechts een van onze proxyservers is.

Mijn begrip van X-Real-IP is dat het is vermeend te gebruiken om het te bepalen werkelijk client IP-adres - niet de proxy. Mis ik iets, of is dit een fout in Nginx?

En bovendien, heeft iemand nog suggesties voor het maken van de X-Real-IP header display the links- de meeste waarde, zoals aangegeven door de definitie van X-Forwarded-For?


49
2017-09-22 20:41


oorsprong




antwoorden:


Ik geloof dat de sleutel tot het oplossen van problemen met X-Forwarded-For, wanneer meerdere IP's worden geketend, de recent geïntroduceerde configuratie-optie is, real_ip_recursive (toegevoegd in nginx 1.2.1 en 1.3.0). Van de nginx realip docs:

Als recursief zoeken is ingeschakeld, wordt een origineel clientadres dat overeenkomt met een van de vertrouwde adressen vervangen door het laatste niet-vertrouwde adres dat is verzonden in het veld met de vraagkop.

nginx greep standaard het laatste IP-adres in de keten, omdat dat de enige was waarvan werd aangenomen dat het werd vertrouwd. Maar met het nieuwe real_ip_recursive ingeschakeld en met meerdere set_real_ip_from opties, kunt u meerdere vertrouwde proxy's definiëren en wordt het laatste niet-vertrouwde adres opgehaald.

Met deze config:

set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

En een X-Forwarded-For-header die resulteert in:

X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1

nginx kiest nu 123.123.123.123 als het IP-adres van de klant.

Wat betreft waarom nginx niet alleen het meest linkse IP-adres kiest en vereist dat u expliciet betrouwbare proxies definieert, is dit om gemakkelijke IP-spoofing te voorkomen.

Laten we zeggen dat het echte IP-adres van een klant dat is 123.123.123.123. Laten we ook zeggen dat de client niet goed is en dat ze proberen hun IP-adres te vervalsen 11.11.11.11. Ze sturen een verzoek naar de server met deze header al op zijn plaats:

X-Forwarded-For: 11.11.11.11

Omdat omgekeerde proxy's gewoon IP's aan deze X-Forwarded-For-keten toevoegen, laten we zeggen dat het er als volgt uit ziet als nginx erbij komt:

X-Forwarded-For: 11.11.11.11, 123.123.123.123, 192.168.2.1, 127.0.0.1

Als je eenvoudig het meest linkse adres hebt gepakt, kan de client zijn IP-adres gemakkelijk vervalsen. Maar met het bovenstaande voorbeeld nginx config, vertrouwt nginx alleen de laatste twee adressen als proxies. Dit betekent dat nginx correct zal kiezen 123.123.123.123 als het IP-adres, ondanks dat dat vervalste IP feitelijk het meest linkse IP-adres is.


75
2017-08-03 22:45



Heel erg bedankt hiervoor, het heeft me echt geholpen. Dit zou het geaccepteerde antwoord moeten zijn. - José F. Romaniello
Standaard lijkt real_ip_header X-Real-IP te zijn volgens nginx.org/en/docs/http/ngx_http_realip_module.html Betekent dit dat kwaadwillende gebruikers gewoon een verzoek kunnen verzenden met willekeurig X-Real-IP en dat dit wordt gebruikt als $ remote_addr in nginx (en mogelijk ook wordt doorgegeven aan de toepassing)? - gansbrest
@gansbrest Nee, omdat set_real_ip_from de vertrouwde hosts beperkt. - El Yobo


Het ontleden van de X-Forwarded-Forheader is inderdaad gebrekkig in de nginx real_ip module.

len = r->headers_in.x_forwarded_for->value.len;
ip = r->headers_in.x_forwarded_for->value.data;

for (p = ip + len - 1; p > ip; p--) {
  if (*p == ' ' || *p == ',') {
    p++;
    len -= p - ip;
    ip = p;
    break;
  }
}

Het begint helemaal rechts van de koptekststring en zodra het een spatie of komma ziet, stopt het met zoeken en plakt het deel rechts van de spatie of komma in de IP-variabele. Dus, het behandelt het meest recente proxy-adres als de originele klant adres.

Het speelt niet leuk volgens de specificaties; dit is het gevaar om het niet in pijnlijk voor de hand liggende bewoordingen in een RFC uiteen te zetten.

terzijde: Het is moeilijk om zelfs maar een goede primaire bron te vinden op het formaat, dat oorspronkelijk werd gedefinieerd door Squid - een graven door hun documentatie bevestigt de bestelling; uiterst links is de originele client, meest recent is de meest recente append. Ik ben erg in de verleiding om er een toe te voegen [citaat nodig] naar die wikipedia-pagina. een anonieme bewerking lijkt de autoriteit van het internet op dit gebied te zijn.

Als het mogelijk is, kunt u uw tussenliggende proxy's laten stoppen met het toevoegen van zichzelf aan het einde van de koptekst, en alleen het echte klantadres achterlaten?


9
2017-09-22 22:08



Bedankt voor het antwoord, @Shane. Sterker nog, bij het bereiken van nginx, een X-Forwarded-For bestaat al. (het is het juiste IP-adres van de client) nginx zelf gaat dan verder met het toevoegen van het IP-adres van onze load balancer (de vorige hop) aan de X-Forwarded-For header. (waarschijnlijk toevoegend wat het ziet als het "externe adres") Als het dat simpelweg niet deed, zou ik in staat zijn om gewoon de X-Forwarded-For kop als voorheen. (we zijn onlangs gemigreerd naar nginx) - Kirk Woll
@Kirk Dus, wanneer nginx de header krijgt, is dit gewoon het adres van de oorspronkelijke klant? Maar wanneer het wordt verwerkt, wordt het toegevoegd aan de header van de verbindende proxyserver? Dat klopt niet - de enige keer dat het die header zou raken, is wanneer hij via a de verbinding met een andere proxy verzendt proxy_pass - en zelfs dan alleen met proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; op zijn plaats. - Shane Madden♦
Zelfs de W3C krijgt dit verkeerd: hun documentatie geeft aan dat "proxies" het IP-adres van de initiatiefnemer van het verzoek moeten toevoegen aan de einde van een door komma's gescheiden lijst in een X-Forwarded-For HTTP-headerveld ", moet dit worden vermeld begin. - Ian Kemp
@IanKemp, nee, einde is juist. Aan de serverzijde van een proxy, de initiatiefnemer van het verzoek (d.w.z. TCP aanvraag) is de vorige proxy (indien aanwezig). Die vorige proxy verzendt mogelijk al een X-Forwarded-For header met mogelijk het originele klantadres aan de linkerkant en eventueel eventuele voorgaande proxy's. Dus de proxy die op dat moment aan het werk is, zou de vorige proxy (= initiator) aan het einde van die lijst toevoegen en de aldus toegevoegde augmented server gebruiken X-Forwarded-For kop naar de volgende stroomopwaartse hop. Toegegeven, ze hadden een meer voor de hand liggende bewoording kunnen kiezen. - blubberdiblub


X-Real-IP is het IP-adres van de daadwerkelijke client waarmee de server praat (de "echte" client van de server), die in het geval van een proxiede verbinding de proxyserver is. Daarom zal X-Real-IP het laatste IP-adres in de X-Forwarded-For-header bevatten.


4
2017-09-22 21:07



OK, maar dat is voor mij gewoon nooit nuttige informatie. Ik wil het originele IP-adres van de klant krijgen - dat is cruciaal, en volgens alles wat ik heb gelezen, het doel van deze headers. Waarom zou ik het IP-adres van onze proxyservers willen weten? - Kirk Woll
Als het niet nuttig voor je is, dan is het niet voor jou. Niemand dwingt je om X-Real-IP te gebruiken. Als u het IP-adres van de gebruiker in uw toepassing nodig heeft, laat uw toepassing dan X-Forwarded-For parsen (wat niet altijd betrouwbaar is omdat er een aantal proxies zijn (internetbeveiligingsapparaat / firewalls) die geen X-Forwarded- Voor). In de context van nginx is X-Forwarded-For niet belangrijk omdat het toch niet met die clients praat, afgezien van de laatste invoer (de X-Real-IP) die de client van nginx is. Als u het niet nodig hebt, stel het dan niet in, schakel het niet uit of negeer het gewoon: / - user558061
Nee, ik bedoel, waarom zou ik dat doen? X-Real-IP het IP-adres van mijn eigen proxyserver retourneren ooit wees nuttig? - Kirk Woll
Geweldig .. antwoord man. Ik was op zoek naar deze precieze informatie. Ik moet met een ncat-server op mijn proxyserver praten, dus ik heb dit meteen nodig. - Yugal Jindle