List Info

Thread: Re: Catalyst::Engine::Apache X-Forwarded-* Handling




Re: Catalyst::Engine::Apache X-Forwarded-* Handling
country flaguser name
United States
2007-05-23 14:11:11
On May 23, 2007, at 2:42 PM, John Shields wrote:

> All,
>
> First, I wasn't sure where to send this since I
couldn't find a
> discussion forum for this module, so I'm sending it
directly to you
> all. If there is a good place to post this then please
let me know and
> I'd be happy to resend to a mailing list, etc.

Thanks, the proper place would be the catalyst-dev mailing
list, but  
this is fine.  I've cc'ed the list and attached your patch
for others  
to see.



>
> I've attached a patch to Catalyst/Engine/Apache.pm
(1.11) to handle
> the Apache "X-Forwarded-*" headers correctly
(as I understand them).
> The patch does two things:
>
> 1. Changed the current IP address determination to use
the *first* IP
> in the "X-Forwarded-For" header rather than
the last. My understanding
> of the header is that the first IP address will be the
first client IP
> and the last will be the closest proxy server IP. My
understanding of
> the $c->req->address field is that this should
indicate the original
> client IP, not the closest proxy server.

I think we need to stick with the current X-Forwarded-For  
implementation because you can't trust any proxy server
outside of  
your own network.  So using the last IP address means you
get the IP  
of what your own proxy server saw, not the actual IP of the
client,  
which may even be a useless private IP address.

See http://ww
w.openinfo.co.uk/apache/index.html for example, they  
discuss this more.

>
> 2. Added the same processing for the
"X-Forwarded-Host" header as this
> can also have a comma separated list. In our
environment we proxy
> twice and the existing code creates a URI that has a
host name of
> "www.myhost.com, www.myhost.com". In this
case as well, I think the
> correct behavior is to pick up the first host name as
this should be
> the original requested host name.

Shouldn't we also use the last forwarded host in this list
too?

-Andy



_______________________________________________
Catalyst-dev mailing list
Catalyst-devlists.rawmode.org
http://lists.rawmode.org/mailman/listinfo/catalyst-dev


  
Re: Catalyst::Engine::Apache X-Forwarded-* Handling
user name
2007-05-23 19:03:10
On 5/23/07, Andy Grundman <andyhybridized.org> wrote:
> >
> > I've attached a patch to Catalyst/Engine/Apache.pm
(1.11) to handle
> > the Apache "X-Forwarded-*" headers
correctly (as I understand them).
> > The patch does two things:
> >
> > 1. Changed the current IP address determination to
use the *first* IP
> > in the "X-Forwarded-For" header rather
than the last. My understanding
> > of the header is that the first IP address will be
the first client IP
> > and the last will be the closest proxy server IP.
My understanding of
> > the $c->req->address field is that this
should indicate the original
> > client IP, not the closest proxy server.
>
> I think we need to stick with the current
X-Forwarded-For
> implementation because you can't trust any proxy server
outside of
> your own network.  So using the last IP address means
you get the IP
> of what your own proxy server saw, not the actual IP of
the client,
> which may even be a useless private IP address.
>
> See http://ww
w.openinfo.co.uk/apache/index.html for example, they
> discuss this more.
>

I think the existence of that Apache module
(mod_extract_forwarded)
clarifies that the "X-Forwarded-For" header is
next to useless unless
you do some munging or just trust it.

If the engine always picks off the last IP then you are
assuming that
there is only one proxy server between you (Perl/Catalyst)
and the
external network. This is not always true. For example, in
our
environment we have a proxy server in a DMZ that proxies to
our
internal "lite" server which then proxies to our
mod_perl server. Thus
the last IP is just our DMZ proxy.

On the other hand, if you always pick off the first IP then
you are
susceptible to external spoofing and possibly to some sort
of attack.
(Although I think that depends upon what you DO with the
IP...) In any
case it could be some internal IP of the client and not much
more
useful than my DMZ proxy IP.

My position with this patch is that the IP returned by
$c->req->address should be the closest thing to the
browser IP as
possible. Due to possible spoofing, there is no definitive
way to
determine that the header is valid (as far as I can tell).
So my
thinking is that Apache.pm should assume that the
"X-Forwarded-For"
header is valid. The task of ensuring that the header is
valid can be
delegated to your internal proxy server configuration. For
example, if
I only want the closest IP to my DMZ proxy to be first, then
I can use
the following directive in the proxy configuration to clear
any
existing header:

RequestHeader unset X-Forwarded-For

I think that Apache.pm either needs to assume that the
"X-Forwarded-For" header is valid or have some
more configuration
options to allow you to control the IP selection from the
list. This
configuration could be similar to the
"mod_extract_forwarded". But
again, I think this can (should) be handled at the proxy
configuration
level rather than at the Catalyst code level.

> >
> > 2. Added the same processing for the
"X-Forwarded-Host" header as this
> > can also have a comma separated list. In our
environment we proxy
> > twice and the existing code creates a URI that has
a host name of
> > "www.myhost.com, www.myhost.com". In
this case as well, I think the
> > correct behavior is to pick up the first host name
as this should be
> > the original requested host name.
>
> Shouldn't we also use the last forwarded host in this
list too?
>
> -Andy
>

My thinking on this one is the same as for
"X-Forwarded-For" except
that you *can* configure your proxies to forward the host
name
(ProxyPreserveHost On) which I think results in all of the
entries
added by your proxies being the same. But there again,
theoretically
the first entry in the list is supposed to represent the
host name
used by the client to access the site. Thus, if I want to
create a new
URL for the user I should use that first host name
(spoofing
notwithstanding). Also, again you can have your external
facing proxy
server clean up the header if you are worried about
spoofing.

So my position for both of these headers is that by the time
they
reach Catalyst they should be trusted and that the original
meaning of
them should be honored. Otherwise, you end up needing to
allow all
kinds of fine tuning via configuration in order to pick out
the
correct IP or host name for your specific proxy
configuration. I feel
like the decision of where to draw the line between external
and
internal should be handled by those administering the proxy
server
itself. This also allows for proxy server architecture
changes without
modifying your Catalyst configuration.

Of course I could be all wrong!  Thanks!

- John

_______________________________________________
Catalyst-dev mailing list
Catalyst-devlists.rawmode.org
http://lists.rawmode.org/mailman/listinfo/catalyst-dev


[1-2]

about | contact  Other archives ( Real Estate discussion Medical topics )