Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat is the most accurate way to retrieve a user's correct IP address in PHP?
    primarykey
    data
    text
    <p>I know there are a plethora of <strong>$_SERVER</strong> variables headers available for IP address retrieval. I was wondering if there is a general consensus as to how to most accurately retrieve a user's real IP address (well knowing no method is perfect) using said variables?</p> <p>I spent some time trying to find an in depth solution and came up with the following code based on a number of sources. I would love it if somebody could please poke holes in the answer or shed some light on something perhaps more accurate.</p> <p><strong><em>edit includes optimizations from @Alix</em></strong></p> <pre><code> /** * Retrieves the best guess of the client's actual IP address. * Takes into account numerous HTTP proxy headers due to variations * in how different ISPs handle IP addresses in headers between hops. */ public function get_ip_address() { // Check for shared internet/ISP IP if (!empty($_SERVER['HTTP_CLIENT_IP']) &amp;&amp; $this-&gt;validate_ip($_SERVER['HTTP_CLIENT_IP'])) return $_SERVER['HTTP_CLIENT_IP']; // Check for IPs passing through proxies if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { // Check if multiple IP addresses exist in var $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); foreach ($iplist as $ip) { if ($this-&gt;validate_ip($ip)) return $ip; } } } if (!empty($_SERVER['HTTP_X_FORWARDED']) &amp;&amp; $this-&gt;validate_ip($_SERVER['HTTP_X_FORWARDED'])) return $_SERVER['HTTP_X_FORWARDED']; if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) &amp;&amp; $this-&gt;validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP'])) return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP']; if (!empty($_SERVER['HTTP_FORWARDED_FOR']) &amp;&amp; $this-&gt;validate_ip($_SERVER['HTTP_FORWARDED_FOR'])) return $_SERVER['HTTP_FORWARDED_FOR']; if (!empty($_SERVER['HTTP_FORWARDED']) &amp;&amp; $this-&gt;validate_ip($_SERVER['HTTP_FORWARDED'])) return $_SERVER['HTTP_FORWARDED']; // Return unreliable IP address since all else failed return $_SERVER['REMOTE_ADDR']; } /** * Ensures an IP address is both a valid IP address and does not fall within * a private network range. * * @access public * @param string $ip */ public function validate_ip($ip) { if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) return false; self::$ip = $ip; return true; } </code></pre> <h2>Words of Warning (update)</h2> <p><code>REMOTE_ADDR</code> still represents the <em>most reliable</em> source of an IP address. The other <code>$_SERVER</code> variables mentioned here can be spoofed by a remote client very easily. The purpose of this solution is to attempt to determine the IP address of a client sitting behind a proxy. For your general purposes, you might consider using this in combination with the IP address returned directly from <code>$_SERVER['REMOTE_ADDR']</code> and storing both.</p> <p><strong>For 99.9% of users this solution will suit your needs perfectly.</strong> It will not protect you from the 0.1% of malicious users looking to abuse your system by injecting their own request headers. If relying on IP addresses for something mission critical, resort to <code>REMOTE_ADDR</code> and don't bother catering to those behind a proxy.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload