Skip to content

Library should not use all available interfaces for outgoing requests #8642

Description

@ValdikSS

Cross-post from qBittorrent qbittorrent/qBittorrent#24730, as the same behavior is with Deluge, and is a default behavior of libtorrent.

  • qBittorrent: 5.2.3 / Deluge 2.2.0
  • libtorrent: 2.1.0 / 2.0.11
  • Linux

What is the problem?

In short, libtorrent by default uses all available network interfaces at least for DHT and torrent announces (see #7902).
For L3/Point-to-Point interfaces (almost all tunnels: PPP, PPTP, OpenVPN, WireGuard, GRE, IPIP, ...) this results in using network interface 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

https://github.com/qbittorrent/qBittorrent/blob/e70f13d46a42b204559d0e7b16a19eeca522fe9e/src/base/bittorrent/sessionimpl.cpp#L2247-L2259

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

libtorrent 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.

The feature of what libtorrent currently does is useful, but it should be activated if listen_interfaces is set to something like auto.
If 0.0.0.0, it set, I'd expect to do literally that: bind to 0.0.0.0 and follow routing decisions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions