Getting the Correct IP Address With PHP

If you do much work on a WordPress site or other PHP app sooner or later you’re going to need to get the end user’s IP address. It used to be easy. We used to be able to just get $_SERVER[‘REMOTE_ADDR’] and go on our way.

Today it isn’t so easy. For both performance and security many web servers put some sort of proxy in front of the web server which means that if you’re using a load balancer or CloudFlare or Varnish $_SERVER[‘REMOTE_ADDR’] will only return the IP address of the proxy, not the IP address of the user trying to access your site. This means that as far your application is concerned the only user it will ever see is the proxy service itself.

Fortunately there is a way around this using the X-Forwarded-For header. This is a server header set by the proxy to pass through the IP address of the end user where necessary. This means that while REMOTE_ADDR still exists the X-Forwarded-For header is the one that is actually tied to the user so we need to use it instead. Here’s some code to get you there:

function get_ip() {

  //Just get the headers if we can or else use the SERVER global.
  if ( function_exists( 'apache_request_headers' ) ) {

    $headers = apache_request_headers();

  } else {

    $headers = $_SERVER;

  }

  //Get the forwarded IP if it exists.
  if ( array_key_exists( 'X-Forwarded-For', $headers ) && filter_var( $headers['X-Forwarded-For'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {

    $the_ip = $headers['X-Forwarded-For'];

  } elseif ( array_key_exists( 'HTTP_X_FORWARDED_FOR', $headers ) && filter_var( $headers['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {

    $the_ip = $headers['HTTP_X_FORWARDED_FOR'];

  } else {

    $the_ip = filter_var( $_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 );

  }

  return $the_ip;

}

So let’s break it down.

  1. We start by creating a function called get_ip() which we can use and re-use to get the user’s IP address.
  2. After we create the function we get the server headers using PHP’s apache_request_headers() function if it exists or just falling back to $_SERVER otherwise.
  3. Next we look for the presence of X-Forwarded-For or HTTP_X_FORWARDED_FOR (they’re actually interchangeable) in order to use one of them if present.
  4. Finally we just REMOTE_ADDR if neither of the others are available.
  5. Note that at each step we pass the header through PHP’s filter_var() function to make sure the value is a valid IPv4 address.
  6. Finally we return the IP we attained.

Pretty simple huh? There is one catch though. If the proxy doesn’t set the header your function won’t be able retrieve it. You’ll need to check with your host to make sure the header is being set correctly.

8 Replies to “Getting the Correct IP Address With PHP”

  1. Running into a few places where ip address is masked, there are some other ways to make sure you get an ip and making sure it’s the right one:

    $ipaddress = ”;
    if ($_SERVER[‘HTTP_CLIENT_IP’] != ‘127.0.0.1’)
    $ipaddress = $_SERVER[‘HTTP_CLIENT_IP’];
    else if ($_SERVER[‘HTTP_X_FORWARDED_FOR’] != ‘127.0.0.1’)
    $ipaddress = $_SERVER[‘HTTP_X_FORWARDED_FOR’];
    else if ($_SERVER[‘HTTP_X_FORWARDED’] != ‘127.0.0.1’)
    $ipaddress = $_SERVER[‘HTTP_X_FORWARDED’];
    else if ($_SERVER[‘HTTP_FORWARDED_FOR’] != ‘127.0.0.1’)
    $ipaddress = $_SERVER[‘HTTP_FORWARDED_FOR’];
    else if ($_SERVER[‘HTTP_FORWARDED’] != ‘127.0.0.1’)
    $ipaddress = $_SERVER[‘HTTP_FORWARDED’];
    else if ($_SERVER[‘REMOTE_ADDR’] != ‘127.0.0.1’)
    $ipaddress = $_SERVER[‘REMOTE_ADDR’];
    else
    $ipaddress = ‘UNKNOWN’;

    Huge topic on this (http://stackoverflow.com/questions/15699101/get-the-client-ip-address-using-php), but I like the way you coded yours. Might consider adding a CLIENT_IP just incase and a else unkown, so we can maybe run another function incase the ip is masked or behind some sort of firewall/VPN?

  2. Hi, is there an eqivalent for this for when I wish to forward a referrer’s domain, e.g. for the purpose of transmitting that information in a confirmation email sent out after a booking or other form submit has been made on my site?

  3. Thanks, and what about the IPv6 address? It may happen someday hopefully that a visitor comes with an IPv6. How does the script process that?

  4. Good afternoon Chris,

    I am trying to implement the correct way to log all visitors Ip address regardless of if they are behind a proxy or not.

    how would I go about implementing this in wordpress on my server where i can display the results on a page on my website that breaks down IP address, geo location, browser, Date, Time, O.S and pages visited, etc, etc?

    I want to do this because well, there are unethical people in the world and in my instance, I have a competitor that has done a negative seo link campaign against me and is deliberately skewing my bounce rate on my site which also has an impact on seo.

    a php guru I am not and this is a topic and subject that I have no former experience with. is there any way that you could assist me with some of your insight on how to achieve what I am asking?

    There is tons of stuff on the net but I am afraid that most are incomplete and do not provide a working tutorial on how to go about implementing such a solution.

    While I may not have insight into this particular topic, I do posses great capabilities as a developer so..I it wouldn’t be too painful of an experience providing me with some assistance. ๐Ÿ˜€

    If you want to see my work just visit my website and you can see that I am not a n00b

    thank you Chris and I look forward to hearing back from you.

    Sincerely,

    Campbell McArthur
    Owner / Lead Engineer
    PC Medics On Call
    Phone: (910) 200-0150
    http://www.pcmedicsoncall.com