-
-
Notifications
You must be signed in to change notification settings - Fork 16.9k
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
Better handling of X-Forwarded-For header to get client ip address #2099
Comments
If I pulled something like https://github.com/dougwilson/node-connect-x-forwarded-for into core, would that work for you? |
why?
Terrible idea, because if a service is accessible directly and through a proxy, this just leads to spoofing anyway; you need to specify the IP addresses or netmasks of your border proxies, not the level.
This could be the default, but with the added requirement that the TCP connection is also from a private IP. |
Yes, something like that should work fine. It would need to work with netmasks, not only trusted ip-s.
Defensive programming? I, as a developer, would like to assume that client ip would actually be ip, not be some arbitrary string given in headers, even in case of misconfiguration.
While I agree that ip/netmasks are another solution, the proxy level has an advantage that it's easier to manage for the major use case of a single proxy (it sure can determine automatically if there's no proxy at all and handle it correctly). It could be the default if 'trust proxy' setting is on. Just an idea, I don't insist.
👍 |
But a single proxy would also be very simple just giving the single IP address or netmask of it, no? |
You would need to keep this ip address somewhere in case it will change, Architectural changes like the number of proxy levels are arguably rarer That being said, I see ip/netmask solution more obvious and clear, which is Alexander Shtuchkin On Sun, May 4, 2014 at 3:44 PM, Douglas Christopher Wilson <
|
People probably have to do this already; I know I deploy the same app with different settings per environment already; my main reason against this is that if we are going to make these changes so it is more secure, why introduce some new setting that is not at all secure with it? Seems to go against the whole reasoning for the changes proposed here.
Unfortunately to introduce these changes in 4.x, the default will have to be the current behavior (i.e. use the left-most address). In most reverse-proxy environments (all?), your proxies on the front end are actually completely re-writing the |
And one more thing, both 'proxy level' and ip/netmask settings could work more like an extension of current setting 'trust proxy':
|
Another config setting, no big deal, I agree.
If the default level is 1, then I don't see the case where it's not secure. It's secure if you have single proxy or no proxy. It will return the IP of the second proxy if there is more than one proxy level, in which case people would understand that something is wrong. It also more secure than current state and doesn't require any additional input from developer, unlike the ip/netmask approach.
Do you plan for 5.x? :)
My experience is different. For example, in Nginx, almost all manuals advise to add directive |
Well, you're right about the dual environment, there it's not safe. Hmm. |
Yea, I would look to do it whenever it becomes possible :)
Ah, looks like nginx pretty much forces you to use append-only. |
Ok, so I suggest making it an extension to 'trust proxy' setting:
Where the list of ips is concatenation of X-Forwarded-For header and direct ip. |
Using the table is kind of cool. This is what I am planning to add to 4.x:
Edit: added localhost, private, and changed local to mean link-local. |
Thats very nice! My subjective comments:
Btw, I researched current state of the business and it seems that Apache has the same non-safe handling of X-Forwarded-For header
And HAProxy setting
(All conforming servers will join several headers of the same name to a comma-separated list, so this is equal to appending as I understand) So, it most proxy servers are actually appending the ip to our header, making current setup unsafe by default. |
That is correct; by default HTTP defines that multiple instances of the same header can be concatenated together with a comma in the order from first to last.
I know, but then we really can't accept any "nice names" at all--users will just always need to specify a list of IPs; doing something special by sniffing the string would just be a bad API. It also depends on what people are using for config storage; some things have an array type.
I can see people using both "private" and "localhost" easily in those options; "localhost" is useful if you are just terminating SSL on the same machine (and thus need the SSL terminator to forwards along the remote IP). "private" would be the more general use-case. In some clouds (specifically Stackato) the proxies only communicate over link-local IPs to the app. Since the apps live in a "dual" environment where you can talk to them through the proxy and directly, "local" is a perfect easy choice for that environment. |
Thats a matter of taste I believe. These nice names are just shortcuts, much like predefined formats in logger middleware. You don't need to 'sniff', you just need to compare it with predefined string(s) and if nothing matched - use it as a comma-separated list of ip/netmasks. On a pro side, this would allow users to move this setting to config and change painlessly from "local" to "1.2.3.4/10" and back in different environments without type mangling. Plus, it will just look nicer in the major use case of a single ip/netmask.
I just wanted to suggest choosing a single option that'll fit 90% of users that know nothing about the differences and don't want to choose. The other 10% will be happy to use generic netmasks to do exactly what they need. "localhost" is the easiest to explain and will fit most users IMHO. If they need something else, they'll know it for sure and it's obvious how to implement. Anyway, I think both issues are not that important and I'll be happy with any decision from your side. I really appreciate your efforts! |
See https://github.com/expressjs/proxy-addr (initial release was made to just mimic express). |
@ashtuchkin this is about to land. This is mostly the same as the tables I put above, but in addition will accept a number for a hop count and comma-separated strings. The pre-defined choices will be there, but simplified from earlier, with the most common choice being "loopback". |
This is awesome, thank you! |
Currently, if the proxy is trusted, express uses first (leftmost) ip address in
X-Forwarded-For
header as the client ip address. This value cannot be trusted (easily spoofed by clients) and it's usage is not recommended. Please see discussion about this issue applied to Ruby:http://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection/
Quote from Apache:
I'd suggest the following algorithm:
Please also see Ruby pull request that solves this rails/rails#7980
I could write a pull request to fix it, please let me know if you're interested.
The text was updated successfully, but these errors were encountered: