Skip to content

Instantly share code, notes, and snippets.

@cballou
Created March 26, 2012 00:51
Show Gist options
  • Star 81 You must be signed in to star a gist
  • Fork 35 You must be signed in to fork a gist
  • Save cballou/2201933 to your computer and use it in GitHub Desktop.
Save cballou/2201933 to your computer and use it in GitHub Desktop.
PHP - Advanced Method to Retrieve Client IP Address
<?php
function get_ip_address() {
$ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR');
foreach ($ip_keys as $key) {
if (array_key_exists($key, $_SERVER) === true) {
foreach (explode(',', $_SERVER[$key]) as $ip) {
// trim for safety measures
$ip = trim($ip);
// attempt to validate IP
if (validate_ip($ip)) {
return $ip;
}
}
}
}
return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : false;
}
/**
* Ensures an ip address is both a valid IP and does not fall within
* a private network range.
*/
function validate_ip($ip)
{
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
return false;
}
return true;
}
<?php
/**
* 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.
*/
function get_ip_address() {
// check for shared internet/ISP IP
if (!empty($_SERVER['HTTP_CLIENT_IP']) && 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 ips exist in var
if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false) {
$iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($iplist as $ip) {
if (validate_ip($ip))
return $ip;
}
} else {
if (validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
return $_SERVER['HTTP_X_FORWARDED_FOR'];
}
}
if (!empty($_SERVER['HTTP_X_FORWARDED']) && validate_ip($_SERVER['HTTP_X_FORWARDED']))
return $_SERVER['HTTP_X_FORWARDED'];
if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
return $_SERVER['HTTP_FORWARDED_FOR'];
if (!empty($_SERVER['HTTP_FORWARDED']) && validate_ip($_SERVER['HTTP_FORWARDED']))
return $_SERVER['HTTP_FORWARDED'];
// return unreliable ip since all else failed
return $_SERVER['REMOTE_ADDR'];
}
/**
* Ensures an ip address is both a valid IP and does not fall within
* a private network range.
*/
function validate_ip($ip) {
if (strtolower($ip) === 'unknown')
return false;
// generate ipv4 network address
$ip = ip2long($ip);
// if the ip is set and not equivalent to 255.255.255.255
if ($ip !== false && $ip !== -1) {
// make sure to get unsigned long representation of ip
// due to discrepancies between 32 and 64 bit OSes and
// signed numbers (ints default to signed in PHP)
$ip = sprintf('%u', $ip);
// do private network range checking
if ($ip >= 0 && $ip <= 50331647) return false;
if ($ip >= 167772160 && $ip <= 184549375) return false;
if ($ip >= 2130706432 && $ip <= 2147483647) return false;
if ($ip >= 2851995648 && $ip <= 2852061183) return false;
if ($ip >= 2886729728 && $ip <= 2887778303) return false;
if ($ip >;= 3221225984 && $ip <= 3221226239) return false;
if ($ip >;= 3232235520 && $ip <= 3232301055) return false;
if ($ip >= 4294967040) return false;
}
return true;
}
@xeoncross
Copy link

// return unreliable ip since all else failed
return $_SERVER['REMOTE_ADDR'];

This is incorrect thinking. ↑

REMOTE_ADDR should be first in the above code, not last and marked as "unreliable".

All I have to do is set a HTTP_X_FORWARDED_FOR header and your server will log whatever IP I give it.

Background: These are valid headers that some proxies do pass - but you have to take their word for it. Anyone could claim anything and you have no idea if it's true.

You MUST log the REMOTE_ADDR since it's the only guaranteed address. If you want to log these others as additional information then please do it - but don't ignore REMOTE_ADDR.

@drklicker
Copy link

I insert REMOTE_ADDR in one column, then I loop through the possible proxy address keys in $_SERVER and when I find one, it gets logged to the Proxy column.

@hefese
Copy link

hefese commented Dec 15, 2014

Thank you so much cballou, you saved me from spammer which views my blog articles and increments my counter redundantly. With this code, now I can use an advanced counter based IP address. But why doesn't $_SERVER['REMOTE_ADDR'] work as a single? It gives me just hosting IP address, not users' which views my website. Could you explain this situtation?

@nimasdj
Copy link

nimasdj commented Jul 17, 2015

what does >;= mean on lines 63-64?

@jeijei4
Copy link

jeijei4 commented Apr 3, 2017

/**
* Function to get the client ip address
* @return String|false
*/
function get_ip_address() {
$ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR');
foreach ($ip_keys as $key) {
if (array_key_exists($key, $_SERVER) === true) {
foreach (explode(',', $_SERVER[$key]) as $ip) {
// trim for safety measures
$ip = trim($ip);
// attempt to validate IP
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
return $ip;
}
}
}
}
return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : false;
}

@cxtal
Copy link

cxtal commented Jul 28, 2018

Small typo:

		if ($ip >;= 3221225984 && $ip <= 3221226239) return false;
		if ($ip >;= 3232235520 && $ip <= 3232301055) return false;

should be:

		if ($ip >= 3221225984 && $ip <= 3221226239) return false;
		if ($ip >= 3232235520 && $ip <= 3232301055) return false;

@akamomer
Copy link


<?php
//Mainly, $_SERVER['REMOTE_ADDR'] contains IP address of client who viewing the page
function get_client_ip($single = 2) {
    $ipaddress = array();
    if( $single == 2){
      if (isset($_SERVER['HTTP_CLIENT_IP']))
          $ipaddress[] = $_SERVER['HTTP_CLIENT_IP'];
      if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
          $ipaddress[] = $_SERVER['HTTP_X_FORWARDED_FOR'];
      if(isset($_SERVER['HTTP_X_FORWARDED']))
          $ipaddress[] = $_SERVER['HTTP_X_FORWARDED'];
      if(isset($_SERVER['HTTP_FORWARDED_FOR']))
          $ipaddress[] = $_SERVER['HTTP_FORWARDED_FOR'];
      if(isset($_SERVER['HTTP_FORWARDED']))
          $ipaddress[] = $_SERVER['HTTP_FORWARDED'];
      if(isset($_SERVER['REMOTE_ADDR']))
          $ipaddress[] = $_SERVER['REMOTE_ADDR'];
      if(count($ipaddress) == 0)
          $ipaddress[] = 'UNKNOWN';
      $ips = implode(", ", array_unique($ipaddress));
    }
    if( $single == 1){
      $ips = $_SERVER['REMOTE_ADDR'];
    }
    return $ips;
}
?>

source: https://standingtech.com/clientip/how-to-get-client-ip-address-in-php

@rmdhfz
Copy link

rmdhfz commented Sep 13, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment