Skip to content

Add ip subnet whitelist for bypassing webui auth - #6779

Merged
glassez merged 3 commits into
qbittorrent:masterfrom
Piccirello:disable-web-auth
Nov 20, 2017
Merged

Add ip subnet whitelist for bypassing webui auth#6779
glassez merged 3 commits into
qbittorrent:masterfrom
Piccirello:disable-web-auth

Conversation

@Piccirello

Copy link
Copy Markdown
Member

Requested in #924.
Provides a more permanent solution than this wiki page while also allowing the web API auth to be disabled

This feature is useful when qBitttorrent is used behind a reverse proxy with its own authentication scheme, or when it's running on a local network.

@Piccirello

Copy link
Copy Markdown
Member Author

@evsh, @glassez , @Chocobo1, @sledgehammer999: would someone be able to review this PR, or at least comment on it? This is a highly requested feature and I know a lot of people would benefit from having it.

@Chocobo1

Chocobo1 commented Jun 14, 2017

Copy link
Copy Markdown
Member

This is a highly requested feature

Don't think so, care to point it out?

I know a lot of people would benefit from having it.

How so? having a simple/mindless password is better than none.
Or do you mind to talk about your specific usage that will need this PR?

@Chocobo1

Copy link
Copy Markdown
Member

This feature is useful when qBitttorrent is used behind a reverse proxy with its own authentication scheme, or when it's running on a local network.

I agree we could have an option for bypassing auth for users on LAN, for WAN, it's best to keep auth on.

@Piccirello

Copy link
Copy Markdown
Member Author

Don't think so, care to point it out?

#924
#4581
#6518
Disable authentification of webGUI
[Solved] Disable Webui Authorization

A method of disabling webgui auth is even provided in the Compiling qBittorrent on Debian and Ubuntu guide. However, that method requires users to modify their login.html file.

@Chocobo1

Chocobo1 commented Jun 14, 2017

Copy link
Copy Markdown
Member

And if users disable authentication, while on public Wi-Fi, how does that protect them then?

I don't get what you're trying to say.
It seems you're talking about different layers of security measures (e.g. public wifi, wifi with WPA2 or not, qbt session auth, http or https).
While a security measure prevents possible exploits (as side effect or not), you shouldn't mix it (multiple security measures) up when thinking about disabling a specific measure.

@Piccirello
Thank you.
However, after skimming through those issues, I read that bypassing LAN is the common request, not bypassing all.

If I wasn't clear enough, I only support the idea of adding a checkbox stated: "Bypass authentication for users on LAN".

@glassez

glassez commented Jun 14, 2017

Copy link
Copy Markdown
Member

the idea of adding a checkbox stated: "Bypass authentication for users on LAN".

But this checkbox exists, isn't it?

@Chocobo1

Copy link
Copy Markdown
Member

But this checkbox exists, isn't it?

No, the one exists is Bypass authentication for localhost.

@Piccirello

Copy link
Copy Markdown
Member Author

I agree that the "disable for LAN" option makes more sense from a security standpoint. I'll modify my changes and update when finished.

@Piccirello Piccirello changed the title Add option for disabling web authentication Add option for disabling webui LAN authentication Jun 20, 2017
@Piccirello

Piccirello commented Jun 21, 2017

Copy link
Copy Markdown
Member Author

I see that env_.clientAddress is storing my ipv4 address 10.0.0.3 in the ipv6 format ::ffff:10.0.0.3. Will this behavior be exhibited by all clients, or will env_.clientAddress ever be in ipv4 format for some users?

Comment thread src/webui/abstractwebapplication.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't be OR in this place?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There are many conditions here so it would be better to have two helper functions: isLoopbackAddress and isLANAddress.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Shouldn't be OR in this place?

The LAN conditionals return true if the address isn't localhost OR if local auth is enabled. Therefore if an OR is used and a user connects with a LAN ip, the function would return true regardless of the LAN conditionals.

That being said, development is still underway, so don't start picking apart my changes just yet ;)

Once I'm finished I'll squash the changes and update this PR.

@Chocobo1

Copy link
Copy Markdown
Member

or will env_.clientAddress ever be in ipv4 format for some users?

you'll need to handle 3 formats:

  1. ipv6
  2. ipv4 mapped ipv6, see: https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses
  3. ipv4

@Piccirello

