2013-08-16 14 views
19

Su Heroku Cedar, volevo ottenere l'IP del client. Primo tentativo:Ottieni l'indirizzo IP reale del client su Heroku

ENV['REMOTE_ADDR'] 

Questo non funziona, ovviamente, perché tutte le richieste vengono passate tramite proxy. Quindi l'alternativa era quella di usare:

ENV['HTTP_X_FORWARDED_FOR'] 

Ma questo non è abbastanza sicuro, vero?

Se contiene solo un valore, prendo questo. Se contiene più di un valore (separati da virgola), potrei prendere il primo.

Ma cosa succede se qualcuno manipola questo valore? Non posso fidarmi di ENV['HTTP_X_FORWARDED_FOR'] come ho potuto con ENV['REMOTE_ADDR']. E non c'è nessuna lista di proxy fidati che potrei usare, neanche io.

Ma ci deve essere in qualche modo per ottenere in modo affidabile l'indirizzo IP del client, sempre. Ne conosci uno?

In their docs, Heroku descrive che X-Forwarded-For è "l'indirizzo IP di origine del client che si connette al router Heroku".

Sembra che Heroku possa sovrascrivere lo X-Forwarded-For con l'IP remoto di origine. Ciò impedirebbe spoofing, giusto? Qualcuno può verificare questo?

+0

Mi dispiace, ma che lingua è? Se non è Python, come faccio a farlo in python? – Cubetastic

risposta

26

Da Jacob, direttore della sicurezza di Heroku al momento:

Il router non sovrascrive X-Forwarded-For, ma non garantisce che la vera origine sarà sempre l'ultima vocenella lista.

Ciò significa che, se si accede a un app Heroku in modo normale, sarà solo vedere il tuo indirizzo IP nel X-Forwarded-For intestazione:

$ curl http://httpbin.org/ip 
{ 
    "origin": "123.124.125.126", 
} 

Se si tenta di falsificare l'IP, il presunto l'origine è riflessa, ma - in modo critico - così è il tuo vero IP. Ovviamente, questo è tutto quello che dobbiamo, quindi non c'è una soluzione chiara e sicura per ottenere l'indirizzo IP del client su Heroku:

$ curl -H"X-Forwarded-For: 8.8.8.8" http://httpbin.org/ip 
{ 
    "origin": "8.8.8.8, 123.124.125.126" 
} 

Questo è esattamente l'opposto di what is described on Wikipedia, tra l'altro.

applicazione PHP:

function getIpAddress() { 
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { 
     $ipAddresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); 
     return trim(end($ipAddresses)); 
    } 
    else { 
     return $_SERVER['REMOTE_ADDR']; 
    } 
} 
+0

https://devcenter.heroku.com/articles/http-routing non entra nel dettaglio del tuo post, ma potrebbe essere interessante per le persone che vogliono verificare se il comportamento è cambiato. La cosa bella qui è che il middleware Rails RemoteIp dovrebbe funzionare correttamente, restituendo l'ultimo IP affidabile, che sarà il client o qualsiasi proxy non affidabile che hanno attraversato, senza la necessità di configurare alcun indirizzo proxy di Heroku. – nruth

+0

Non penso che l'esempio che date sia il contrario di ciò che dice wikipedia (almeno ora). Il client si connette a heroku con 8.8.8.8 nell'intestazione, essenzialmente fingendo che si tratti di un proxy che inoltra una richiesta da 8.8.8.8, quindi heroku aggiunge l'IP della connessione che riceve alla lista. O nel loro esempio di lista, una richiesta normale sarà [client], e una falsificata sarà [fakeclient, client]. Non ci sono IP proxy inseriti perché Heroku utilizza solo 1 proxy. – nruth

+0

@nruth Quello che intendevo è che Wikipedia dice "il più a sinistra è il client originale" mentre Heroku dice "la vera origine sarà sempre l'ultima voce nella lista". – caw

3

Non si può mai davvero fidarsi di qualsiasi informazione proveniente dal cliente. È più una questione di chi ti fidi e come lo verifichi. Persino Heroku può essere influenzato per fornire un valore errato HTTP_X_FORWARDED_FOR se ha un bug nel loro codice, o viene hackerato in qualche modo. Un'altra opzione potrebbe essere un'altra macchina di Heroku che si collega al server internamente e bypassando del tutto il proxy mentre simulando REMOTE_ADDR e/o HTTP_X_FORWARDED_FOR.

La migliore risposta qui dipenderà da ciò che stai cercando di fare. Se stai provando a verificare i tuoi clienti, un certificato sul lato client potrebbe essere una soluzione più appropriata. Se tutto ciò di cui hai bisogno per l'IP è geo-localizzazione, fidarti dell'input potrebbe essere abbastanza buono. Nel peggiore dei casi, qualcuno falsificherà la posizione e otterrà il contenuto sbagliato ... Se hai un caso d'uso diverso, ci sono molte altre soluzioni tra questi due estremi.

+1

Grazie! Sto solo chiedendo perché Heroku _chiude_ il reale IP del cliente.Questo è solo l'IP dal quale il proxy di Heroku ha ricevuto la richiesta. Se _that_ è di nuovo un proxy, non dobbiamo preoccuparcene. Questa è la situazione normale che avresti anche con 'REMOTE_ADDR' quando il client è dietro un proxy. Il fatto che Heroku sia hackerato o che abbia un bug nel codice è un'eccezione e non dovremmo nemmeno preoccuparcene. Perché non possiamo farci nulla. Ma se Heroku avesse appena _overwrite_ il 'HTTP_X_FORWARDED_FOR' avremmo sempre saputo il reale IP del client, che avremmo normalmente con' REMOTE_ADDR'. Destra? – caw

