如何从访问者获得真正的 IP?

我使用这个 PHP 代码来获取访问者的 IP 地址:

<?php echo $_SERVER['REMOTE_ADDR']; ?>

但是,我不能从访问者 当他们使用代理服务器时得到真正的 IP 地址。在这种情况下,有没有办法获得访问者的 IP 地址?

316637 次浏览

Proxies may send a HTTP_X_FORWARDED_FOR header but even that is optional.

Also keep in mind that visitors may share IP addresses; University networks, large companies and third-world/low-budget ISPs tend to share IPs over many users.

Try this php code.

<?PHP


function getUserIP()
{
// Get real visitor IP behind CloudFlare network
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
$_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
$client  = @$_SERVER['HTTP_CLIENT_IP'];
$forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
$remote  = $_SERVER['REMOTE_ADDR'];


if(filter_var($client, FILTER_VALIDATE_IP))
{
$ip = $client;
}
elseif(filter_var($forward, FILTER_VALIDATE_IP))
{
$ip = $forward;
}
else
{
$ip = $remote;
}


return $ip;
}




$user_ip = getUserIP();


echo $user_ip; // Output IP address [Ex: 177.87.193.134]




?>

Yes, $_SERVER["HTTP_X_FORWARDED_FOR"] is how I see my ip when under a proxy on my nginx server.

But your best bet is to run phpinfo() on a page requested from under a proxy so you can look at all the availabe variables and see what is the one that carries your real ip.

This is the most common technique I've seen:

function getUserIP() {
if( array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')>0) {
$addr = explode(",",$_SERVER['HTTP_X_FORWARDED_FOR']);
return trim($addr[0]);
} else {
return $_SERVER['HTTP_X_FORWARDED_FOR'];
}
}
else {
return $_SERVER['REMOTE_ADDR'];
}
}

Note that it does not guarantee it you will get always the correct user IP because there are many ways to hide it.

This is my approach:

 function getRealUserIp(){
switch(true){
case (!empty($_SERVER['HTTP_X_REAL_IP'])) : return $_SERVER['HTTP_X_REAL_IP'];
case (!empty($_SERVER['HTTP_CLIENT_IP'])) : return $_SERVER['HTTP_CLIENT_IP'];
case (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) : return $_SERVER['HTTP_X_FORWARDED_FOR'];
default : return $_SERVER['REMOTE_ADDR'];
}
}

How to use:

$ip = getRealUserIp();

This works for Windows and Linux! It doesn't matter if it's localhost or online..

    function getIP() {
$ip = $_SERVER['SERVER_ADDR'];


if (PHP_OS == 'WINNT'){
$ip = getHostByName(getHostName());
}


if (PHP_OS == 'Linux'){
$command="/sbin/ifconfig";
exec($command, $output);
// var_dump($output);
$pattern = '/inet addr:?([^ ]+)/';


$ip = array();
foreach ($output as $key => $subject) {
$result = preg_match_all($pattern, $subject, $subpattern);
if ($result == 1) {
if ($subpattern[1][0] != "127.0.0.1")
$ip = $subpattern[1][0];
}
//var_dump($subpattern);
}
}
return $ip;
}

apply this code for get the ipaddress:

    if (getenv('HTTP_X_FORWARDED_FOR')) { $pipaddress = getenv('HTTP_X_FORWARDED_FOR');
$ipaddress = getenv('REMOTE_ADDR');
echo "Your Proxy IP address is : ".$pipaddress. "(via $ipaddress)" ; }
else { $ipaddress = getenv('REMOTE_ADDR'); echo "Your IP address is : $ipaddress"; }
------------------------------------------------------------------------

This is my function.

benefits :

  • Work if $_SERVER was not available.
  • Filter private and/or reserved IPs;
  • Process all forwarded IPs in X_FORWARDED_FOR
  • Compatible with CloudFlare
  • Can set a default if no valid IP found!
  • Short & Simple !

/**
* Get real user ip
*
* Usage sample:
* GetRealUserIp();
* GetRealUserIp('ERROR',FILTER_FLAG_NO_RES_RANGE);
*
* @param string $default default return value if no valid ip found
* @param int    $filter_options filter options. default is FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
*
* @return string real user ip
*/


function GetRealUserIp($default = NULL, $filter_options = 12582912) {
$HTTP_X_FORWARDED_FOR = isset($_SERVER)? $_SERVER["HTTP_X_FORWARDED_FOR"]:getenv('HTTP_X_FORWARDED_FOR');
$HTTP_CLIENT_IP = isset($_SERVER)?$_SERVER["HTTP_CLIENT_IP"]:getenv('HTTP_CLIENT_IP');
$HTTP_CF_CONNECTING_IP = isset($_SERVER)?$_SERVER["HTTP_CF_CONNECTING_IP"]:getenv('HTTP_CF_CONNECTING_IP');
$REMOTE_ADDR = isset($_SERVER)?$_SERVER["REMOTE_ADDR"]:getenv('REMOTE_ADDR');


$all_ips = explode(",", "$HTTP_X_FORWARDED_FOR,$HTTP_CLIENT_IP,$HTTP_CF_CONNECTING_IP,$REMOTE_ADDR");
foreach ($all_ips as $ip) {
if ($ip = filter_var($ip, FILTER_VALIDATE_IP, $filter_options))
break;
}
return $ip?$ip:$default;
}

If the Proxy is which you trust, you can try: (Assume the Proxy IP is 151.101.2.10)

<?php


$trustProxyIPs = ['151.101.2.10'];


$clientIP  = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL;


if (in_array($clientIP, $trustProxyIPs)) {


$headers = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR'];


foreach ($headers as $key => $header) {


if (isset($_SERVER[$header]) && filter_var($_SERVER[$header], FILTER_VALIDATE_IP)) {


$clientIP = $_SERVER[$header];


break;
}
}
}


echo $clientIP;

This will prevent forged forward header by direct requested clients, and get real IP via trusted Proxies.