So che ci sono moltissime intestazioni di variabili $ _SERVER disponibili per il recupero dell'indirizzo IP. Mi chiedevo se esiste un consenso generale su come recuperare in modo più accurato l'indirizzo IP reale di un utente (ben sapendo che nessun metodo è perfetto) utilizzando tali variabili?
Ho trascorso un po 'di tempo a cercare una soluzione approfondita e ho trovato il seguente codice basato su una serie di fonti. Mi piacerebbe se qualcuno potesse per favore fare buchi nella risposta o fare luce su qualcosa forse più preciso.
modifica include ottimizzazioni da @Alix
/**
* Retrieves the best guess of the client's actual IP address.
* Takes into account numerous HTTP proxy headers due to variations
* in how different ISPs handle IP addresses in headers between hops.
*/
public function get_ip_address() {
// Check for shared internet/ISP IP
if (!empty($_SERVER['HTTP_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_CLIENT_IP']))
return $_SERVER['HTTP_CLIENT_IP'];
// Check for IPs passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// Check if multiple IP addresses exist in var
$iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($iplist as $ip) {
if ($this->validate_ip($ip))
return $ip;
}
}
}
if (!empty($_SERVER['HTTP_X_FORWARDED']) && $this->validate_ip($_SERVER['HTTP_X_FORWARDED']))
return $_SERVER['HTTP_X_FORWARDED'];
if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && $this->validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
return $_SERVER['HTTP_FORWARDED_FOR'];
if (!empty($_SERVER['HTTP_FORWARDED']) && $this->validate_ip($_SERVER['HTTP_FORWARDED']))
return $_SERVER['HTTP_FORWARDED'];
// Return unreliable IP address since all else failed
return $_SERVER['REMOTE_ADDR'];
}
/**
* Ensures an IP address is both a valid IP address and does not fall within
* a private network range.
*
* @access public
* @param string $ip
*/
public function validate_ip($ip) {
if (filter_var($ip, FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4 |
FILTER_FLAG_IPV6 |
FILTER_FLAG_NO_PRIV_RANGE |
FILTER_FLAG_NO_RES_RANGE) === false)
return false;
self::$ip = $ip;
return true;
}
Words of Warning (aggiornamento)
REMOTE_ADDR
rappresenta ancora la fonte più affidabile di un indirizzo IP. Le altre $_SERVER
variabili menzionate qui possono essere facilmente falsificate da un client remoto. Lo scopo di questa soluzione è tentare di determinare l'indirizzo IP di un client seduto dietro un proxy. Per i tuoi scopi generali, potresti considerare di usarlo in combinazione con l'indirizzo IP restituito direttamente da $_SERVER['REMOTE_ADDR']
e memorizzandoli entrambi.
Per il 99,9% degli utenti questa soluzione soddisferà perfettamente le tue esigenze. Non ti proteggerà dallo 0,1% degli utenti malintenzionati che cercano di abusare del tuo sistema iniettando le proprie intestazioni di richiesta. Se si fa affidamento su indirizzi IP per qualcosa di fondamentale, ricorrere REMOTE_ADDR
e non preoccuparsi di provvedere a coloro che stanno dietro un proxy.