Compdigitec Labs

« | Home | »

Reverse proxy (X-Forwarded-For) patches for WordPress comments and Bad Behaviour

By admin | October 30, 2010

Update: Reverse proxy support is now built into Bad Behaviour as of 2.1.x. Therefore the following patch is obsolete and should only be applied to Bad Behaviour 2.0.x. You can configure the built-in reverse proxy either through your settings.ini or in WordPress administration.

Normally, when PHP scripts access the remote IP of a client through REMOTE_ADDR, it can only access the IP of the last client. Under most web hosting conditions this is perfectly normal, but in some corporate networks there is a reverse name-based proxy used to serve multiple servers through one IP. However, this messes up many scripts because to them it appears that all traffic is coming through one Intranet address, and this also messes up many spam protection filters because it appears to be an internal address.

Most proxy servers send the X-Forwarded-For header when contains the real IP that it is forwarding, but this cannot always be trusted, especially if your server is open both inside and outside the intranet. This means that when getting the real IP address, one must be careful that the request is coming from a trusted proxy server and not from a rouge spammer.

Since most scripts are not programmed by default to provide this kind of functionality, we have written a patch for WordPress 2.9 and Bad Behvaiour 2.0.38. However, this is not an efficient or elegant way to perform this kind of functionality, and instead recommend that Apache (or whatever your web server is) automatically rewrite REMOTE_ADDR instead. This way no unofficial patching is required, and it is compatible with more scripts.

For WordPress 2.9:

Open <blog path>/wp-includes/comment.php and scroll to line 1199 (line 1390 in 3.5), which reads “$commentdata['comment_author_IP'] = preg_replace( ‘/[^0-9a-fA-F:., ]/’, ”,$_SERVER['REMOTE_ADDR'] );“.

Now add the following code to it (replacing 111.222.233.144 with your trusted proxy server IP):

/** Begin X-Forwarded-For Patch **/
$headers = getallheaders();
if(isset($headers["X-Forwarded-For"])) {
	// forwarded proxy
	if($_SERVER['REMOTE_ADDR'] == "111.222.233.144") {
		// this is a trusted gateway
		$xff = $headers["X-Forwarded-For"];
		$xff_array = explode(",",$xff);
		$last_forwarded_host = trim($xff_array[count($xff_array)-1]);
		// remove port number, if needed
		if(strpos($last_forwarded_host,":") !== false) {
			$lfh_array = explode(":",$last_forwarded_host);
			unset($lfh_array[count($lfh_array)-1]);
			$last_forwarded_host = implode(":",$lfh_array);
		}
		// set real client IP as IP
		$commentdata['comment_author_IP'] = $last_forwarded_host;
	}
}
/** End X-Forwarded For Patch **/

Now comments should be attributed to their source IPs in the Comment administration panel.

Obsolete for modern versions of Bad Behaviour! For Bad Behaviour 2.0.38:

Open <bad behaviour path>/bad-behavior/core.inc.php to line 116 ($ip = $_SERVER['REMOTE_ADDR']).

Now add the following lines after a newline (replace 111.222.233.144 with your gateway IP):

/** Begin X-Forwarded-For Patch **/
if(isset($headers["X-Forwarded-For"])) {
	// forwarded proxy
	if($ip == "111.222.233.144") {
		// this is a trusted gateway
		$xff = $headers["X-Forwarded-For"];
		$xff_array = explode(",",$xff);
		$last_forwarded_host = trim($xff_array[count($xff_array)-1]);
		// remove port number, if needed
		if(strpos($last_forwarded_host,":") !== false) {
			$lfh_array = explode(":",$last_forwarded_host);
			unset($lfh_array[count($lfh_array)-1]);
			$last_forwarded_host = implode(":",$lfh_array);
		}
		// set real client IP as IP
		$ip = $last_forwarded_host;
		unset($headers["X-Forwarded-For"]);
		unset($headers_mixed["X-Forwarded-For"]);
	}
}
/** End X-Forwarded For Patch **/

Now Bad Behaviour will start functioning again, as by default any Intranet address is whitelisted by default.

If you found this article helpful or interesting, please help Compdigitec spread the word. Don’t forget to subscribe to Compdigitec Labs for more useful and interesting articles!

Topics: HTTP (Internet), PHP | No Comments »

Comments