Skip to content

Client should not use all available interfaces for outgoing requests #24730

Description

@ValdikSS

qBittorrent & operating system versions

  • qBittorrent: 5.2.3
  • libtorrent: 2.1.0
  • Linux

What is the problem?

In short:

  • qBittorrent in its default configuration uses all available network interfaces for outgoing requests
  • To do so, it binds to both IP address and network interface
  • This results in using all interfaces for outgoing requests per se, at least for DHT
  • Most importantly, for L3/Point-to-Point interfaces (almost all tunnels: PPP, PPTP, OpenVPN, WireGuard, GRE, IPIP, ...) this results in using them even if no routes are present

Basically I've only added a GRE tunnel, added the address on it, and qBittorrent started to send UDP packets to DHT peers over it, even if there's no default route is configured for this interface.

Right now, from what I could see in the code and in the behavior, qBittorrent auto-detects network interfaces and configures 0.0.0.0, :: as lt::settings_pack::listen_interfaces and an empty string as lt::settings_pack::outgoing_interfaces

for (const QString &portString : asConst(portStrings))
endpoints << (ip + portString);
outgoingInterfaces << ip;
#endif
}
}
const QString finalEndpoints = endpoints.join(u',');
settingsPack.set_str(lt::settings_pack::listen_interfaces, finalEndpoints.toStdString());
LogMsg(tr("Trying to listen on the following list of IP addresses: \"%1\"").arg(finalEndpoints));
settingsPack.set_str(lt::settings_pack::outgoing_interfaces, outgoingInterfaces.join(u',').toStdString());
m_listenInterfaceConfigured = true;

According to libtorrent documentation, outgoing_interfaces:

This string is a comma-separated list of IP addresses and interface names. An empty string will not bind TCP sockets to a device, and let the network stack assign the local address.

but listen_interfaces

These are also used for outgoing uTP and UDP tracker connections and DHT nodes.

It seems that supplying 0.0.0.0, :: to listen_interfaces means that it will not use 0.0.0.0, :: in a sense of "bind to 0.0.0.0 and use default routing", but it handles it in a "smart" way of enumerating all interfaces and binding to all of them (opens the socket for each device and binds it both to the address (bind()) and to the device (setsockopt SO_BINDTODEVICE), as seen with strace).

I hope the comment for listen_interfaces means that every interface would be used only for DHT/trackers, and not for data downloading, but mentioning µTP makes me doubt it.

Steps to reproduce

  1. On Linux, create dummy GRE interface: ip link add testgre type gre remote 1.0.0.0
  2. Set it up: ip link set testgre up
  3. Assign the address: ip addr add 192.168.60.1/32 dev testgre
  4. Run tcpdump -n -i testgre
  5. Launch qBittorrent

Result

First-launched qBittorrent starts to discover DHT peers over testgre interface, even if there's no default route over it.

15:21:40.106980 IP 192.168.60.1.64051 > 67.215.246.10.6881: UDP, length 111
15:21:40.107009 IP 192.168.60.1.64051 > 87.98.162.88.6881: UDP, length 111
15:21:40.107033 IP 192.168.60.1.64051 > 185.157.221.247.25401: UDP, length 111
15:21:40.107056 IP 192.168.60.1.64051 > 212.129.33.59.6881: UDP, length 111

Expected result

qBittorrent might listen for incoming connections on all interfaces but should not attempt to do any outgoing activity over non-default-route interface, especially with bypass of main routing table.

Additional context

No response

Log(s) & preferences file(s)

Default qBittorrent configuration (~/.config/qBittorrent and ~/.local/share/Qbittorrent clean).

Metadata

Metadata

Assignees

No one assigned

    Labels

    NetworkIssues related to network connectivity

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions