Advertisement
Advertisement


How to get the client IP address in PHP


Question

How can I get the client IP address using PHP?

I want to keep record of the user who logged into my website through his/her IP address.

2019/02/13
1
1189
2/13/2019 3:56:54 PM


$_SERVER['REMOTE_ADDR'] may not actually contain real client IP addresses, as it will give you a proxy address for clients connected through a proxy, for example. That may well be what you really want, though, depending what your doing with the IPs. Someone's private RFC1918 address may not do you any good if you're say, trying to see where your traffic is originating from, or remembering what IP the user last connected from, where the public IP of the proxy or NAT gateway might be the more appropriate to store.

There are several HTTP headers like X-Forwarded-For which may or may not be set by various proxies. The problem is that those are merely HTTP headers which can be set by anyone. There's no guarantee about their content. $_SERVER['REMOTE_ADDR'] is the actual physical IP address that the web server received the connection from and that the response will be sent to. Anything else is just arbitrary and voluntary information. There's only one scenario in which you can trust this information: you are controlling the proxy that sets this header. Meaning only if you know 100% where and how the header was set should you heed it for anything of importance.

Having said that, here's some sample code:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

Editor's note: Using the above code has security implications. The client can set all HTTP header information (ie. $_SERVER['HTTP_...) to any arbitrary value it wants. As such it's far more reliable to use $_SERVER['REMOTE_ADDR'], as this cannot be set by the user.

From: http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html

2016/01/14

2010/06/09

Here is a cleaner code sample of a good way to get the IP address of the user.

$ip = $_SERVER['HTTP_CLIENT_IP'] ? $_SERVER['HTTP_CLIENT_IP'] : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);

Here is a shorter version that uses the elvis operator:

$_SERVER['HTTP_CLIENT_IP'] ? : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? : $_SERVER['REMOTE_ADDR']);

Here is a version that uses isset to remove notices (thank you, @shasi kanth):

$ip = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
2019/03/02

It should be contained in the $_SERVER['REMOTE_ADDR'] variable.

2013/03/07

My favourite solution is the way Zend Framework 2 uses. It also considers the $_SERVER properties HTTP_X_FORWARDED_FOR, HTTP_CLIENT_IP, REMOTE_ADDR but it declares a class for it to set some trusted proxies and it returns one IP address not an array. I think this is the solution that comes closest to it:

class RemoteAddress
{
    /**
     * Whether to use proxy addresses or not.
     *
     * As default this setting is disabled - IP address is mostly needed to increase
     * security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
     * just for more flexibility, but if user uses proxy to connect to trusted services
     * it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
     *
     * @var bool
     */
    protected $useProxy = false;

    /**
     * List of trusted proxy IP addresses
     *
     * @var array
     */
    protected $trustedProxies = array();

    /**
     * HTTP header to introspect for proxies
     *
     * @var string
     */
    protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';

    // [...]

    /**
     * Returns client IP address.
     *
     * @return string IP address.
     */
    public function getIpAddress()
    {
        $ip = $this->getIpAddressFromProxy();
        if ($ip) {
            return $ip;
        }

        // direct IP address
        if (isset($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        }

        return '';
    }

    /**
     * Attempt to get the IP address for a proxied client
     *
     * @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
     * @return false|string
     */
    protected function getIpAddressFromProxy()
    {
        if (!$this->useProxy
            || (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies))
        ) {
            return false;
        }

        $header = $this->proxyHeader;
        if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
            return false;
        }

        // Extract IPs
        $ips = explode(',', $_SERVER[$header]);
        // trim, so we can compare against trusted proxies properly
        $ips = array_map('trim', $ips);
        // remove trusted proxy IPs
        $ips = array_diff($ips, $this->trustedProxies);

        // Any left?
        if (empty($ips)) {
            return false;
        }

        // Since we've removed any known, trusted proxy servers, the right-most
        // address represents the first IP we do not know about -- i.e., we do
        // not know if it is a proxy server, or a client. As such, we treat it
        // as the originating IP.
        // @see http://en.wikipedia.org/wiki/X-Forwarded-For
        $ip = array_pop($ips);
        return $ip;
    }

    // [...]
}

See the full code here: https://raw.githubusercontent.com/zendframework/zend-http/master/src/PhpEnvironment/RemoteAddress.php

2019/03/05

Source: https://stackoverflow.com/questions/3003145
Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]