Ich weiß, dass es eine Vielzahl von $ _SERVER- Variablen-Headern gibt, die zum Abrufen von IP-Adressen verfügbar sind. Ich habe mich gefragt, ob es einen allgemeinen Konsens darüber gibt, wie die tatsächliche IP-Adresse eines Benutzers (wohl wissend, dass keine Methode perfekt ist) unter Verwendung dieser Variablen am genauesten abgerufen werden kann.
Ich habe einige Zeit damit verbracht, eine gründliche Lösung zu finden, und habe den folgenden Code basierend auf einer Reihe von Quellen gefunden. Ich würde es lieben, wenn jemand bitte Löcher in die Antwort stechen oder etwas Licht auf etwas vielleicht Genaueres werfen könnte.
Bearbeiten enthält Optimierungen von @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;
}
Warnhinweise (Update)
REMOTE_ADDR
stellt immer noch die zuverlässigste Quelle einer IP-Adresse dar. Die anderen $_SERVER
hier genannten Variablen können von einem Remote-Client sehr einfach gefälscht werden. Mit dieser Lösung soll versucht werden, die IP-Adresse eines Clients zu ermitteln, der sich hinter einem Proxy befindet. Für Ihre allgemeinen Zwecke können Sie dies in Kombination mit der IP-Adresse verwenden, die direkt von $_SERVER['REMOTE_ADDR']
beiden zurückgegeben wird, und beide speichern.
Für 99,9% der Benutzer wird diese Lösung perfekt zu Ihren Anforderungen passen. Es schützt Sie nicht vor 0,1% der böswilligen Benutzer, die Ihr System missbrauchen möchten, indem sie ihre eigenen Anforderungsheader einfügen. Wenn Sie sich für geschäftskritische Zwecke auf IP-Adressen verlassen, REMOTE_ADDR
wenden Sie sich an diejenigen, die hinter einem Proxy stehen , und kümmern Sie sich nicht darum.