I have a simple script which determines the user's IP address:
function GetIp(){
if (!empty($_SERVER['HTTP_CLIENT_IP']))
//check ip from share internet
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
//to check ip is pass from proxy
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
Now on the Net somewhere I saw someone using this script:
if (isset($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP'] != '')
$Ip = $_SERVER['HTTP_CLIENT_IP'];
elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] != '')
$Ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != '')
$Ip = $_SERVER['REMOTE_ADDR'];
I was wondering if my implementation is broken.. Do I need to check if the value of $_SERVER['HTTP_CLIENT_IP']
, $_SERVER['HTTP_X_FORWARDED_FOR']
, or $_SERVER['REMOTE_ADDR']
is empty? Or is it actually unnecessary to do so?
If the reason why you want to find out the client's IP address is really important, screw all this stuff.
Any one of these header values can be freely spoofed.
REMOTE_ADDR
is the only really reliable information, as it is transmitted to you by your web server that is handling the request. It can be theoretically falsified as well, but that is much, much harder than spoofing a header value, and an entirely different class of attack.
There are exceptions in very, very specific hosting environments behind reverse proxies. In those cases the person administering that proxy will be able to tell what header value you need to test for.
From Kohanas' Request class:
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])
AND isset($_SERVER['REMOTE_ADDR'])
AND in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies))
{
// Use the forwarded IP address, typically set when the
// client is using a proxy server.
// Format: "X-Forwarded-For: client1, proxy1, proxy2"
$client_ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
Request::$client_ip = array_shift($client_ips);
unset($client_ips);
}
elseif (isset($_SERVER['HTTP_CLIENT_IP'])
AND isset($_SERVER['REMOTE_ADDR'])
AND in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies))
{
// Use the forwarded IP address, typically set when the
// client is using a proxy server.
$client_ips = explode(',', $_SERVER['HTTP_CLIENT_IP']);
Request::$client_ip = array_shift($client_ips);
unset($client_ips);
}
elseif (isset($_SERVER['REMOTE_ADDR']))
{
// The remote IP address
Request::$client_ip = $_SERVER['REMOTE_ADDR'];
}
This is pretty much as good as it gets. Please note the Request::$trusted_proxies
array and that your $ip
var is Request::$client_ip
in this case.
Do not check any HTTP_*
headers for the client IP unless you specifically know your application is configured behind a reverse proxy. Trusting the values of these headers unconditionally will allow users to spoof their IP address.
The only $_SERVER
field containing a reliable value is REMOTE_ADDR
.
The two things are practically identical.. In the script you found, the author is just doing a check if the element in the array is set before checking that it is non-empty.
In regards to using the empty()
-function instead of the comparison, check http://php.net/empty. Since you are dealing with a variable that is set by the environment and not a user input it doesn't matter which of the two options you choose. So your script should be perfectly fine