12.9. Getting the Remote Server IP in the Backend Server in the Proxy Setup
When using the proxy setup to boost
performance, you might face the problem that the remote IP always
seems to be 127.0.0.1, which is your proxy's IP. To
solve that issue, Ask Bjoern Hansen has written the
mod_proxy_add_forward module,[44] which can be aded to the frontend Apache server. It sets
the X-Forwarded-For header when doing a
ProxyPass, similar to what Squid can do. This
header contains the IP address of the client connecting to the proxy,
which you can then access in the mod_perl-enabled server. You
won't need to compile anything into the backend
server.
[44]See Section
12.16 at the end of this chapter for download information.
To enable this module you have to recompile the frontend server with
the following options:
Adjust the location of mod_proxy_add_forward.c
if needed.
In the backend server you can use the handler in Example 12-4 to automatically correct
$r->connection->remote_ip.
Example 12-4. Book/ProxyRemoteAddr.pm
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;
Next, enable this handler in the backend's
httpd.conf file:
PerlPostReadRequestHandler Book::ProxyRemoteAddr
and the right thing will happen transparently for your scripts: for
Apache::Registry or
Apache::PerlRunscripts, you can access the remote
IP through $ENV{REMOTE_ADDR}, and for other
handlers you can use
$r->connection->remote_ip.
Generally, you shouldn't trust the
X-Forwarded-For header. You should only rely on
the X-Forwarded-For header from proxies you
control yourself—this is why the recommended handler we have
just presented checks whether the request really came from 127.0.0.1
before changing remote_ip. If you know how to
spoof a cookie, you've probably got the general idea
of making HTTP headers and can spoof the
X-Forwarded-For header as well. The only address
you can count on as being a reliable value is the one from
$r->connection->remote_ip.
12.8. mod_rewrite Examples
12.10. Frontend/Backend Proxying with Virtual Hosts