nginx real_ip_header e X-Forwarded-For sembra sbagliato


59

La descrizione di Wikipedia dell'intestazione HTTP X-Forwarded-Forè:

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

La documentazione nginx per la direttiva real_ip_headerrecita, in parte:

Questa direttiva imposta il nome dell'intestazione utilizzata per il trasferimento dell'indirizzo IP sostitutivo.
Nel caso di X-Forwarded-For, questo modulo utilizza l' ultimo ip nell'intestazione X-Forwarded-For per la sostituzione. [Enfasi mia]

Queste due descrizioni sembrano in contrasto tra loro. Nel nostro scenario, l' X-Forwarded-Forintestazione è esattamente come descritta: l'indirizzo IP "reale" del client è la voce più a sinistra. Allo stesso modo, il comportamento di nginx è di usare il valore più giusto - che, ovviamente, è solo uno dei nostri server proxy.

La mia comprensione X-Real-IPè che si suppone che debba essere utilizzato per determinare l' indirizzo IP del client effettivo , non il proxy. Mi sto perdendo qualcosa o è un bug in nginx?

E, a parte questo, qualcuno ha qualche suggerimento su come fare in modo che l' X-Real-IPintestazione visualizzi il valore più a sinistra , come indicato dalla definizione di X-Forwarded-For?

Risposte:


97

Credo che la chiave per risolvere i guai di X-Forwarded-For quando più IP sono concatenati è l'opzione di configurazione introdotta di recente real_ip_recursive(aggiunta in nginx 1.2.1 e 1.3.0). Dai documenti di riapparizione di nginx :

Se la ricerca ricorsiva è abilitata, un indirizzo client originale che corrisponde a uno degli indirizzi attendibili viene sostituito dall'ultimo indirizzo non attendibile inviato nel campo dell'intestazione della richiesta.

nginx stava afferrando l'ultimo indirizzo IP nella catena per impostazione predefinita perché quello era l'unico che si riteneva attendibile. Ma con il nuovo real_ip_recursiveabilitato e con più set_real_ip_fromopzioni, è possibile definire più proxy attendibili e verrà recuperato l'ultimo IP non attendibile.

Ad esempio, con questa configurazione:

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;

E un'intestazione X-Forwarded-For che risulta in:

X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1

nginx ora sceglierà 123.123.123.123 come indirizzo IP del client.

Per quanto riguarda il motivo per cui nginx non si limita a scegliere l'indirizzo IP più a sinistra e richiede di definire in modo esplicito i proxy attendibili, è per impedire lo spoofing IP semplice.

Diciamo che il vero indirizzo IP di un client è 123.123.123.123. Diciamo anche che il client non va bene e stanno cercando di falsificare il loro indirizzo IP 11.11.11.11. Inviano una richiesta al server con questa intestazione già in atto:

X-Forwarded-For: 11.11.11.11

Poiché i proxy inversi aggiungono semplicemente IP a questa catena X-Forwarded-For, diciamo che finisce così quando nginx ci arriva:

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

Se prendessi semplicemente l'indirizzo più a sinistra, ciò consentirebbe al client di falsificare facilmente il proprio indirizzo IP. Ma con l'esempio sopra nginx config, nginx si fiderà solo degli ultimi due indirizzi come proxy. Ciò significa che nginx sceglierà correttamente 123.123.123.123come indirizzo IP, nonostante quell'IP falsificato sia in realtà il più a sinistra.


2
Grazie mille per questo, mi ha davvero aiutato. Questa dovrebbe essere la risposta accettata.
José F. Romaniello,

