With a little side of applesauce...

Tuesday, January 30, 2007

mod_perl replacing r->connection->remote_ip with with “original client ip”

We have just moved our machines behind load-balancers which only send the “original client ip” in the x-forwarded-for header. This has caused us a lot of problems with our ip-based access control, (ie Allow from 192.168). We already use mod_perl for authentication on our machines, so went the next step and used mod_perl to replace the load-balancer’s address in:

r->connection->remote_ip

with the “original client ip”. Here is the code verbatim Stas Bekman’s Practical mod_perl:

package Book::ProxyRemoteAddr;

use Apache::Constants qw(OK);
use strict;

sub handler {
my $r = shift;

# we'll only look at the X-Forwarded-For header if the request
# comes from our proxy at localhost
return OK unless ($r->connection->remote_ip eq "127.0.0.1") &&
$r->header_in('X-Forwarded-For');

# Select last value in the chain -- original client's IP
if (my ($ip) = $r->headers_in->{'X-Forwarded-For'} =~ /([^,s]+)$/) {
$r->connection->remote_ip($ip);
}

return OK;
}
1;


We found it easiest to download the

sourcecode.tgz

from the book, and then move the ~/source/ch12-perf_strategy/Book directory into:

/usr/local/share/perl/5.8.4/Book

on the web server machine. The existing ProxyRemoteAddr.pm just contains a template, so you will need to replace the contents of the file with this:

handler code

And, replace 127.0.0.1 with the ip address of your load-balancer(s), (use the logical || for multiple load-balancers):

# we'll only look at the X-Forwarded-For header if the request
# comes from our proxy at localhost
return OK unless ($r->connection->remote_ip eq "127.0.0.1") &&
$r->header_in('X-Forwarded-For');

Then, you simply add this to your httpd.conf file:

PerlPostReadRequestHandler Book::ProxyRemoteAddr
Restart apache, and begin to tail your logs to make sure that you see outside ip addresses being logged.

DON’T FORGET! If you have modified your LogFormat directive to replace “%h” (client ip address) with “%{X-Forwarded-For}i”, (contents of x-forwarded-for header), change them back, or your log files will not accurately reflect the changes created by ProxyRemoteAddr.pm.

No comments: