Skip to content
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

Add WebUI reverse proxy source IP resolution #15047

Merged
merged 12 commits into from
Jun 23, 2021
Merged

Conversation

HiFiPhile
Copy link
Contributor

This PR is a revive of #9176 .

Since the orignal author @qix67 is no longer maintaining the PR and based on the discussion some collaborators are also in favor of this feature, I rebased the PR to latest master.

It also includes some refactor and renaming.

Co-authored-by: qix67
Co-authored-by: HiFiPhile admin@hifiphile.com

@FranciscoPombal FranciscoPombal added Network Issues related to network connectivity WebUI WebUI-related issues/changes labels May 31, 2021
@HiFiPhile HiFiPhile force-pushed the proxy branch 2 times, most recently from a325aa2 to d2dcc47 Compare May 31, 2021 21:30
@glassez
Copy link
Member

glassez commented Jun 1, 2021

@HiFiPhile
If you want to contribute to qBittorrent you should consider our Coding Guidelines and follow them in your contributions.

@glassez glassez removed the WebUI WebUI-related issues/changes label Jun 1, 2021
Copy link
Contributor

@thalieht thalieht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things not mentioned in coding guidelines

src/base/http/connection.cpp Outdated Show resolved Hide resolved
src/base/http/connection.cpp Outdated Show resolved Hide resolved
src/gui/optionsdialog.ui Outdated Show resolved Hide resolved
src/webui/www/private/views/preferences.html Outdated Show resolved Hide resolved
@glassez glassez changed the title Add WebUI reverse proxy source ip resolution. Add WebUI reverse proxy source ip resolution Jun 4, 2021
src/webui/webapplication.h Outdated Show resolved Hide resolved
src/webui/webapplication.cpp Outdated Show resolved Hide resolved
@HiFiPhile HiFiPhile force-pushed the proxy branch 2 times, most recently from 68cf37c to 3a1ccf4 Compare June 4, 2021 07:47
@glassez glassez changed the title Add WebUI reverse proxy source ip resolution Add WebUI reverse proxy source IP resolution Jun 5, 2021
{
if (clientAddress.setAddress(remoteIp) && clientAddress.isGlobal())
{
hasGlobalIp = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can return clientAddress; here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what about changing it?

PS I hope that your disagreements with @qix67 do not mean that this PR is not ready?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what about changing it?

I've changed it in the last commit.

PS I hope that your disagreements with @qix67 do not mean that this PR is not ready?

No we only have some differences in proxy configuration, this PR can fit both cases.


if (!forwardedFor.isEmpty())
{
// client address is the 1st global IP in X-Forwarded-For or, if none available, the 1st IP in the list
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, client address is always first. Any subsequent addresses become to midway proxies. Am I wrong?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are wrong but it is a fairly common error.

When I access to qbittorrent from my work, I have the following the X-forwarded-for
172.29.225.237,194.254.4.90,10.0.3.254,127.0.0.1

  • First IP is the local IP of my desktop PC at work.
  • 2nd IP is the public IP used by my work proxy.
  • 3rd IP is the local IP of my reverse proxy at home. This reverse proxy runs on my gateway and performs SSL termination.
  • 4th IP is added by nginx running on the same computer as qbittorrent (proxy_pass).

The correct IP is always the last public IP, here, the 2nd IP.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are wrong but it is a fairly common error.

I was only guided by https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For#syntax

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is correct, the first IP is the real client IP but it does not mean it is a public IP, that's why it is kinda misleading.

The worst case I ever seen is something like that (combination of proxy, VPN and reverse proxies):
192.168.0.1, public_IP, 10.0.23.1, public_IP2, 172.29.226.1, 127.0.0.1

In this case, the correct public IP is public_IP2 (last public IP). I admit, it is a very unusual settings but it is a valid value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thanks.

One more question.
We specify the address of the proxy server to make sure that the request (containing X-Forwarded-For header) is received from it. This assumes that requests can come from both the proxy server address and another address. Is it a valid usecase to have a configured proxy server and at the same time some other access channels for untrusted clients?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for a safe reverse proxy configuration, it's better to delete X-Forwarded-For at frontend, so someone from the
outside cannot spoof this header. It also ensures the first IP in the header is the client IP.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for a safe reverse proxy configuration, it's better to delete X-Forwarded-For at frontend, so someone from the
outside cannot spoof this header. It also ensures the first IP in the header is the client IP.

I don't think it will change anything as the frontend will always add the incoming IP address at the end of X-Forwarded-For string. Anything existing before should be assumed unsafe and purely informational. That's why taking the last public IP is important.

Moreover, it is not always possible to reconfigure the reverse proxy.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We specify the address of the proxy server to make sure that the request (containing X-Forwarded-For header) is received from it. This assumes that requests can come from both the proxy server address and another address. Is it a valid usecase to have a configured proxy server and at the same time some other access channels for untrusted clients?

The point is that if it is only available through a proxy (as it should be, IMO; i.e., if we have a proxy, then it should only be available through it), then we do not need to have a proxy address check, but just specify whether it should resolve the client address or not.

It looks like we should still allow user to explicitly set the proxy address for better security. But maybe we can be more lenient in another case, i.e. allow the user to enable client address resolution without explicitly specifying the proxy address?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But maybe we can be more lenient in another case, i.e. allow the user to enable client address resolution without explicitly specifying the proxy address?

It's hard to say, people do it differently.
For example Gitea allows client address resolution from 127.0.0.0 by default, SFTPGo needs to specify proxy address whitelist.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just that we could provide more options to the user by placing more responsibility on them (of course, by warning them about this). If he is confident in the security of his network environment settings, then allow him not to explicitly specify the proxy server address.

In any case, this is not a blocking comment. So if you don't agree, you can continue as is and wait for user feedback.

@@ -761,6 +761,26 @@ void Preferences::setWebUICustomHTTPHeaders(const QString &headers)
setValue("Preferences/WebUI/CustomHTTPHeaders", headers);
}

bool Preferences::isWebUIReverseProxyEnabled() const
{
return value("Preferences/WebUI/ReverseProxyEnabled", false).toBool();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, "reverse proxy enabled" confuses. One may think that there is some built-in "reverse proxy" feature.
Maybe "forwarded client IP enabled/used/allowed"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "Reverse proxy support" ? I think the word "reverse proxy" makes the purpose clear.


QString Preferences::getWebUIReverseProxyAddress() const
{
return value("Preferences/WebUI/ReverseProxyAddress", "").toString().trimmed();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't it be used with some kind of "forward" proxy as well? I would avoid explicitly specifying "reverse" term.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a list of "trusted_proxies" is not a bad idea.

src/webui/webapplication.cpp Outdated Show resolved Hide resolved
src/webui/webapplication.cpp Outdated Show resolved Hide resolved
@glassez glassez requested a review from Chocobo1 June 10, 2021 06:25
@glassez glassez added this to the 4.4.0 milestone Jun 10, 2021
src/base/preferences.cpp Outdated Show resolved Hide resolved
src/base/http/types.h Show resolved Hide resolved
src/base/preferences.cpp Outdated Show resolved Hide resolved
src/webui/api/appcontroller.cpp Outdated Show resolved Hide resolved
src/webui/www/private/views/preferences.html Outdated Show resolved Hide resolved
src/webui/webapplication.cpp Outdated Show resolved Hide resolved
src/webui/webapplication.cpp Outdated Show resolved Hide resolved
src/webui/webapplication.cpp Outdated Show resolved Hide resolved
src/webui/webapplication.cpp Outdated Show resolved Hide resolved
src/webui/webapplication.cpp Outdated Show resolved Hide resolved
@Walter-o
Copy link

My input:

The idea of a "Trusted proxies list" is good in case people have multiple proxies

The warning for configuring is also in the right place since misconfiguration can lead to IP impersonation

1 thing i would propose as a tiny bonus is being able to manually enter the header name that is checked for IP.
Some proxies are already configured or forced to use a single header like "X-Forwarded-For" or "CF-Client-IP",

Personally i have been using "X-Forwarded-For" but there is a chance some other people might be unhappy.

Anyways this pull request is already a banger i can recommend

src/webui/webapplication.cpp Outdated Show resolved Hide resolved
src/webui/webapplication.cpp Outdated Show resolved Hide resolved
Copy link
Member

@Chocobo1 Chocobo1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one last comment, I'm fine with the rest.

src/webui/webapplication.cpp Outdated Show resolved Hide resolved
@HiFiPhile HiFiPhile requested a review from Chocobo1 June 20, 2021 14:48
@glassez glassez merged commit f5315d9 into qbittorrent:master Jun 23, 2021
@glassez
Copy link
Member

glassez commented Jun 23, 2021

Thank you!

@glassez
Copy link
Member

glassez commented Jun 23, 2021

@HiFiPhile
I hope you intend to maintain it if there are any related problems in the future.

@HiFiPhile
Copy link
Contributor Author

I hope you intend to maintain it if there are any related problems in the future.

Yes in general I maintain my commits.

IceCodeNew pushed a commit to IceCodeNew/qBittorrent-Enhanced-Edition that referenced this pull request Jun 23, 2021
Co-authored-by: qix67
Co-authored-by: HiFiPhile <admin@hifiphile.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Network Issues related to network connectivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants