In PHP, è molto facile rilevare un indirizzo IP ad un livello base:
echo 'Sai, il tuo indirizzo IP è' . $_SERVER['INDIRIZZO REMOTO'] . '?';
Attenzione: Ottenere l'indirizzo IP come chiave del campo
$_SERVER['REMOTE_ADDR']
è possibile solo se PHP è stato chiamato dal browser. In modalità CLI (per esempio, in esecuzione da terminale con cron), l'indirizzo IP non è disponibile (questo ha senso, dato che non viene fatta alcuna richiesta di rete).
Dopo molti anni di sviluppo, alla fine sono rimasto con questa implementazione:
function getIp(): string{if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) { // Supporto Cloudflare$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];} elseif (isset($_SERVER['INDIRIZZO REMOTO']) === true) {$ip = $_SERVER['INDIRIZZO REMOTO'];if (preg_match('/^(?:127|10)\.0\.0\.[12]?\d{1,2}$/', $ip)) {if (isset($_SERVER['HTTP_X_REAL_IP'])) {$ip = $_SERVER['HTTP_X_REAL_IP'];} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];}}} else {$ip = '127.0.0.1';}if (in_array($ip, ['::1', '0.0.0.0', 'localhost'], true)) {$ip = '127.0.0.1';}$filter = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);if ($filter === false) {$ip = '127.0.0.1';}return $ip;}
Molto meglio, allora:
echo 'Sai, il tuo indirizzo IP è' . getIp() . '?';
Se l'IP può essere rilevato direttamente, o è solo IPv6, o è in modalità CLI (ad esempio cron), restituisce 127.0.0.1
(localhost).
Le implementazioni che tengono conto degli header X-Forwarded-For
e X-Real-IP
sono estremamente pericolose direttamente in PHP, perché i dati possono essere facilmente modificati e un attaccante può spoofare un falso indirizzo IP per, ad esempio, visualizzare l'amministrazione o attivare la modalità Debug del sito (Nette Tracy). D'altra parte, dobbiamo accettare alcune richieste proxy (per esempio, quando proxiamo il traffico attraverso Cloudflare, o quando si eseguono Apache e Ngnix sulla stessa macchina, quando sono chiamati localmente subito dopo l'altro).
Nel caso di accesso diretto dell'utente al server, c'è solo una soluzione corretta, ed è quella di assicurarsi su Apache (tramite l'estensione RemoteIP
) e su Nginx tramite l'estensione remote_ip
che X-Forwarded-For
sia impostato dall'effettivo indirizzo IP del visitatore, e che l'indirizzo IP non possa essere impostato con un header HTTP.
Il campo $_SERVER['REMOTE_ADDR']
ottiene automaticamente l'indirizzo IP corretto (cioè l'indirizzo IP da cui la richiesta è arrivata direttamente a PHP) e non dobbiamo occuparcene.
Succede spesso che un utente acceda attraverso un proxy. Poi l'indirizzo IP effettivo è memorizzato nella variabile $_SERVER['HTTP_X_FORWARDED_FOR']
.
Questo caso può verificarsi, per esempio, quando il routing sul server è risolto usando il metodo Ngnix -> Apache -> PHP
, dove Ngnix
serve come reverse proxy prima di Apache
. In questo caso, PHP vede solo l'indirizzo IP all'interno della rete interna (di solito della forma 127.0.0.*
).
Per esempio, il servizio Cloudflare può comportarsi in questo modo, e bisogna fare attenzione se stiamo lavorando con l'indirizzo IP dell'utente reale o del proxy. Per me, il modo migliore è usare la funzione getIp()
menzionata all'inizio di questo articolo. Possiamo assicurare il rilevamento di Cloudflare verificando l'esistenza della chiave $_SERVER['HTTP_CF_CONNECTING_IP']
, che viene trasmessa automaticamente in ogni richiesta proxy.
Dipende dall'indirizzo IP che avete a disposizione.
ip2long
è usata per questo,Se il tuo server di database non supporta direttamente un tipo di dati per l'indirizzo IP, ti consiglio di memorizzare l'indirizzo IP come varchar(39)
, dove entrambe le versioni si adattano a una stringa e sono leggibili.
Quando si memorizza l'indirizzo IP, considerare se ha senso memorizzare anche il nome di dominio rilevato dalla funzione
gethostbyaddr
. Quando si elencano e si cercano, non si possono scoprire i nomi perché ci vuole molto tempo e possono cambiare nel tempo.
La soluzione ideale è quella di creare una lista di indirizzi IP bloccati e confrontare questa lista con l'indirizzo IP corrente su ogni richiesta. Se gli indirizzi corrispondono, la richiesta sarà fermata immediatamente.
$blackList = ['first-ip','druha-ip',];if (\in_array(getIp(), $blackList, true) === true) {echo 'Purtroppo il tuo indirizzo IP è bloccato :-(';die; // Richiesta di uscita}
L'esempio presuppone un'implementazione della funzione getIp()
come nell'esempio precedente.
Una soluzione più potente è controllare l'occorrenza dell'indice nell'array:
$blackList = ['first-ip' => true,'druha-ip' => true,];if (isset($blackList[getIp()]) === true) {echo 'Purtroppo il tuo indirizzo IP è bloccato :-(';die; // Richiesta di uscita}
L'indirizzo IP del server è solitamente memorizzato nel campo $_SERVER['SERVER_ADDR']
e il suo nome può essere ottenuto con il costrutto gethostbyaddr($_SERVER['SERVER_ADDR'])
.
Tuttavia, se il concetto Ngnix -> Apache -> PHP
è usato e Ngnix
è nel ruolo di un reverse proxy, il vero indirizzo IP del server non viene visualizzato.
In questo caso, il nome del server può essere trovato nel campo $_SERVER['SERVER_NAME']
, o usando la funzione php_uname('n')
. Documentazione ufficiale della funzione uname.
Possiamo quindi usare questo trucco per trovare l'indirizzo IP pubblico del server: gethostbyname(php_uname('n'))
.
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu:
Články píše Jan Barášek © 2009-2023 | Kontakt | Mapa webu
Status | Aktualizováno: ... | it