qBittorrent
qBittorrent copied to clipboard
WebUI: Support for "Enable cookie Secure flag" when the WebUI is behind an HTTP reverse proxy
Suggestion
Currently, this feature is disabled unless the "Use HTTPS instead of HTTP" option is toggled and information about certificates is provided. Users should be able to enable the cookie Secure flag for WebUI behind an HTTP reverse proxy, which manages the certificate for HTTPS.
Use case
Hosting the WebUI behind the Cloudflare Tunnel, which Cloudflare handles the HTTPS part, and there is no point in setting up HTTPS for connections inside the machine.
Extra info/examples/attachments
No response
Currently, this feature is disabled unless the "Use HTTPS instead of HTTP" option is toggled and information about certificates is provided.
For qbt viewpoint, it is doing the correct thing. It wouldn't know that you were intercepting/redirecting the traffic.
Hosting the WebUI behind the Cloudflare Tunnel, which Cloudflare handles the HTTPS part, and there is no point in setting up HTTPS for connections inside the machine.
Since you are intercepting/redirecting the traffic, you should modify the header on Cloudflare side. Not sure if Cloudflare provide such functionality though.
It wouldn't know that you were intercepting/redirecting the traffic.
The X-Forwarded-Proto header can be used to determine if the login request is received via HTTPS and set the Secure flag automatically. Some established software has been doing this for years, so I think it's a valid feature.
Two directions:
- Add a new option under the "Enable reverse proxy support" section to detect the forwarded protocol, and allow the "Enable cookie Secure flag" option to be enabled. (which clearly states the new behaviour)
- Allow the "Enable cookie Secure flag" option to be enabled when reverse proxy support is on, and detect the forwarded protocol to set the Secure flag. (which makes it a feature of the reverse proxy support)
These two options would not change the behaviour unless the user decided to, which should be safe to implement.
Since you are intercepting/redirecting the traffic, you should modify the header on Cloudflare side. Not sure if Cloudflare provide such functionality though.
What about it? Is Cloudflare configurable for the case here?
The X-Forwarded-Proto header can be used to determine if the login request is received via HTTPS and set the Secure flag automatically. Some established software has been doing this for years, so I think it's a valid feature.
Alright, but is this feature a necessity for qbt? I would not like to make it more complicated. I mean, I would like to learn why an app would care/detect about reverse proxy presence. Shouldn't the reverse proxy be transparent to the app and user in an ideal world?
Shouldn't the reverse proxy be transparent to the app and user in an ideal world?
👍
Since you are intercepting/redirecting the traffic, you should modify the header on Cloudflare side. Not sure if Cloudflare provide such functionality though.
What about it? Is Cloudflare configurable for the case here?
No out-of-box solutions: Adding Secure HttpOnly to Set-Cookie header?
The Worker service mentioned in this post now comes with free quotas, but I think the scripting for this purpose is still complicated.
I mean, I would like to learn why an app would care/detect about reverse proxy presence. Shouldn't the reverse proxy be transparent to the app and user in an ideal world?
Sorry, may I ask your thoughts about the existing feature of the reverse proxy support, which obtains the real client IP accessing the WebUI from the X-Forwarded-For header? I think there is not much difference between it and obtaining the protocol used, both should improve the website security.
Instead, I think managing HTTPS certificates is what a web application should not be responsible for, since it violates the Separation of Concerns and is not a long-term solution considering the certificate should be renewed regularly. But I also understand that it may be very useful for Windows users etc.
The Worker service mentioned in this post now comes with free quotas, but I think the scripting for this purpose is still complicated.
And you are just suggesting to move that complication into qbt instead. It doesn't disappear.
I mean, I would like to learn why an app would care/detect about reverse proxy presence. Shouldn't the reverse proxy be transparent to the app and user in an ideal world?
Sorry, may I ask your thoughts about the existing feature of the reverse proxy support, which obtains the real client IP accessing the WebUI from the
X-Forwarded-Forheader? I think there is not much difference between it and obtaining the protocol used, both should improve the website security.
Well, counter-question won't help the discussion. I'll only do this one time. I still don't see the necessity for an app to learn the presence of reverse proxy. Is the feature convenient? sure but strictly speaking it isn't qbt concern (IMO) nor responsibility to implement it. If anything, it is the user whom deployed the reverse proxy should ensure everything work smoothly. That's why every competent reverse proxy has powerful rule engines to modify the data headers. (I guess now you know why Cloudflare wants to charge you for it) And do you have anything to say about my original question?
Instead, I think managing HTTPS certificates is what a web application should not be responsible for, since it violates the Separation of Concerns and is not a long-term solution considering the certificate should be renewed regularly. But I also understand that it may be very useful for Windows users etc.
I believe you are mixing the app (and it comes with a bundled server) with the reverse proxy. These are two separate entities and should be treated separately. Strange that you mentioned "Separation of Concerns" here...
From https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#block_access_to_your_cookies
A cookie with the Secure attribute is only sent to the server with an encrypted request over the HTTPS protocol. It's never sent with unsecured HTTP (except on localhost)...
It seems qbt didn't follow the "except on localhost" part. This should be a valid bug.
And you are just suggesting to move that complication into qbt instead. It doesn't disappear.
I believe the level of complexity is different, making it do so from the root is easier than mangling HTTP responses with Cloudflare Worker scripts (I can explain the course of action if you are interested). And even if I implemented it with Cloudflare, it's just for me, while in qbt it may benefit more users. And to be clear, I am not asking anyone to do it, I originally thought I might try to do a PR if the idea was not opposed, but I guess that's not the case here.
Well, counter-question won't help the discussion. I'll only do this one time. I still don't see the necessity for an app to learn the presence of reverse proxy. Is the feature convenient? sure but strictly speaking it isn't qbt concern (IMO) nor responsibility to implement it. If anything, it is the user whom deployed the reverse proxy should ensure everything work smoothly. That's why every competent reverse proxy has powerful rule engines to modify the data headers. (I guess now you know why Cloudflare wants to charge you for it) And do you have anything to say about my original question?
-
Alright, but is this feature a necessity for qbt?
-
I hope this is not the "original question" you are mentioning, obviously, you have authority over this if you want.
-
I mean, I would like to learn why an app would care/detect about reverse proxy presence. Shouldn't the reverse proxy be transparent to the app and user in an ideal world?
-
I still cannot answer this question more directly in a way specific to the topic here, because I don't understand why you were asking. I don't know your definition of "learn the presence of reverse proxy" while qbt has "reverse proxy support" and will obtain the real client IP from the
X-Forwarded-Forheader. Does that count? Or did you just generalise the question too much without intention? I didn't want to say these too directly originally, but I am sorry since that sounds like a mere counter-question for you. In my defence, I did mention that I don't see how the "reverse proxy support" is technically different from checking another header.
It seems qbt didn't follow the "except on localhost" part. This should be a valid bug.
@Func86 Could you explain how does Cloudflare connect to webUI in your case? is it both on localhost? If that is the case, it might be possible make some adjustments.
It seems qbt didn't follow the "except on localhost" part. This should be a valid bug.
@Func86 Could you explain how does Cloudflare connect to webUI in your case? is it both on localhost? If that is the case, it might be possible make some adjustments.
Yes, but I guess the doc means it needs the Host header of the request to be localhost?
Yes, but I guess the doc means it needs the Host header of the request to be localhost?
What is the value of Host header Cloudflare sends to webUI?
UPDATE:
I dived into Firefox codebase and in the end it comes to this: https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
It is referring to the request URL when it say "origin is a tuple origin". So it is not the Host header.
Hum, I think the linked PR will not help the case here. As far as I can see, the env().clientAddress would be set to the IP in the X-Forwarded-For header when the original value is within the trusted reverse proxy list. I don't think anyone would want to disable the reverse proxy support, and risk being banned because of a random guy trying to brute-force the password or turn off the auth failure ban (or if the ban would not work on loopback addresses, that's even worse).
As far as I can see, the env().clientAddress would be set to the IP in the X-Forwarded-For header when the original value is within the trusted reverse proxy list.
You read it wrong. You are mixing up env().clientAddress and m_clientAddress, those two are not the same.
It would be nice if you can actually test it and verify that it also works for you. Our review process will go faster if the feature/fix can be verified.
It would be nice if you can actually test it and verify that it also works for you. Our review process will go faster if the feature/fix can be verified.
Tested with the build artifact, and it works for me. But I am really not sure if the behaviour change is correct, because it will serve cookies with the Secure flag even if the reverse proxy serves clients with HTTP. I guess you will say that it's the user's or the reverse proxy's responsibility to make it work, but the change is effective out-of-box with the default config, which may affect some existing users.
But I am really not sure if the behaviour change is correct, because it will serve cookies with the Secure flag even if the reverse proxy serves clients with HTTP. I guess you will say that it's the user's or the reverse proxy's responsibility to make it work, but the change is effective out-of-box with the default config, which may affect some existing users.
@glassez What do you think? Should we ignore reverse proxy presence? or cater to it? The related PR #21260 is correctly implemented. It is the people who are running reverse proxy will be potentially affected. I would say it is quite easy from them to address this issue since one-liner solution exists.
/rant I always knew acknowledging reverse proxy presence is going to be an endless rabbit hole. Now that I think about it. From all related specs/docs that I've read, none of them mentioned reverse proxy. From this viewpoint, this issue is asking something creative and (quite possibly) isn't the norm. I doubt it should be taken seriously.
I'm sorry, I don't know much about this topic. The only thing that seems clear to me is that the presence of a reverse proxy server should be absolutely transparent to clients. But I have not found any detailed information about how the interaction between the reverse proxy and the real servers (server applications) is supposed to be. From what I saw about using a reverse proxy, this implies the fact that the entire system (the reverse proxy server and the servers it serves) is configured simultaneously, i.e. the server DOES NOT ASSUME that it is possibly working behind the reverse proxy at the moment, but it KNOWS that it is working behind the reverse proxy. It follows from this that all those things that are required to support working behind a reverse proxy should be optional so that anyone who wants to configure their qBittorrent instance to work behind a reverse proxy can tell it (configure it) to behave in the desired way.
I did a survey on other web apps I happened to host, so for your information:
- MediaWiki: Have a config for the secure flag (true|false|"detect"), which defaults to true when the "redirect to HTTPS" feature is enabled, otherwise defaults to "detect", which will check the
X-Forwarded-Protoheader (from the$_SERVERvariable set by the web server). - Grafana, OpenObserve: Have a config for the secure flag, which defaults to false, and has no dependency on other configs compared to qbt.
- phpMyAdmin: Set the secure flag for requests via HTTPS, which is determined from a lot of
$_SERVERvariables set by the web server, including theX-Forwarded-Protoheader. - Cockpit: Claims to set the secure flag for requests via HTTPS, which will check the
X-Forwarded-Protoheader, but with a bug of behaviour inconsistency. - Comentario: Takes a base URL config, and sets the secure flag when the protocol of the base URL is
https.
None of the above have any exceptions for localhost or loopback addresses.
I think although the specs said the user agent can send cookies with the secure flag to localhost over HTTP, the web app probably should not actively set the secure flag for localhost, that's way more unconventional than checking the X-Forwarded-Proto header.
I decided to support X-forwarded-proto for this use case. PR #21260 is updated.