[2.6.x] Trusting only the immediate proxy without knowing the IP address

43 views
Skip to first unread message

Simon

unread,
Feb 13, 2018, 12:24:21 PM2/13/18
to Play Framework
Hi,

my app is running on Heroku where I don't know the IP address of the immediate proxy, but I can trust that it will append the previous IP address to the X-Forwarded-For header.
Trusting all proxies will retrieve the first in the list which can easily be spoofed and without trusted proxies, the X-Forwarded-For header will be ignored.

Currently I extract the last one from the X-Forwarded-For list manually.  
Is there a way to get the same behaviour from  request.remoteAddress by configuration?

Thanks
Simon

Simon

unread,
Feb 14, 2018, 5:52:04 AM2/14/18
to Play Framework
I just realised that knowing the IP address of my immediate proxy wouldn't even help, because it's not in the X-Forwarded-For  header anyway. 

So the question is just: how to make request.remoteAddress return the last entry in the X-Forwarded-For or Forwarded list, if available? 

Greg Methvin

unread,
Feb 14, 2018, 6:54:54 AM2/14/18
to Play Framework
You can always write a custom HttpRequestHandler: https://www.playframework.com/documentation/2.6.x/ScalaHttpRequestHandlers#Implementing-a-custom-request-handler

In this case you'd probably want to extend the default HttpRequestHandler and override:

override def handlerForRequest(rh: RequestHeader) =
  super.handlerForRequest(new RequestHeader {
    def remoteConnection = RemoteConnection(/* whatever you want here */)

    /* implement other methods by delegating to rh */
  })


I haven't tested this code but pretty sure something along these lines will work. The modification could also be done in a filter, but that would only affect the request used by your action itself and filters later in the chain. Doing it in the HttpRequestHandler means every request processing step will see your custom remote connnection info.

Simon

unread,
Feb 15, 2018, 12:57:37 PM2/15/18
to Play Framework
thanks Greg, I'll take a look into this approach. 

But I'm still confused by the documentation, which says:

... and will validate the incoming forwarded headers to verify that they are trusted, taking the first untrusted IP address that it finds as the reported user remote address .

If none of the incoming IP addresses is in the trusted proxies list, I expected the first untrusted IP address to be  the last one in the X-Forwarded-For list (considering the list is validated in reversed order)  and not the immediate connection.

What am I missing here?

Dominic Scheirlinck

unread,
Feb 16, 2018, 1:05:37 AM2/16/18
to Play Framework
On Friday, February 16, 2018 at 6:57:37 AM UTC+13, Simon wrote:
What am I missing here?

Just that the approach to parsing forwarded headers is to append the immediate connection address (default value of request.remoteAddress) to the end of the sequence of IPs obtained from the forwarded header before processing that sequence.

So, if the immediate connection address isn't in the trusted proxies, it's used in preference to the one at the end of the forwarded header (because this scenario implies a untrusted address connecting directly to the server).

Simon

unread,
Feb 16, 2018, 3:14:04 AM2/16/18
to Play Framework
The documentation says

Play provides a configuration option to configure a list of trusted proxies, and will validate the incoming forwarded headers to verify that they are trusted


After looking at the source code  again I think you're right, the immediate connection is checked against the trusted proxy list, too. Not only the incoming forwarded headers. 

So knowing the address range of the immediate connection would solve the problem.

Greg Methvin

unread,
Feb 16, 2018, 3:45:16 AM2/16/18
to play-framework
On Fri, Feb 16, 2018 at 12:14 AM, Simon <simon....@gmail.com> wrote:
The documentation says

Play provides a configuration option to configure a list of trusted proxies, and will validate the incoming forwarded headers to verify that they are trusted


After looking at the source code  again I think you're right, the immediate connection is checked against the trusted proxy list, too. Not only the incoming forwarded headers. 

What you're getting from X-Forwarded-For is not a list of proxies, but a list of addresses the proxies are forwarding for. Probably the most common case is a single proxy, in which case X-Forwarded-For would contain the originating IP of the user of your app/service, and the immediate connection would be from your first proxy.

The immediate connection address has to be checked to tell if you can trust the forwarded headers you're getting. Otherwise anyone could send you fake forwarded headers.
 

So knowing the address range of the immediate connection would solve the problem.


On Friday, February 16, 2018 at 7:05:37 AM UTC+1, Dominic Scheirlinck wrote:
On Friday, February 16, 2018 at 6:57:37 AM UTC+13, Simon wrote:
What am I missing here?

Just that the approach to parsing forwarded headers is to append the immediate connection address (default value of request.remoteAddress) to the end of the sequence of IPs obtained from the forwarded header before processing that sequence.

So, if the immediate connection address isn't in the trusted proxies, it's used in preference to the one at the end of the forwarded header (because this scenario implies a untrusted address connecting directly to the server).

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/fb3a9101-f5c7-4a6d-b8e8-f2aa7db311cc%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Simon

unread,
Feb 16, 2018, 7:16:59 AM2/16/18
to Play Framework

The immediate connection address has to be checked to tell if you can trust the forwarded headers you're getting. Otherwise anyone could send you fake forwarded headers.


In my case I can trust the immediate connection without knowing the IP address. 
config flag like play.http.forwarded.trustImmediateConnection would be great.
Reply all
Reply to author
Forward
0 new messages