HOWTO · PHP
Ottieni l'indirizzo IP dell'utente in PHP
Questo tutorial mostra come ottenere l'indirizzo IP dell'utente in PHP
In questa pagina
Per leggere l’indirizzo di rete associato a una richiesta PHP, parti da $_SERVER['REMOTE_ADDR']. Questo valore identifica il peer che si è connesso al server web. Se davanti all’applicazione c’è un proxy inverso, il peer potrebbe essere il proxy anziché il visitatore. Gli header della richiesta relativi ai proxy si possono usare solo se l’applicazione dispone di una configurazione esplicita che stabilisce quali proxy sono attendibili e verifica quelli che li forniscono.
Leggere l’indirizzo del peer connesso usando $_SERVER['REMOTE_ADDR']
$_SERVER è una superglobale PHP che contiene informazioni sul server e sulla richiesta. L’elemento REMOTE_ADDR contiene l’indirizzo del peer connesso al server che gestisce la richiesta. Con una connessione diretta, di solito è il client che si è connesso. Dietro un bilanciatore del carico o un proxy inverso, spesso è l’indirizzo del proxy. Il valore ricevuto da PHP dipende dalla configurazione del server web e del proxy; quindi non va descritto come se fosse sempre l’indirizzo dell’utente finale.
Per una richiesta locale, il peer può avere l’indirizzo di loopback IPv6 ::1. Gli indirizzi di loopback si riferiscono alla macchina locale: ::1 è l’indirizzo di loopback IPv6, equivalente a 127.0.0.1 in IPv4. Il valore esatto dipende dal server locale e dalla connessione. Consulta questa spiegazione dell’indirizzo di loopback.
L’esempio eseguibile seguente imposta un valore rappresentativo per il server, così la lettura è autonoma. Mantiene display_output impostato su false, quindi legge il valore senza mostrarlo; in un’applicazione, usalo secondo le esigenze della risposta o della registrazione nei log.
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
<?php
$_SERVER['REMOTE_ADDR'] = '::1';
$peerAddress = $_SERVER['REMOTE_ADDR'];
$display_output = false;
if ($display_output) {
echo "The connected peer is: " . $peerAddress . PHP_EOL;
}
?>
Per una richiesta reale, usa il valore $_SERVER['REMOTE_ADDR'] fornito dal server invece di assegnare un valore di esempio. Il riferimento del Manuale PHP alle variabili del server descrive le voci disponibili in $_SERVER.
Interpretare gli header del proxy solo se il proxy è attendibile
PHP può esporre gli header della richiesta come voci di $_SERVER, per esempio HTTP_X_FORWARDED_FOR e HTTP_CLIENT_IP. La loro presenza non dimostra che contengano l’indirizzo del visitatore: un client può inviare valori di header propri e un proxy può conservarli, aggiungerli o sostituirli. In particolare, HTTP_X_FORWARDED_FOR può contenere una catena di indirizzi separati da virgole, non un solo indirizzo. Non scegliere il primo valore e definirlo l’indirizzo reale del client senza applicare le regole di attendibilità documentate per la tua infrastruttura.
Usa un valore inoltrato solo quando il peer connesso corrisponde a un proxy che l’applicazione considera esplicitamente attendibile e quel proxy è configurato per rimuovere o convalidare gli header di inoltro inviati dai client. L’elenco dei proxy attendibili deve corrispondere alla tua installazione: non copiare indirizzi di esempio nelle impostazioni di produzione. Se il peer non è attendibile, usa REMOTE_ADDR. HTTP_CLIENT_IP presenta lo stesso problema di attendibilità e non va trattato come una risposta speciale per le connessioni Internet condivise.
Questo frammento eseguibile rappresenta un’installazione in cui il proxy attendibile sovrascrive X-Forwarded-For con un singolo indirizzo convalidato. Sostituisci l’indirizzo del proxy di esempio e la politica di convalida con i valori definiti per la tua infrastruttura. Per questi valori rappresentativi, stampa l’indirizzo inoltrato selezionato; non implementa l’analisi di una catena di più proxy.
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
<?php
$_SERVER['REMOTE_ADDR'] = '192.0.2.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '198.51.100.24';
$trustedProxies = ['192.0.2.10'];
$peerAddress = $_SERVER['REMOTE_ADDR'];
if (in_array($peerAddress, $trustedProxies, true)
&& isset($_SERVER['HTTP_X_FORWARDED_FOR'])
&& filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP) !== false) {
$clientAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$clientAddress = $peerAddress;
}
echo "Selected address: " . $clientAddress . PHP_EOL;
?>
Selected address: 198.51.100.24
La documentazione di filter_var() descrive la funzione di convalida usata qui. Verificare che una stringa sia un indirizzo IP non dimostra che provenga da una fonte attendibile: questa decisione dipende dal controllo del peer e dalla configurazione del proxy. Se il proxy inoltra una catena, usa un framework o codice esaminato con attenzione che percorra la catena secondo le precise regole di attendibilità dei proxy della tua installazione.
Usare un’espressione condizionale per un fallback compatto
Un blocco leggibile if/elseif/else è in genere più facile da verificare, soprattutto quando include un controllo di attendibilità del proxy. Un’espressione condizionale può esprimere la stessa scelta in modo compatto, ma non rende sicuro un header non attendibile. L’esempio eseguibile seguente verifica l’attendibilità del proxy e applica la stessa politica descritta sopra: un solo indirizzo, sovrascritto dal proxy. I valori del server sono rappresentativi; l’esempio stampa l’indirizzo inoltrato selezionato.
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
<?php
$_SERVER['REMOTE_ADDR'] = '192.0.2.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '198.51.100.24';
$trustedProxies = ['192.0.2.10'];
$peerAddress = $_SERVER['REMOTE_ADDR'];
$forwardedAddress = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
$clientAddress = in_array($peerAddress, $trustedProxies, true)
&& filter_var($forwardedAddress, FILTER_VALIDATE_IP) !== false
? $forwardedAddress
: $peerAddress;
echo "Selected address: " . $clientAddress . PHP_EOL;
?>
Selected address: 198.51.100.24
L’ordine del fallback è intenzionale: accetta l’indirizzo inoltrato convalidato solo quando il peer connesso appartiene all’elenco dei proxy attendibili; altrimenti mantiene l’indirizzo del peer connesso. Le parentesi possono rendere più chiare le espressioni condizionali annidate, ma un ternario annidato è più difficile da mantenere e non sostituisce i controlli di attendibilità. Mantieni coerenti il comportamento degli header del proxy e la lista di indirizzi consentiti dell’applicazione, così un client non può far considerare attendibile un header inviato da lui.