You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Mark Moseley <mo...@gmail.com> on 2009/01/08 19:40:18 UTC

Setting $r->connection->remote_ip doesn't change $r->connection->remote_addr

Hi. This is largely a cut/paste repost from the regular modperl list,
so pardon any weirdness (and likely odd line wraps).

I've got a reverse proxy setup in front of apache (2.2.10 with mp
2.0.4) and setting $r->connection->remote_ip based on a header I add
on the reverse proxy. All that is working ok. The bit that I'm
perplexed about is that when I call $r->connection->remote_ip(
$new_ip), the corresponding ip in $r->connection->remote_addr (i.e.
what's returned by "APR::SockAddr::ip_get") is still set to the
original IP. I've verified on my existing Apache1 boxes that when I
call $r->connection->remote_ip( $new_ip ), the remote_addr structure
is getting set. I've been doing this reverse proxying with apache1 for
quite a while and haven't seen this come up ever.

Here's a line of code and the resulting error_log excerpt from apache2
where the remote IP that I'm setting is 1.1.1.1 but the real address
of the reverse proxy is 192.168.1.33:

$r->log_error( "[$$] [postread] remote_ip is now " .
$r->connection->remote_ip() . ", socket: " .
$r->connection->remote_addr->ip_get );

[Thu Dec 18 12:16:10 2008] [error] [6938] [postread] remote_ip is now
1.1.1.1, socket: 192.168.1.33


Here's the same from apache1 with all the extra stuff to deal with the
packed sockaddr:

my $remote_addr = $r->connection->remote_addr;
my ( $remote_addr_port, $remote_addr_ip ) = sockaddr_in( $remote_addr );
$remote_addr_ip = inet_ntoa( $remote_addr_ip );
$r->log_error( "[$$] [postread] remote_ip is now " .
$r->connection->remote_ip() . ", socket: $remote_addr_ip" );

[Thu Dec 18 13:14:50 2008] [error] [7179] [postread] remote_ip is now
1.1.1.1, socket: 1.1.1.1


The significance is that if you do IP-based allow/deny in your apache
conf and/or .htaccess via mod_authz_host, it seems to be using the
remote_addr structure, so if I set, e.g., "Deny from 1.1.1.1" on
apache2, it doesn't actually deny it but setting it to "Deny from
192.168.1.33" or "Deny from 192.168." denies it. On apache1, it's
correctly denying based on the address I'm setting with
$r->connection->remote_ip( $new_ip ).

I've also verified that the same thing happens on a stock Debian Etch
apache2+mp (2.2.8 + mp 2.0.3), so it's not limited to apache 2.2.10 or
mp 2.0.4.

According to the changelog for mp1, this was supported in mp1 as of mp
1.23 (that is, changing remote_ip silently updated remote_addr as
well), though perhaps the new API makes it quite hard to pull off in
perl. According to apache2_structures.map, remote_addr is read-only at
the moment but the todo/api_status file mentions it as a candidate for
making read-write.

Anybody have any pointers on how to make (safely) it read-write? The
docs for Apache2::compat have a compatible routine for remote_addr but
if you try to use it, you get the same 'Can't locate object method
"ip_set" via package "APR::SockAddr"' error. The Changes for mp2
mention "ip_set" being removed in 1.99_12 but don't mention why.

There's a C module called mod_rpaf that lets you reset remote_addr's
IP field, so there's at least some workaround, but then you lose the
flexibility of doing it in mod_perl. In my mp1 code, I've got it
looking for a few different headers and they'd depend on different ip
blocks, whereas with mod_rpaf, you're stuck with one header and one
set of acceptable remote IPs.

Thanks!

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org