Copy link
Copy Markdown
Member Author

Ok, all three scenarios are now handled by the LAN check. Commits are also squashed. What're your thoughts?

Comment thread src/webui/abstractwebapplication.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would prefer const QHostAddress &clientAddress

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

Comment thread src/webui/abstractwebapplication.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would prefer const QHostAddress &clientAddress

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

Comment thread src/webui/abstractwebapplication.h Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These 2 can move to src\base\utils\net if you want

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

At least it shouldn't be member of AbstractWebApplication.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

Comment thread src/webui/abstractwebapplication.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please use:

if ()
else if ()
else

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No. Don't do it!
It is considered "bad form" to use else after return.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK, but at least it should be

if ()
  return ...
else if ()
  return ...
return true;

to save 1 comparison.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You are again mistaken. It saves nothing.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second comparison will be executed only if the first returns false, because otherwise we will just return from the function.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You are again mistaken. It saves nothing.

You're right. I my head was obsessed with something else.

Comment thread src/webui/abstractwebapplication.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

0a00

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

0a00 and a00 are equivalent.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I know, the suggestion is for clarity.

Comment thread src/base/utils/net.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

use isInSubnet(const QHostAddress &subnet, int netmask)?
i.e. isInSubnet(QLatin1String("10.0.0.0"), 8)
and below

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Why? They are equivalent.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

They are equivalent.

to save 1 function call in our code?

@Piccirello Piccirello Jun 25, 2017

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

isInSubnet(QLatin1String("10.0.0.0"), 8)

What's the purpose of using QLatin1String in this instance? It's not currently used for creating the ipv6 mapped 127.0.0.1 address.

@Chocobo1 Chocobo1 Jun 25, 2017

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's the purpose of using QLatin1String in this instance?

QHostAddress is constructed via QHostAddress(const QString &address) and then from http://doc.qt.io/qt-5/qlatin1string.html#details :

This is a bit longer to type, but it provides exactly the same benefits as the first version of the code, and is faster than converting the Latin-1 strings using QString::fromLatin1().

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

Comment thread src/base/utils/net.h Outdated

@Chocobo1 Chocobo1 Jun 25, 2017

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

clientAddress -> addr or some other name
there is no concept of "client" in these 2 helper functions

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Done.

I still see "clientAddress"...

Comment thread src/base/utils/net.cpp Outdated

@Chocobo1 Chocobo1 Jun 25, 2017

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

there are non-trivial computation in this func, maybe it make sense to add the following?

if (clientAddress.isInSubnet(QLatin1String("0.0.0.0"), 0)) {
  // ipv4
}
else {
  // ipv6
}

UPDATE: example updated.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

example updated

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

Comment thread src/base/utils/net.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we use implicit type conversion in our codebase, so I'll say there is no need for explicit QHostAddress() construction here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I can't compile without explicitly passing QHostAddress

base/utils/net.cpp:51:60: error: no matching function for call to ‘QHostAddress::isInSubnet(QLatin1String, int) const’
             if (addr.isInSubnet(QLatin1String("0.0.0.0"), 0)) {
                                                            ^
base/utils/net.cpp:51:60: note: candidates are:
In file included from /opt/qt55/include/QtNetwork/QHostAddress:1:0,
                 from base/utils/net.cpp:30:
/opt/qt55/include/QtNetwork/qhostaddress.h:116:10: note: bool QHostAddress::isInSubnet(const QHostAddress&, int) const
     bool isInSubnet(const QHostAddress &subnet, int netmask) const;
          ^
/opt/qt55/include/QtNetwork/qhostaddress.h:116:10: note:   no known conversion for argument 1 from ‘QLatin1String’ to ‘const QHostAddress&’
/opt/qt55/include/QtNetwork/qhostaddress.h:117:10: note: bool QHostAddress::isInSubnet(const QPair<QHostAddress, int>&) const
     bool isInSubnet(const QPair<QHostAddress, int> &subnet) const;
          ^
/opt/qt55/include/QtNetwork/qhostaddress.h:117:10: note:   candidate expects 1 argument, 2 provided
base/utils/net.cpp:62:9: warning: control reaches end of non-void function [-Wreturn-type]
         }
         ^

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hmmm, OK then.

@Chocobo1

Copy link
Copy Markdown
Member

my review is finished.
👍 for this PR.