1
Di default real_ip_header sembra essere X-Real-IP secondo nginx.org/en/docs/http/ngx_http_realip_module.html Significa che un utente malintenzionato può semplicemente inviare una richiesta con X-Real-IP casuale e che verrà usato come $ remote_addr in nginx (e forse anche passato all'applicazione)?
Gansbrest,

@gansbrest No, perché set_real_ip_from limita gli host fidati.
El Yobo,

9

L'analisi X-Forwarded-Fordell'intestazione è effettivamente imperfetta nel modulo nginx real_ip.

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

Inizia all'estrema destra della stringa di intestazione e non appena vede uno spazio o una virgola, smette di cercare e inserisce la parte a destra dello spazio o della virgola nella variabile IP. Quindi, tratta l' indirizzo proxy più recente come l' indirizzo client originale .

Non sta giocando bene secondo le specifiche; questo è il pericolo di non averlo spiegato in termini dolorosamente ovvi in ​​un RFC.

A parte: è difficile persino trovare una buona fonte primaria nel formato, che originariamente è stato definito da Squid - uno scavo attraverso la loro documentazione conferma l'ordinamento; l'estrema sinistra è il client originale, l'estrema destra è l'appendice più recente. Sono fortemente tentato di aggiungere una [citazione necessaria] a quella pagina di Wikipedia. Una modifica anonima sembra essere l'autorità di Internet sull'argomento.

Se possibile, puoi fare in modo che i tuoi proxy intermedi smettano di aggiungersi alla fine dell'intestazione, lasciandolo solo con il vero indirizzo client?


Grazie per la risposta, @Shane. In effetti, quando si raggiunge nginx, X-Forwarded-Foresiste già un . (è l'indirizzo IP client corretto) nginx stesso procede quindi ad aggiungere l'indirizzo IP del nostro bilanciamento del carico (l'hop precedente) all'intestazione X-Forwarded-For. (presumibilmente aggiungendo quello che vede come "indirizzo remoto") Se semplicemente non lo facesse, sarei in grado di usare l' X-Forwarded-Forintestazione come prima. (Di recente stiamo migrando verso Nginx)
Kirk Woll,

@Kirk Quindi, quando nginx ottiene l'intestazione, è solo l'indirizzo del cliente originale? Ma quando lo sta elaborando, viene aggiunto nell'intestazione del server proxy di connessione? Ciò non si somma - l'unica volta che dovrebbe toccare quell'intestazione è quando sta inviando la connessione a un altro proxy tramite un proxy_pass- e anche allora, solo con proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;in posizione.
Shane Madden

Anche il W3C sbaglia questo : la loro documentazione afferma che "i proxy dovrebbero aggiungere l'indirizzo IP dell'iniziatore della richiesta alla fine di un elenco separato da virgole in un campo di intestazione X-Forwarded-For HTTP", dovrebbe indicare l' inizio .
Ian Kemp,

3
@IanKemp, no, la fine è corretta. Sul lato server di un proxy, l' iniziatore della richiesta (ovvero la richiesta TCP ) è il proxy precedente (se presente). Quel proxy precedente probabilmente già invia X-Forwarded-Forun'intestazione con possibilmente l'indirizzo client originale a sinistra e probabilmente tutti i proxy precedenti aggiunti a quello. Quindi il proxy attualmente in servizio aggiungerebbe il proxy precedente (= iniziatore) alla fine di tale elenco e servirebbe l' X-Forwarded-Forintestazione così aumentata al successivo hop a monte. Certo, avrebbero potuto scegliere una formulazione più ovvia.
Blubberdiblub,

5

X-Real-IP è l'indirizzo IP del client effettivo con cui sta parlando il server (il client "reale" del server), che, nel caso di una connessione proxy, è il server proxy. Ecco perché X-Real-IP conterrà l'ultimo IP nell'intestazione X-Forwarded-For.


1
OK, ma, per me, non sono informazioni mai utili. Voglio ottenere l'indirizzo IP originale del client, che è cruciale e, in base a tutto ciò che ho letto, lo scopo di queste intestazioni. Perché dovrei voler sapere l'indirizzo IP dei nostri server proxy?
Kirk Woll,

Se non è utile per te, allora non è per te. Nessuno ti sta obbligando a usare X-Real-IP. Se hai bisogno dell'IP dell'utente nella tua applicazione, fai in modo che l'applicazione analizzi X-Forwarded-For (che non è sempre affidabile perché ci sono alcuni proxy (appliance di sicurezza Internet / firewall) che non impostano X-Forwarded- Per). Nel contesto di nginx, X-Forwarded-For non è importante perché non parla comunque con quei client, a parte l'ultima voce (X-Real-IP) che è il client di nginx. Se non ti serve, non impostarlo, disinserirlo o semplicemente ignorarlo: /
user558061

2
No, ciò che intendo è, perché la X-Real-IPrestituzione dell'indirizzo IP del mio server proxy sarebbe mai stata utile?
Kirk Woll,

Ottimo ... rispondi amico. Stavo cercando queste informazioni precise. Devo parlare con un server ncat sul mio server proxy, quindi ho bisogno di questo al volo.
Yugal Jindle,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.