Andrew Gatenby

Get a Visitors’ IP Address - Accurately!

One of the sites that I’m working on at the moment requires some IP-specific functionality, but in testing I realised that the standard $_SERVER['REMOTE_ADDR'] wasn’t being as accurate as I wanted.  Then I realised that this variable doesn’t take into consideration visitors accessing via a proxy server or any random proxy/caching stuff put in place by their ISP.

So, I put together this simple little function that returns the actual IP of any visitor…

function getRemoteIP() {
	if(isset($_SERVER['HTTP_CLIENT_IP']) && !empty($_SERVER['HTTP_CLIENT_IP'])) { 
		return $_SERVER['HTTP_CLIENT_IP'];
	} else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { 
		return $_SERVER['HTTP_X_FORWARDED_FOR'];
	} else {
		return $_SERVER['REMOTE_ADDR'];
	}
 
}
 

This simple function can replace $_SERVER['REMOTE_ADDR'] in your code, and very simply checks to see if the HTTP_CLIENT_IP environmental variable is set, if so we use that.  If that’s not set, we check for HTTP_X_FORWARDED, and if that’s not set then we pass back the standard REMOTE_ADDR variable.

My understanding is that the HTTP_CLIENT_IP or HTTP_X_FORWARDED headers are set by proxy servers, sometimes at a visitors’ ISP, and contain the IP of the machine accessing the proxy server. The REMOTE_ADDR in these cases would be the IP of the proxy itself.

The order of these checks means that any accesses via a proxy, or similar setup, will result in the IP of the machine accessing the proxy server being returned.  If the machine isn’t requesting pages via a proxy, then the first two criteria aren’t matched and the standard REMOTE_ADDR should be accurate.
 

Bookmark or share this article:

  • Digg
  • del.icio.us
  • Facebook
  • Google
  • description
  • Reddit
  • StumbleUpon

Category: PHP

Tagged:

3 Responses

  1. I was working on a function like this earlier today and found that REMOTE_ADDR gives me the correct address for my IP while HTTP_X_FORWARDED_FOR returns the IP of the computer connected to the proxy server on my home network (192.168.*.*). While my situation would be rather uncommon amongst visitors I decided to make a second function that checks the IP address against private IP addresses before returning the value.

    /**
    * Call as: $userip = GetUserIP();
    */
    function GetUserIP() {
      if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $ip = CheckIP($_SERVER['HTTP_X_FORWARDED_FOR']))
          return $ip;
        if (isset($_SERVER['HTTP_CLIENT_IP']) && $ip = CheckIP($_SERVER['HTTP_CLIENT_IP']))
          return $ip;
        return $_SERVER['REMOTE_ADDR'];
      }
      if ($ip = CheckIP(getenv('HTTP_X_FORWARDED_FOR')))
        return $ip;
      if ($ip = CheckIP(getenv('HTTP_CLIENT_IP')))
        return $ip;
      return getenv('REMOTE_ADDR');
    }
     
    /**
    * Call as: $ip = CheckIP($ip);
    */
    function CheckIP($ip) {
    if (empty($ip) ||
    ($ip >= '10.0.0.0' && $ip <= '10.255.255.255') ||
    ($ip >= '172.16.0.0' && $ip <= '172.31.255.255') ||
    ($ip >= '192.168.0.0' && $ip <= '192.168.255.255') ||
    ($ip >= '169.254.0.0' && $ip <= '169.254.255.255'))
    return false;
    return $ip;
    }
  2. Thanx a lot man, I’m using this to ID spammers on my web sites.

  3. Thanks for sharing this code. This is exactly what I was looking for.

Leave a Reply