Comment thread src/base/utils/net.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please drop else branch and place return statement outside it.

Comment thread src/base/utils/net.h Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Done.

I still see "clientAddress"...

Comment thread src/webui/abstractwebapplication.h Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Move this include to .cpp

@glassez

glassez commented Jun 25, 2017

Copy link
Copy Markdown
Member

And one more question. Is bypass auth for lan but require it for localhost the expected behavior?

@glassez

glassez commented Nov 5, 2017

Copy link
Copy Markdown
Member

@Piccirello, I've done it for you (rebased and squashed). You need to force update your local branch.

@glassez

glassez commented Nov 5, 2017

Copy link
Copy Markdown
Member

GitHub's "Resolve conflicts" editor is just too tempting!

You shouldn't use GitHub editor. When you need to resolve conflicts in your PR, you need to rebase your local branch on top of current qBittorrent master (manually resolving some conflicts if required) and then force push it on GitHub.

@Piccirello

Copy link
Copy Markdown
Member Author

Thanks @glassez.

Chocobo1
Chocobo1 previously approved these changes Nov 7, 2017
@glassez

glassez commented Nov 7, 2017

Copy link
Copy Markdown
Member

Thanks @glassez.

@Piccirello, what the hell are you doing? Are you kidding me?
I squashed your fixup commits for you, I even fixed the remaining coding style issues for you... You don't have to do anything anymore. The only thing you had to do is "to force update your local branch" (as I suggested you), to make it identical with PR branch on GitHub. But what did you do? You did the opposite! You just returned everything as it was (with the exception of fixed conflict). I don't even know what to say... Maybe "Please squash your commits and fix the coding style".
(I'm sorry if I was overly emotional).

zeule
zeule previously approved these changes Nov 7, 2017
@glassez

glassez commented Nov 7, 2017

Copy link
Copy Markdown
Member

Please squash your commits and fix the coding style

Ok. You can forget about commits squashing since they are unrelated. But coding style issues are still be fixed.

@glassez glassez left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Fix coding style.
The rest is ok.

@Piccirello

Piccirello commented Nov 7, 2017

Copy link
Copy Markdown
Member Author

Fix coding style.
The rest is ok.

Care to point out the style issues? I re-pushed the repo because you squashed unrelated commits.

Comment thread src/base/utils/net.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wrong curly brace position.

Comment thread src/base/utils/net.cpp Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Inconsistent else block. Curly braces are required because of curly braces in if.

@Piccirello
Piccirello dismissed stale reviews from zeule and Chocobo1 via 0de2f17 November 9, 2017 03:39
@Piccirello

Copy link
Copy Markdown
Member Author

@evsh @Chocobo1 Any further changes required?

@WolfganP

Copy link
Copy Markdown

Great work @Piccirello
I hope this great addition is promptly merged into master.

@glassez
glassez merged commit f41cb80 into qbittorrent:master Nov 20, 2017
@glassez

glassez commented Nov 20, 2017

Copy link
Copy Markdown
Member

@Piccirello, thank you!
Thanks for all reviewers as well!

@Piccirello

Copy link
Copy Markdown
Member Author

Woohoo! Glad we were able to get this merged.

Thanks for the back and forth over many months @Chocobo1 @glassez @evsh

Comment thread src/webui/prefjson.cpp
QStringList authSubnetWhitelistStringList;
for (const Utils::Net::Subnet &subnet : pref->getWebUiAuthSubnetWhitelist())
authSubnetWhitelistStringList << Utils::Net::subnetToString(subnet);
data["bypass_auth_subnet_whitelist"] = authSubnetWhitelistStringList.join("\n");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Unfortunately I noticed it only now... Why have you chosen this out-of-context way to encode this list? We should send it as (json) list, isn't it? I'm sure this should be fixed soon.

@nomandera

Copy link
Copy Markdown

Posting for posterity. If you wish to turn of authentication completely, say in the scenario where the web interface is protected by a separate TLS nginx/apache/trafik/haproxy reverse proxy you can add 0.0.0.0\0 to allow the entire IPv4 space which includes the internet.

Insert obvious warning: dont do this if dont know what you are doing, authentication is there for a reason.

@Piccirello
Piccirello deleted the disable-web-auth branch July 15, 2019 00:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WebUI WebUI-related issues/changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants