Problem
Presentation
Recently, I tried out some networking shenanigans. I was attempting to isolate the route across a commercial VPN with a SOCKS5 server. Programs elsewhere on the LAN would be configured to pass through that proxy when I desired to move traffic out the VPN. qBittorrent (5.1.2) was one such program, marked to proxy announces and peer connections. Unfortunately, this use of a SOCKS5 proxy in qB presented an issue with announces to a certain tracker. Announces were rejected, and I received a message reported back of ‘port 1 is blacklisted.’
Explanation
The problem boils down to the listening port being unset when a proxy is configured and ‘use proxy for peer connections’ is enabled. This effectively disables inbound peer connections, and makes that fact known to trackers through your announces.
Tracker operators can choose to blacklist clients which say they listen on certain ports. For at least one piece of tracker software, this is interpreted as port 1. Presumably the tracker in question for me blacklists the entire privileged port range.
This behavior was implemented in qB with the understanding that one cannot accept unsolicited incoming connections through a SOCKS proxy by design. To be connectable when making use of the proxy feature for peer connections, one would have to consider additional networking intervention such as a reverse TCP proxy to route inbound traffic from the proxy server back to the client machine.
This is obviously out of the scope of the BitTorrent client, and it was presumed that broadcasting that the client is unconnectable to trackers would be better for swarm health considering the very reasonable assumption that the majority of proxy users wouldn’t go to the lengths required to be otherwise.
That said, this frankly opinionated behavior isn’t uniformly applied in qB; when the client knows your unconnectable from other means, it doesn’t unset the listening port. I’d call this an inconsistent and unintuitive implementation detail.
Solution
Initial attempt
I attempted to follow this blog post ᵃ to resolve this issue, rebuilding libtorrent 2.0.11 with a custom patch to source code. It compiled successfully, yet restarting the program yielded a failure to announce to any trackers.
After talking with a friend and Claude about it, we’re thinking the patch is too aggressive and likely results in libtorrent making direct connections through the primary physical interface, enp8s0 in my case, which fail due to VPN client routing rules (I haven’t removed the workstation VPN client yet, wanting to wait and insure everything is behaving as expected.)
What worked
Digging around further, I found a pending PR to libtorrent which aims to properly fix the issue. Discussing further with my friend, we decided that modifying qB to hardcode the flag this PR implements seemed like the best move forward in lieu of waiting for both projects to incorporate the changes.
This was a fairly straightforward task, being an Arch user. Their package management system makes it trivially easy to modify core packages for custom compilation jobs, but I didn’t even have to go that far. Since core packages use release binaries, and I needed to modify source code, I checked AUR for -git versions, and these were readily available.
Implementation
An important note
The tracker in question that I wanted to get this working for explicitly forbids running development builds of approved BitTorrent clients. My solution re-compiles qB against the 5.1.x release branch while adding experimental code. This is technically spoofing, as we have modified the source code and diverged from that of the official release.
If you’re running into this same issue, and the site that’s cucking you has a similar rule, consider whether it’s worth risking your account before following this guide. The PR to libtorrent which fixes this problem is in review, and very well could be merged soon. The changes to accommodate this new feature are trivial to implement in BitTorrent clients relying on that library. You might not have to wait long before the fix becomes merely upgrading your client and changing a setting!
After going through all this work, I decided not to move forward with the application changes, as I was not comfortable with risking my private tracker accounts. Regardless, I publish this information for those who would find some benefit.
Set up the build environment
These commands just download the latest AUR package snapshots. The PKGBUILD files may have been updated since writing of this post, so do bear that in mind.
Patch libtorrent build file
libtorrent-rasterbar-2_0-git/PKGBUILD
Main change here is to the source directive, moving from the official repo to the fork by the user whom submitted the PR we’re interested in (Masong19hippow/libtorrent on the ListenonTCPWithProxy branch)
Create custom patchfile
qbittorrent-git/src/libtorrent-v5_1_x-PR8003.patch
This is the patch that creates and sets the new hardcoded option to qB that was added by the libtorrent PR.
Patch qbittorrent build file
qbittorrent-git/PKGBUILD
Similarly, we change the source directive here, but only to move from main to the release branch, v5_1_x. We also add the prepare() block to patch in the aforementioned file.
The rest of the changes in these PKGBUILD diffs are to update the package name and version metadata. It’s not essential, but I wanted to try to conform to AUR standards despite not publishing these. Sortof gave up halfway, through. 😋
Build, install, test
Restart qB, and we’re good to go. Valid announces ought to now be sent to the tracker in question, with it reporting back a state of ‘Working!’
I tested this with a fresh qB configuration and an infohash pointed at local tracker software to be able to confirm that the tracker indeed receives an announce including a valid listening port.
Finishing touches
System reconfiguration
To prevent future system upgrades from touching our custom packages, we need to inform pacman of that desire. Modify /etc/pacman.conf and add a line under [options] declaring IgnorePkg = libtorrent-rasterbar-git qbittorrent-git. Remember to check qB’s release notes periodically! Once we can move back to a mainline release, reinstall qbittorrent from core, and remove that line from the pacman configuration. There’ll be a new checkbox under the proxy settings to enable the listening port at that point.
qBittorrent reconfiguration
The last set of changes you might consider making lie in the ‘Advanced’ tab of the ‘Preferences’ modal:
- Set ‘Network Interface’ to the system’s primary physical adapter
- Set ‘IP address to bind to’ appropriately, depending on how your SOCKS server is configured (the IPv4 address if IPv4 only, or ‘Any’ if dual-stack.)
These settings work together to a) to only listen on that interface and IP(s) for incoming peer connections, and b) inform the proxy code path to only initiate outbound connections through the same route (qB issue #11735.)
This isn’t necessary to prevent leaks, since connections to the proxy server through other interfaces merely won’t be able to route to the intended destination. Regardless, this is proper/tidy networking to want to enforce upon the client.
Confirm that these settings are achieving the expected result by checking the Execution Log. You shouldn’t see messages like SOCKS5 proxy error. Address: (LAN IP):(Listening port). that are unexpected. Link-local addresses are expected to generate errors, as traffic across them isn’t routable. However, if you see timed out on a routable LAN IP, this indicates the proxy server isn’t responding.