About

Fetching an ip address in PHP is rather simple but this relies on the web server, this can be any of the available web servers such as Apache, nginx, lighttpd or even the internal php web server. It shouldn’t really matter what kind of web server you are behind of, unless you have reverse proxying methods or you are behind a VPN/docker/etc…

Code

Here’s the snippet for the function, I recommend adding this into your helper functions, it shouldn’t really be kept in a class or associative array as you will most probably access it from different sections of code more or less unpredictably.

/**
 * Get the current ip address of the request
 * @example $ipAddress = getIp();
 * @return string The ip address of the current request
 */
function getIp(): string {
    // Initialize the response of the ip as an unknown proxy.
    $ip = "Unknown Proxy";

    // Try multiple server variables for the ip address
    if ( !empty($_SERVER['HTTP_CLIENT_IP']) ) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } else if ( !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }

    // Return the found ip ( if any )
    return $ip;
}

Tips for WebServers

According to RFC 7239 (Forwarded HTTP Extension), all proxy must relay client information like IP address, requested hostname, request protocol, etc. to the next location. This must be done in the Forwarded header but in real world the non-standard X-Forwarded-For header is widely used, for instance, if Apache is used as a proxy (mod_proxy), it passes on three different headers to the next hop by default:

  • X-Forwarded-For – List or chain of IP addresses where the left most address belongs to the originating client and the right most to the most recent proxy. This basically means every proxy just keeps appending this header with the client IP they resolve. With multiple proxies in the chain, some of the client IPs would be that of the proxy servers itself.
  • X-Forwarded-Host – Contains the host requested by the original client (the useragent).
  • X-Forwarded-Server – Gets overwritten by each proxy and contains the current proxy’s server name. If the proxy were Apache then it’d simply slap its ServerName value in it.

The most important piece here is X-Forwarded-For. If we trust the intermediate proxies/load balancers (more on this in a bit), then we can just extract the original IP from this header.

Nginx Proxy

For nginx add this to your location proxy pass

location /some/path/ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://localhost:8000;
}

Apache Proxy

mod_remoteip

Apache Web Server has pre-built module called mod_remoteip that can be used to resolve the IP of the original client instead of the proxy.

Once the mod_remoteip is enabled, we must specify which header is Apache supposed to read the original IP from. For this we use the RemoteIPHeader directive.

In your Apache VirtualHost Configuration add the following code to help your PHP backend

<VirtualHost *:80>
    # Stuff
    <Location />
        # Add the RemoteIPHeader X-Forwarded-For directive
        RemoteIPHeader X-Forwarded-For
    </Location>
    # Stuff
</VirtualHost>