-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
X-Forwarded-For allows spoofing client address #179
Comments
We have created an issue in Pivotal Tracker to manage this: https://www.pivotaltracker.com/story/show/147715417 The labels on this github issue will be updated when the story is started. |
@sorenh : Thank you for filing this issue. There is a story in our backlog which allows gorouter job to be configured with trusted proxies for given domains. This story address a part of the issue where gorouter expects the request to come from a trusted proxy otherwise the request is rejected. Will this story address your concern ? Regards |
assuming healthcheck api is private, how about automatically picking up trusted ips from whoever calls healthcheck api? that will allow for more dynamic configuration.
…Sent from my iPhone
On Jun 30, 2017, at 3:27 PM, Shashwathi ***@***.***> wrote:
@sorenh :
Thank you for filing this issue. There is a story in our backlog which allows gorouter job to be configured with trusted proxies for given domains. This story address a part of the issue where gorouter expects the request to come from a trusted proxy otherwise the request is rejected. Will this story address your concern ?
Regards
Shash
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
@shashwathi It helps very, very little. If the proxy in question can be relied upon to perform this filtering (discarding X-Forwarded-For entries from untrusted sources) then we'd be in good shape, but generally that's not something we can expect and there won't always be a proxy in front of the gorouter. I think this is something that needs to be addressed in gorouter. |
@sorenh You will always need some proxy in front of Gorouter to maintain HA and horizontal scaling. Gorouter currently supports the PROXY protocol. Using this you can have your LB send the client IP to gorouter. Gorouter will set x-forwarded-for to this value. |
Is using DNS to spread the request load across a gorouter cluster not supported? Anyway, if I'm reading the code correctly, using PROXY only helps identify the immediately preceding hop. If an app wants to identify the client, all it has to go on is the X-Forwarded-For header, and since a client can put any old nonsense in there, it's utterly unreliable. If a user is on a network with a proxy, connecting over the internet through an ISP who also has a proxy, in through your front end load balancer and the gorouter before reaching the app and everyone is a well-behaved, good citizen, the X-Forwarded-For header will read:
I, as the platform provider, can't really trust anything before the ISP proxy IP (which was added by the load balancer). The application developer doesn't (or at least shouldn't) know anything about the network layout, so they don't know what to trust or how many of the final hops to discard to find something trustworthy or useful. The gorouter really seems like the right place to address this problem. It can trust the load balancer to correctly identify its (immedite) client, but it can't trust any prior information, so it should be discarded and the X-Forwarded-For header should read only:
|
@sorenh : I see a potential problem with this approach. Lets take a CF deployment which has multiple layers of Load balancers configured, in this case the X-Forwarded-For header will read
This will require gorouter to have knowledge of upstream LB/Haproxy components configured to decide which part of Referring documentation on X-Forwarded-For on mozilla developer site standard format is
If gorouter alters the Thoughts @shalako ? Regards |
That does not solve the problem of passing fake IPs in Regards |
You're exactly right that gorouter will need information about trustworthy components. The alternative is allowing clients to spoof their IP. The typical scenario is simply: (Client IP), (My 1st load balancer), (My 2nd load balancer), (My nth load balancer), (Gorouter IP) All the load balancers in that case would be listed as trusted and the client IP will be passed along to the application unharmed. I'd by far prefer partial, trustworthy information over untrustworthy information (partial or not). All of GCP's load balancers (and health checkers) are in two well-known subnets. The list of trustworthy proxies should be able to include subnets, not just individual IP's. Again, nginx's docs on why and how are pretty good. |
We have tested in our lab environment. For solution: We put rule in WAF if remoteIP other then X-Forwarded-for IP then packet drop on WAF and assuming spoofing attack. |
@mohitmehral |
I'm closing this, as it appears your issue has been resolved by your workaround. Please feel free to open another issue if it has not been resolved. Thanks, |
Issue
X-Forwarded-For is passed through unfiltered, allowing anyone to spoof their origin IP.
Context
X-Forwarded-For records the path a given request has taken. The first IP is the origin client, each subsequent IP denotes a path along the way (proxies, load balancers, whatever). It's the only way for a backend service to determine the original IP, since the incoming connection is from the gorouter.
However, blindly trusting the header obviously allows anyone to spoof the origin IP. Common ways to address this security problem is to only trust X-Forwarded-For headers from trusted sources.
Examples of how to mitigate this problem:
https://httpd.apache.org/docs/current/mod/mod_remoteip.html#remoteiptrustedproxy
http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
Steps to Reproduce
Pass a X-Forwarded-For header with someone else's IP (e.g. 8.8.8.8) in it to your application, and it'll appear as though that's where the request came from.
Expected result
Since I'm not a trusted client, my X-Forwarded-For header should have been discarded, and my IP should be the first in the X-Forwarded-For header received by the backend.
Current result
The backend service will see an X-Forwarded-For header reading "8.8.8.8, [my real IP], [gorouter IP]" (possibly more, if there's a load balancer or something in the path). It will think the request came from 8.8.8.8.
Possible Fix
Allow specifying a list of IPs (or CIDR's) of trusted proxies and load balancers. If the request didn't come from one of them, discard the X-Forwarded-For. For bonus points, do what nginx does: Go through the list (starting from the last entry) and check each entry to see if it's the list of trusted proxies. When one is encountered that's not on the list, discard everything before it.
All of the above also applies to X-Forwarded-Proto. We shouldn't trust people to say that their request was ever HTTPS if it never was.
The text was updated successfully, but these errors were encountered: