Fix for Incorrect IP Addresses in WordPress Comments
by Grant Burton on Nov.30, 2008, under PHP, Security, Spam, Wordpress
Due to a web server’s proxy or the server is clustered (particularly with “cloud” based hosting), the server variable WordPress uses does not reflect the IP address of the posting user. Instead the IP address is the internal private LAN address of the web server’s network. This causes problems when trying to blacklist spammers or use a plugin like Akismet.
To workaround this IP address issue, you will need to modify the $_SERVER[“REMOTE_ADDR”] variable by editing the “wp-config.php” in your WordPress root directory:
- Download and backup your wp-config.php configuration file.
- Open your WordPress configuration file and add the following code after the named constant definitions:
/* By Grant Burton @ BURTONTECH.COM (11-30-2008): IP-Proxy-Cluster Fix */ /* Updated on 7/30/2015 to reflect current IANA addresses */ function checkIP($ip) { if (!empty($ip) && ip2long($ip)!=-1 && ip2long($ip)!=false) { $private_ips = array (array('10.0.0.0','10.255.255.255'), array('127.0.0.0','127.255.255.255'), array('169.254.0.0','169.254.255.255'), array('172.16.0.0','172.31.255.255'), array('192.168.0.0','192.168.255.255'), array('255.255.255.0','255.255.255.255') ); </p><p>foreach ($private_ips as $r) { $min = ip2long($r[0]); $max = ip2long($r[1]); if ((ip2long($ip) >= $min) && (ip2long($ip) < = $max)) return false; } return true; } else { return false; } } function determineIP() { if (checkIP($_SERVER["HTTP_CLIENT_IP"])) { return $_SERVER["HTTP_CLIENT_IP"]; } foreach (explode(",",$_SERVER["HTTP_X_FORWARDED_FOR"]) as $ip) { if (checkIP(trim($ip))) { return $ip; } } if (checkIP($_SERVER["HTTP_X_FORWARDED"])) { return $_SERVER["HTTP_X_FORWARDED"]; } elseif (checkIP($_SERVER["HTTP_X_CLUSTER_CLIENT_IP"])) { return $_SERVER["HTTP_X_CLUSTER_CLIENT_IP"]; } elseif (checkIP($_SERVER["HTTP_FORWARDED_FOR"])) { return $_SERVER["HTTP_FORWARDED_FOR"]; } elseif (checkIP($_SERVER["HTTP_FORWARDED"])) { return $_SERVER["HTTP_FORWARDED"]; } else { return $_SERVER["REMOTE_ADDR"]; } } //Override server variable for WordPress comments $_SERVER["REMOTE_ADDR"] = determineIP();
Caution should be used since many of these variables can be spoofed by a client, so don’t use them for authentication or access control. The functions could be easily adapted for other web applications though.
3 Comments for this entry
1 Trackback or Pingback for this entry
-
Getting Visitors’ IP Address in PHP :: Web Scripting
October 28th, 2009 on 10:18 am[…] Grant Burton has a better mechanism for detecting visitor’s real IP address. He is checking for local network IP address (for example -192.168.x.x) first and based on that he is deciding which one to take. You may not like storing the 192.168.x.x etc., as it will be useless. […]
January 12th, 2014 on 2:31 am
Great work Grant, but the 2.0.0.0/8 range is not private any more. I just saw a legit IP like today. You should update the code and remove that line altogether, or narrow it down to 0.0.0.0/8 as according to IANA only 0.0.0.0/8 is local.
December 20th, 2014 on 2:50 am
Hello
Please find below a slightly revised version of your functions that do not trigger PHP notice when in full debug mode and remove extraneous spaces in the case of comma separated multiple IPS
Cheers
/* By Grant Burton @ BURTONTECH.COM (11-30-2008): IP-Proxy-Cluster Fix */
function checkIP($ip) {
if (!empty($ip) && ip2long($ip)!=-1 && ip2long($ip)!=false) {
$private_ips = array (
array(‘0.0.0.0′,’2.255.255.255’),
array(‘10.0.0.0′,’10.255.255.255’),
array(‘127.0.0.0′,’127.255.255.255’),
array(‘169.254.0.0′,’169.254.255.255’),
array(‘172.16.0.0′,’172.31.255.255’),
array(‘192.0.2.0′,’192.0.2.255’),
array(‘192.168.0.0′,’192.168.255.255’),
array(‘255.255.255.0′,’255.255.255.255’)
);
foreach ($private_ips as $r) {
$min = ip2long($r[0]);
$max = ip2long($r[1]);
if ((ip2long($ip) >= $min) && (ip2long($ip) <= $max)) return false;
}
return true;
} else {
return false;
}
}
function determineIP() {
if (!empty($_SERVER['HTTP_CLIENT_IP']) && checkIP($_SERVER["HTTP_CLIENT_IP"])) {
return $_SERVER["HTTP_CLIENT_IP"];
}
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
foreach (explode(",",$_SERVER["HTTP_X_FORWARDED_FOR"]) as $ip) {
//attention aux espaces (null), 134.214.152.108 !!!!!!
if (checkIP(trim($ip))) {
return trim($ip);
}
}
}
if (!empty($_SERVER['HTTP_X_FORWARDED'])&& checkIP($_SERVER["HTTP_X_FORWARDED"])) {
return $_SERVER["HTTP_X_FORWARDED"];
} elseif (!empty($_SERVER["HTTP_X_CLUSTER_CLIENT_IP"]) && checkIP($_SERVER["HTTP_X_CLUSTER_CLIENT_IP"])) {
return $_SERVER["HTTP_X_CLUSTER_CLIENT_IP"];
} elseif (!empty($_SERVER["HTTP_FORWARDED_FOR"]) && checkIP($_SERVER["HTTP_FORWARDED_FOR"])) {
return $_SERVER["HTTP_FORWARDED_FOR"];
} elseif (!empty($_SERVER["HTTP_FORWARDED"]) && checkIP($_SERVER["HTTP_FORWARDED"])) {
return $_SERVER["HTTP_FORWARDED"];
} elseif(!empty($_SERVER["REMOTE_ADDR"]) && checkIP($_SERVER["REMOTE_ADDR"])) {
return $_SERVER["REMOTE_ADDR"];
} else {
return '';
}
}
July 29th, 2015 on 4:30 am
Warning, the first range is wrong: array(‘0.0.0.0′,’2.255.255.255’)
the right one is:
array(‘0.0.0.0′,’0.255.255.255’)
Example: 2.227.250.202 is a valid public IP (from Italian Fastweb Company) !!!