Frage nginx real_ip_header und X-Forwarded-For scheint falsch


Die Wikipedia-Beschreibung des HTTP-Headers X-Forwarded-For ist:

X-Weitergeleitet-Für: client1, proxy1, proxy2, ...

Die nginx-Dokumentation für die Richtlinie real_ip_header liest, teilweise:

Diese Direktive legt den Namen des Headers fest, der für die Übertragung der Ersatz-IP-Adresse verwendet wird.
  Im Falle von X-Forwarded-For verwendet dieses Modul die zuletzt IP in der X-Forwarded-For-Kopfzeile zum Ersetzen. [Betonung meiner]

Diese beiden Beschreibungen scheinen einander zu widersprechen. In unserem Szenario, der X-Forwarded-For Header ist genau wie beschrieben - die "echte" IP-Adresse des Clients ist der äußerste linke Eintrag. Genauso ist das Verhalten von nginx die Verwendung des Recht-most value - was natürlich nur einer unserer Proxy-Server ist.

Mein Verständnis von X-Real-IP ist, dass es ist soll verwendet werden, um das zu bestimmen tatsächlich Client-IP-Adresse - nicht der Proxy. Fehle ich etwas oder ist das ein Fehler in Nginx?

Und darüber hinaus hat jemand irgendwelche Vorschläge, wie man das macht X-Real-IP Überschrift anzeigen die links-most Wert, wie durch die Definition von angegeben X-Forwarded-For?


49
2017-09-22 20:41


Ursprung




Antworten:


Ich glaube, der Schlüssel zur Lösung von X-Forwarded-For-Problemen, wenn mehrere IPs verkettet sind, ist die kürzlich eingeführte Konfigurationsoption, real_ip_recursive (hinzugefügt in nginx 1.2.1 und 1.3.0). Von dem nginx-docs:

Wenn die rekursive Suche aktiviert ist, wird eine ursprüngliche Clientadresse, die mit einer der vertrauenswürdigen Adressen übereinstimmt, durch die letzte nicht vertrauenswürdige Adresse ersetzt, die im Anforderungsheaderfeld gesendet wurde.

nginx hat standardmäßig die letzte IP-Adresse in der Kette erfasst, da dies die einzige war, von der angenommen wurde, dass sie vertrauenswürdig ist. Aber mit dem Neuen real_ip_recursive aktiviert und mit mehreren set_real_ip_from Optionen können Sie mehrere vertrauenswürdige Proxies definieren und die letzte nicht vertrauenswürdige IP-Adresse abrufen.

Zum Beispiel mit dieser Konfiguration:

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;

Und ein X-Forwarded-For-Header, der zu folgenden Ergebnissen führt:

X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1

nginx wählt nun 123.123.123.123 als IP-Adresse des Clients aus.

Warum Nginx nicht nur die linke IP-Adresse auswählt und Sie explizit vertrauenswürdige Proxies definieren müssen, um ein einfaches IP-Spoofing zu verhindern.

Nehmen wir an, die reale IP-Adresse eines Kunden ist 123.123.123.123. Lassen Sie uns auch sagen, der Client ist nicht gut, und sie versuchen, ihre IP-Adresse zu spoofen 11.11.11.11. Sie senden eine Anfrage an den Server mit diesem Header bereits vorhanden:

X-Forwarded-For: 11.11.11.11

Da Reverse-Proxies einfach IPs zu dieser X-Forwarded-For-Kette hinzufügen, nehmen wir an, dass sie so aussieht, wenn nginx dazu kommt:

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

Wenn Sie einfach die Adresse ganz links greifen, könnte der Client seine IP-Adresse einfach spoofen. Aber mit dem obigen Beispiel nginx config vertraut nginx nur den letzten beiden Adressen als Proxies. Dies bedeutet, dass nginx korrekt auswählen wird 123.123.123.123 als die IP-Adresse, trotz dieser gefälschten IP tatsächlich die am weitesten links.


75
2017-08-03 22:45



Vielen Dank dafür, es hat mir wirklich geholfen. Dies sollte die akzeptierte Antwort sein. - José F. Romaniello
Standardmäßig scheint real_ip_header nach X-Real-IP zu sein nginx.org/en/docs/http/ngx_http_realip_module.html Bedeutet dies, dass böswillige Benutzer einfach eine Anfrage mit zufälliger X-Real-IP senden können und diese als $ remote_addr in nginx verwendet wird (und möglicherweise auch an die Anwendung weitergegeben wird)? - gansbrest
@gansbrest Nein, da set_real_ip_fr die vertrauenswürdigen Hosts begrenzt. - El Yobo


Das Parsen der X-Forwarded-ForHeader ist tatsächlich in der nginx real_ip-Modul fehlerhaft.

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;
  }
}

Es beginnt ganz rechts in der Kopfzeile, und sobald es ein Leerzeichen oder ein Komma sieht, hört es auf zu suchen und hält den Teil rechts vom Leerzeichen oder Komma in der IP-Variablen. Also, es behandelt die neueste Proxyadresse als ursprünglicher Kunde Adresse.

Es spielt nicht nett nach der Spezifikation; das ist die Gefahr, dass es in einem RFC nicht in schmerzlich offensichtlichen Ausdrücken formuliert wird.

Beiseite: Es ist schwer, sogar eine gute primäre Quelle für das Format zu finden, das ursprünglich von Squid definiert wurde - eine Suche durch deren Dokumentation bestätigt die Bestellung; ganz links ist der ursprüngliche Client, ganz rechts ist der letzte Anhang. Ich bin sehr versucht, eine hinzuzufügen [Zitat benötigt] zu dieser Wikipedia-Seite. Ein anonyme Bearbeitung scheint die Autorität des Internets zu diesem Thema zu sein.

Wenn möglich, können Sie Ihre Zwischenproxies aufhören, sich selbst am Ende des Headers hinzuzufügen, nur mit der realen Client-Adresse nur verlassen?


9
2017-09-22 22:08



Danke für die Antwort, @Shane. In der Tat, wenn nginx erreicht, ein X-Forwarded-For ist bereits vorhanden. (es ist die korrekte Client-IP-Adresse) nginx Dann fährt er fort, um die IP - Adresse unseres Load Balancers (der vorherige Hop) an die X-Forwarded-For Header. (vermutlich anhängen, was es als die "entfernte Adresse" sieht) Wenn es das einfach nicht tun würde, wäre ich in der Lage, einfach die X-Forwarded-For Header wie zuvor. (Wir sind kürzlich zu nginx migriert) - Kirk Woll
@Kirk Also, wenn nginx den Header bekommt, ist es nur die Adresse des ursprünglichen Clients? Aber wenn es verarbeitet wird, wird es auf dem Header des verbindenden Proxyservers hinzugefügt? Das summiert sich nicht - die einzige Zeit, die es diesen Header berühren sollte, wenn es die Verbindung zu einem anderen Proxy über eine sendet proxy_pass - und auch dann nur mit proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; an Ort und Stelle. - Shane Madden♦
Selbst das W3C bekommt das falsch: In ihrer Dokumentation heißt es: "Proxies sollten die IP - Adresse des Initiators der Anfrage an die Ende einer kommagetrennten Liste in einem X-Forwarded-For HTTP-Header-Feld "sollte es angeben Anfang. - Ian Kemp
@Iankemp, nein, Ende ist richtig. Auf die Serverseite eines Proxy, der Initiator der Anfrage (d. h. TCP Anfrage) ist der vorherige Proxy (wenn es einen gibt). Dieser vorherige Proxy sendet möglicherweise bereits einen X-Forwarded-For Header mit möglicherweise der ursprünglichen Client-Adresse auf der linken Seite und möglicherweise alle vorhergehenden Proxies, die daran angehängt sind. Der aktuell versorgende Proxy würde also den vorherigen Proxy (= Initiator) am Ende dieser Liste hinzufügen und den so erweiterten Server bedienen X-Forwarded-For Header zum nächsten Upstream-Hop. Zugegeben, sie hätten eine offenere Formulierung wählen können. - blubberdiblub


X-Real-IP ist die IP-Adresse des aktuellen Clients, mit dem der Server kommuniziert (der "echte" Client des Servers), der im Falle einer Proxy-Verbindung der Proxy-Server ist. Aus diesem Grund wird X-Real-IP die letzte IP im Header X-Forwarded-For enthalten.


4
2017-09-22 21:07



OK, aber für mich ist das einfach nie eine nützliche Information. Ich möchte die ursprüngliche IP-Adresse des Clients erhalten - das ist entscheidend und nach allem, was ich gelesen habe, den Zweck dieser Header. Warum sollte ich die IP-Adresse unserer Proxy-Server wissen wollen? - Kirk Woll
Wenn es für dich nicht nützlich ist, dann ist es nicht für dich. Niemand zwingt dich, X-Real-IP zu benutzen. Wenn Sie die IP des Benutzers in Ihrer Anwendung benötigen, dann lassen Sie Ihre Anwendung X-Forwarded-For parsen (was nicht immer zuverlässig ist, da es einige Proxies (Internet Security Appliance / Firewalls) gibt, die X-Forwarded- nicht setzen). Zum). Im Kontext von nginx ist X-Forwarded-For nicht wichtig, da es nicht mit diesen Clients kommuniziert, abgesehen von dem letzten Eintrag (dem X-Real-IP), der der Client von nginx ist. Wenn Sie es nicht brauchen, dann setzen Sie es nicht, heben Sie es auf, oder ignorieren Sie es einfach: / - user558061
Nein, was ich meine ist, warum würde X-Real-IP Rückgabe der IP-Adresse meines eigenen Proxy-Servers je nützlich sein? - Kirk Woll
Großartig ... Antwort Mann. Ich habe nach dieser genauen Information gesucht. Ich muss mit einem Ncat-Server auf meinem Proxy-Server sprechen, also brauche ich das im laufenden Betrieb. - Yugal Jindle