qbittorrent / qBittorrent

qBittorrent BitTorrent client
https://www.qbittorrent.org
Other
28.16k stars 3.97k forks source link

Not binding to specified interface (tun0) after reboot #2741

Closed RainmakerRaw closed 9 years ago

RainmakerRaw commented 9 years ago

Using qbt 3.1.12 on Linux Mint 17.1 x64 Rebecca, with the Cinnamon DE.

With qbt instructed to bind to interface tun0 (VPN), a disconnection of that VPN results in an immediate cessation of all traffic, as one would expect. However if the VPN is not reconnected and for some reason qbt relaunches (eg user-induced restart, a crash, etc) then qbt instantly begins downloading over any available interface (eg the ISP connection) without querying the user.

This is unexpected and (speaking for privacy) dangerous behaviour. It is expected that, even after a reboot, qbt will remain bound to the stated interface and refuse to work unless it is present. Instead, the logs state that the interface (tun0) cannot be found and the tracker and peer connections resume instantly. When checking the advanced settings the tun0 option has disappeared from the list, as it's not immediately active on the host system.

In fact the list of network interfaces should remain, or at least the last selected interface, so that in the event of the VPN going down qbt 'remembers' to stay bound to its interface and await its return. This is an important safety issue for many torrent users, especially those in restrictive and oppressive regimes.

pyro12 commented 9 years ago

I am also experiencing this and agree that qBittorent should remain bound to whatever interface the user selects until the user gives permission for qBittorrent to use another.

I've also noticed that if the selected interface is disconnected, QB stops as expected, but will never restart on it's own if the interface returns. QB must be closed and restarted, but this is less of an issue.

SierraJC commented 9 years ago

Also experiencing this issue. Using qbittorrent-nox on a headless linux server with a VPN, and IP is leaking when "tun0" is not present.

sledgehammer999 commented 9 years ago

QB stops as expected, but will never restart on it's own if the interface returns.

This has been debugged in the past. When your VPN reconnects it gives a different interface/local ip. qbt continues listening to the old ip. You should configure the VPN (maybe its tun driver) to always use the same interface/local ip.

ppolewicz commented 9 years ago

I am looking into this. It seems that there are two separate issues, one with libtorrent working as if nothing happened, when the configured interface is not even present in the system, and second issue described by @sledgehammer999 in the comment, with qbittorrent never recovering after VPN reconnects.

ppolewicz commented 9 years ago

Not working after VPN reconnection is tracked in issue #475

This issue here might be a bug in libtorrent, where their docs claim that not supplying an IP address when creating a session makes the session inoperable, but I've read their code and can't find evidence that this is what happens. If one doesn't pass a valid ip, they just bind to 0.0.0.0. I'm gonna fix #475 first and then look some more into this.

ppolewicz commented 9 years ago

Related issue filed in libtorrent: https://code.google.com/p/libtorrent/issues/detail?id=748

sledgehammer999 commented 9 years ago

I am not sure if this code was in v3.1.12, but in v3.2.0 if qbt doesn't find the configured interface it just errors out and stops setting up libtorrent. And a log entry is produced. @RainmakerRaw can you test v3.2.0 via our PPA? If the problem persists, please copy your log here too(view->execution log).

sledgehammer999 commented 9 years ago

Well, I found the problem. When we create the libtorrent::session object it defaults to the "0.0.0.0" interface. So afterwards when trying to figure out what interface to pass to session::listen_on() results in a non-existent interfacce we just exit that code thus leaving the pre-configured interface (0. 0.0.0). So we either check the interface very early, before creating the "session" object OR we should stop(session::pause()) the session after we find a non-existent interface OR we should pass a bogus interface to listen_on() eg 127.0.0.1.

sledgehammer999 commented 9 years ago

@ppolewicz I now see that you basically say the same thing on your bug report....

ppolewicz commented 9 years ago

2714 is "outgoing connections leak privacy"

2741 (this issue) is "incoming connections leak privacy"

those are two separate problems, but they can share some of fix designs

@sledgehammer999 I linked the libtorrent issue here hoping that you will read my comment before investigating it yourself ;) I am sorry for the long comment below, but I believe it is important to design a good fix for this issue and what you suggested may not be enough:

ad 1. Checking interface very early is not perfect: if the interface will disappear between checking and binding, user privacy will be compromised.

ad 2. Pausing session after we find a non-existent interface can leak data before we find out that the interface doesn't exist. libtorrent has it's own loop in another thread and if it is faster than our checker, pause() call can be late.

ad 3. Even providing a bogus interface to listen_on() would cause current libtorrent implementation to first bind to 0.0.0.0, then potentially leak packets and then to get our listen_on() call. In my understanding (correct me if I'm wrong) current implementation of libtorrent, which does not allow for creation of a pre-paused session, there is no way to create and securely bind it via separate listen_on() call.

design 4: we could create the session with listen address pre-initialized to 127.0.0.1 (there is a constructor that allows this to be done) and then only attempt to bind to other interfaces later or rebind to 0.0.0.0 if user set the interface to "Any". This would make sure we never listen on a bogus interface and no incoming traffic can be found to be embarrassing (so it would reliably fix #2741). Fix implementation seems to be very easy (just use the right libtorrent::session constructor and pass 127.0.0.1 as ip). As far as I know, despite popular belief, 127.0.0.1 is not present in all systems, but we could say we don't care about such malicious configurations.

This would not make sure that no packets are routed when the selected interface is down (something close to #2714), which is an important feature present in other clients (which don't do any traffic unless they bind successfully), In our case, after the fix, it would bind to 127.0.0.1 and then route packets out via whatever default gateway the system has, while some time later after hammering listen_on() for a while we could not find any good interface to listen to, but it could be too late to call pause() as in case of Design 2 above. Therefore only outgoing connections would compromise privacy.

To wrap it up, I recommend initially binding to 127.0.0.1 in libtorrent session constructor to prevent privacy breach by incoming traffic, and I recommend changing libtorrent so that they allow some way of securing privacy of outgoing traffic.