-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
forwardedForHeadersWorking should return true if the remote address matches trusted proxies #11594
Comments
GitMate.io thinks possibly related issues are #10826 (webdav address is incorrect when using reverse proxy), and #3456 (Remote wipe). |
My dear bot, this is not related I think. |
When remote addr is b.b.b.b for nextcloud than your setup is not configured properly. If you ask for remoteAddr you expect the client ip (a.a.a.a). Return false when your remoteAddr is listed as trusted proxy looks correct for me. server/lib/private/AppFramework/Http/Request.php Lines 597 to 627 in c0a283f
When remoteAddr is trusted proxy than check if real client ip is passed by HTTP_X_FORWARDED_FOR (or any other header you specify). cc @rullzer @MorrisJobke could you have a second look? |
Makes sense 👍 |
@danielkesselberg I think the remote address in your example is b.b.b.b and should be b.b.b.b. We are checking the proxy IP b.b.b.b not the client IP a.a.a.a. You can't trust client IPs which could change every hour on a mobile device with DHCP, maybe we should never do that. What we want to do here is to trust a reverse proxy whose IP is fixed in your intranet or IDC, so you need to check if $_SERVER['REMOTE_ADDR'] is in the trusted proxies list. If you have a client desktop or mobile device with static IP a.a.a.a (which is rare) you can use $_SERVER['HTTP_X_FORWARDED_FOR'] to check against something like trusted_clients, but I don't think anybody needs this feature and it is not related to my problem. Here is how I found this bug, I set up my nextcloud server with a reverse proxy, in the admin console it always complain about the reverse proxy mis-configuration then I check the ajax response error message and then tracked down this bug. You can use an nginx proxy with a nextcloud docker container to do the test. |
@DanielYWoo This is also correct, but we should trust the proxy and on the other side also require the proxy to forward the correct address. And if this is not the case, then the proxy is slightly misconfigured. That's the whole point of this check. So if we get the IP of a trusted server, then it is not a real client, but a proxy that does not forward the UP properly. |
@MorrisJobke If you want to check the forwarded address, that's fine but you should not use $_SERVER['REMOTE_ADDR'] for that purpose, you should use $_SERVER['HTTP_X_FORWARDED_FOR'] and you should do something more, split the addresses by comma then check them one by one. Let's say, we have multiple proxies along the way, let's say client IP a.a.a.a, proxy 1 as b.b.b.b, proxy 2 and c.c.c.c, then nextcloud as d.d.d.d. In that case the x-forwarded-for headers will be something like this: a.a.a.a, b.b.b.b, you have to split x-forwarded-for then check one by one. If any proxy along the way in matches, we can say it's safe, is that right? But I am kind of confused, nextcloud should not care about a.a.a.a or b.b.b.b, it should only care about the nearest proxy c.c.c.c is trusted, right? |
server/lib/private/AppFramework/Http/Request.php Lines 597 to 627 in c0a283f
No (you should set c.c.c.c as trusted proxy)
Yes I'm confused now 🙈 I guess |
@danielkesselberg I did not read Request.php carefully so I thought it does not respect x-forwarded-for, sorry for that. But I am still confused about the checking logic. If we only check the nearest proxy IP, why do we just check $_SERVER['REMOTE_ADDR'? If you want to utilize x-forwarded-for, getRemoteAddr should return a list of proxies and we should extract the last IP in the chain but the current implementation extracts the first one which could be a DHCP client IP, it's not a proxy at all. Let's say x-forwarded-for is "a.a.a.a, b.b.b.b, c.c.c.c", getRemoteAddr currently returns a.a.a.a which is the client IP, but I think we should use c.c.c.c, extract the last one, right? |
Thank you for your patience I got it 🙈
What do you think about the above version? When |
Yes, if the x-forwarded-for is set correctly, $remoteAddress would be the nearest proxy IP in the proxy chain, getRemoteAddress() should return the farthest IP in the chain (client IP), and they should never match. Your solution is definitely much better than my pull request, so ignore my PR please. And there are some corner cases to mention but they are all just fine with your solution: Lastly, a little suggestion. To better help users troubleshoot all these kinds of network issues, maybe we can return the IP chains in x-forwarded-for and the $server['REMOTE_ADDR'] instead of a simple boolean value, then we can show them in the console along with the warning message. Without that information it's also OK, because most users can modify the nginx accesss log format or modify php code to write a log to get that information too, with that info it's would be a little easier and time-saving. nextcloud rocks! |
Would you mind updating your pr? The above solution is something we developed together 👍 @nickvergessen when we use #11594 (comment) howto mock |
Sure, I will do it this weekend. |
in your unit test: self::invokePrivate($request, 'item', [['REMOTE_ADDR' => 'fake.addr']]); |
If that doesn't work, add it to server/lib/private/AppFramework/Http/Request.php Lines 324 to 328 in c0a283f
|
As discussed in #11594 when discovering if x-forwarded-for is working properly its not possible to use getRemoteAddr because the "client ip" is returned. For this check the ip of the last hop would be required. Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
As discussed in #11594 when discovering if x-forwarded-for is working properly its not possible to use getRemoteAddr because the "client ip" is returned. For this check the ip of the last hop would be required. Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
As discussed in #11594 when discovering if x-forwarded-for is working properly its not possible to use getRemoteAddr because the "client ip" is returned. For this check the ip of the last hop would be required. Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
As discussed in #11594 when discovering if x-forwarded-for is working properly its not possible to use getRemoteAddr because the "client ip" is returned. For this check the ip of the last hop would be required. Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
Because this is purely a potential logical bug so I skip all the environment and reproduce steps, since the bug is very easy to understand I think.
Nextcloud version: (see Nextcloud admin page)
13 and the master branch.
If the remote address is in the trusted proxy list, here we should return true, right?
The text was updated successfully, but these errors were encountered: