Je sais qu'il y a une pléthore de $_SERVER variables en-têtes disponibles pour l'extraction de l'adresse IP. Je me demandais si il y a un consensus général quant à la façon la plus précise de récupérer un utilisateur de l'adresse IP réelle (sachant bien aucune méthode n'est parfaite) utilisation de variables?
J'ai passé du temps à essayer de trouver un remaniement en profondeur de la solution et est venu avec le code suivant, basé sur un certain nombre de sources. J'aimerais si quelqu'un pourrait s'il vous plaît faire des trous dans la réponse ou de jeter un peu de lumière sur quelque chose peut-être plus exact.
edit comprend des améliorations 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;
}
Paroles d'Avertissement (mise à jour)
REMOTE_ADDR
représente encore la plus fiable source d'une adresse IP. Les autres $_SERVER
variables mentionnées ici peuvent être usurpée par un client à distance 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 fins générales, vous pouvez envisager d'utiliser cette combinaison avec l'adresse IP renvoyée directement à partir de $_SERVER['REMOTE_ADDR']
et de stocker à la fois.
Pour 99,9% des utilisateurs de cette solution permettra de répondre à vos besoins parfaitement. Il ne sera pas vous protéger contre les 0,1% des utilisateurs malveillants qui cherchent à abuser de votre système en injectant leurs propres en-têtes de requête. Si en s'appuyant sur les adresses IP pour quelque chose d'essentiel à la mission, le recours à des REMOTE_ADDR
et ne pas la peine de restauration pour ceux qui sont derrière un proxy.