PHP: Get remote IP address

This is a frequently-asked question in PHP communities; you can never know the answer with 100% certainty, but here is a function which will return a best guess for remote user's IP address.

If a user is accessing your site from behind a proxy server, you'll still get their IP address providing the proxy has been configured to forward it on along with the request. If the proxy forwards an internal IP address (e.g. 192.168.1.23) then the function ignores it and returns the public IP of the proxy instead.

If you need to know the user's hostname as well, you should use gethostbyaddr().

<?php

  function getRemoteIP ()
  {
  
    // check to see whether the user is behind a proxy - if so,
    // we need to use the HTTP_X_FORWARDED_FOR address (assuming it's available)

    if (strlen($_SERVER["HTTP_X_FORWARDED_FOR"]) > 0) { 

      // this address has been provided, so we should probably use it

      $f = $_SERVER["HTTP_X_FORWARDED_FOR"];

      // however, before we're sure, we should check whether it is within a range 
      // reserved for internal use (see http://tools.ietf.org/html/rfc1918)- if so 
      // it's useless to us and we might as well use the address from REMOTE_ADDR

      $reserved = false;

      // check reserved range 10.0.0.0 - 10.255.255.255
      if (substr($f, 0, 3) == "10.") {
        $reserved = true;
      }

      // check reserved range 172.16.0.0 - 172.31.255.255
      if (substr($f, 0, 4) == "172." && substr($f, 4, 2) > 15 && substr($f, 4, 2) < 32) {
        $reserved = true;
      }

      // check reserved range 192.168.0.0 - 192.168.255.255
      if (substr($f, 0, 8) == "192.168.") {
        $reserved = true;
      }

      // now we know whether this address is any use or not
      if (!$reserved) {
        $ip = $f;
      }

    } 

    // if we didn't successfully get an IP address from the above, we'll have to use
    // the one supplied in REMOTE_ADDR

    if (!isset($ip)) {
      $ip = $_SERVER["REMOTE_ADDR"];
    }

    // done!
    return $ip;

  }

?>

Questions? Suggestions for improvement? Feel free to get in touch.