Je sais qu'il existe une pléthore d'en- têtes de variables $ _SERVER disponibles pour la récupération d'adresse IP. Je me demandais s'il y avait un consensus général sur la façon de récupérer le plus précisément la véritable adresse IP d'un utilisateur (sachant bien qu'aucune méthode n'est parfaite) en utilisant lesdites variables?
J'ai passé un certain temps à essayer de trouver une solution approfondie et j'ai trouvé le code suivant basé sur un certain nombre de sources. Je serais ravi que quelqu'un puisse faire des trous dans la réponse ou éclaircir quelque chose de plus précis.
la modification inclut des optimisations de @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;
}
Mots d'avertissement (mise à jour)
REMOTE_ADDR
représente toujours la source la plus fiable d'une adresse IP. Les autres $_SERVER
variables mentionnées ici peuvent être usurpées par un client distant très facilement. Le but de cette solution est de tenter de déterminer l'adresse IP d'un client assis derrière un proxy. Pour vos besoins généraux, vous pouvez envisager de l'utiliser en combinaison avec l'adresse IP renvoyée directement par les deux $_SERVER['REMOTE_ADDR']
et de les stocker.
Pour 99,9% des utilisateurs, cette solution répondra parfaitement à vos besoins. Il ne vous protégera pas du 0,1% d'utilisateurs malveillants qui cherchent à abuser de votre système en injectant leurs propres en-têtes de demande. Si vous comptez sur les adresses IP pour quelque chose de mission critique, recourez à REMOTE_ADDR
et ne vous embêtez pas à répondre à ceux qui se trouvent derrière un proxy.