+0

Sì, è corretto. Un po 'di più su questo è disponibile su [Wikipedia] (http://en.wikipedia.org/wiki/X-Forwarded-Per). – kichik

19

Io lavoro nel reparto di assistenza di Heroku e hanno trascorso un po 'di tempo a discutere di questo con i nostri ingegneri di routing. Volevo pubblicare alcune informazioni aggiuntive per chiarire alcune cose su cosa sta succedendo qui.

L'esempio fornito nella risposta sopra ha avuto l'IP del client visualizzato per ultima coincidenza e questo non è realmente garantito. Il motivo per cui non è stato il primo è perché la richiesta di origine ha affermato che stava inoltrando per l'IP specificato nell'intestazione X-Forwarded-For. Quando il router Heroku ha ricevuto la richiesta, ha semplicemente aggiunto l'IP che si collegava direttamente all'elenco X-Forwarded-For dopo quello che era stato iniettato nella richiesta. Il nostro router aggiunge sempre l'IP collegato all'ADB di AWS di fronte alla nostra piattaforma come ultimo IP nell'elenco. Questo IP potrebbe essere quello originale (e nel caso in cui vi sia un solo IP, è quasi certamente), ma nell'istante in cui vi sono più IP concatenati, tutte le scommesse sono disattivate. La convenzione è sempre quella di aggiungere l'ultimo IP della catena alla fine della lista (che è ciò che facciamo), ma in qualsiasi punto della catena tale catena può essere modificata e possono essere inseriti diversi IP. In quanto tale, l'unico IP affidabile (dal punto di vista della nostra piattaforma) è l'ultimo IP nell'elenco.

Per illustrare, diciamo che qualcuno avvia una richiesta e aggiunge arbitrariamente 3 indirizzi IP aggiuntivi per l'intestazione X-Forwarded-For:

curl -H "X-Forwarded-For: 12.12.12.12,15.15.15.15,4.4.4.4" http://www.google.com 

Immaginate IP di questa macchina era 9.9.9.9 e che doveva passare attraverso un proxy (ad es. un proxy universitario di livello universitario). Diciamo che il proxy ha avuto un IP di 2.2.2.2. Supponendo che non fosse configurato per rimuovere le intestazioni X-Forwarded-For (che probabilmente non sarebbe), si limiterebbe a virare l'IP 9.9.9.9 alla fine dell'elenco e passare la richiesta a Google. A questo punto, l'intestazione sarebbe simile a questa:

X-Forwarded-For: 12.12.12.12,15.15.15.15,4.4.4.4,9.9.9.9 

Tale richiesta sarà poi passare attraverso endpoint di Google, che aggiungerà IP del proxy universitaria di 2.2.2.2, quindi l'intestazione finalmente questo aspetto nei registri di Google :

X-Forwarded-For: 12.12.12.12,15.15.15.15,4.4.4.4,9.9.9.9,2.2.2.2 

Quindi, qual è l'IP del client? È impossibile dirlo dal punto di vista di Google. In realtà, l'IP del client è 9.9.9.9. L'ultimo IP elencato è 2.2.2.2 e il primo è 12.12.12.12. Tutto ciò che Google potrebbe sapere è che l'IP 2.2.2.2 è sicuramente corretto perché quello era l'IP effettivamente connesso al loro servizio, ma non saprebbero se quello era il client iniziale per la richiesta o meno dai dati disponibili. Allo stesso modo, quando in questa intestazione c'è un solo IP, questo è l'IP direttamente connesso al nostro servizio, quindi sappiamo che è affidabile.

Dal punto di vista pratico, questo IP sarà probabilmente affidabile maggior parte del tempo (perché la maggior parte delle persone non saranno preoccuparsi di spoofing loro IP). Sfortunatamente, è impossibile prevenire questo tipo di spoofing e quando una richiesta arriva al router Heroku, è impossibile per noi sapere se gli IP in una catena X-Forwarded-For sono stati manomessi o meno.

Tutti i problemi di affidabilità a parte, queste catene IP devono sempre essere lette da sinistra a destra. Il client IP dovrebbe essere sempre l'IP più a sinistra.

+2

Ho seguito fino all'ultimo paragrafo. Dovrebbe questo dire che le catene IP dovrebbero essere lette da destra a sinistra e che l'IP del client dovrebbe essere l'IP più giusto? – Aaron

+0

L'IP client è l'IP più a sinistra. La convenzione è che gli IP aggiuntivi vengono aggiunti all'elenco mentre vengono rilevati, quindi il primo IP nell'elenco dovrebbe essere l'IP del client che si desidera nella maggior parte dei casi. Altri IP nell'elenco sono intermedi. Tieni presente che gli IP nell'elenco possono essere modificati arbitrariamente in qualsiasi punto della catena di richieste, quindi non sei garantito che l'IP sia corretto. –

+0

Quindi nell'esempio precedente sarebbe '12.12.12.12' essere considerato IP del client anche se è' 9.9.9.9' perché hanno intenzionalmente aggiunto gli IP aggiuntivi all'intestazione? – Aaron

Problemi correlati