qBittorrent-ClientBlocker: a Go daemon that bans peers by the client they announce
一款适用于 qBittorrent/Transmission (Beta)/BitComet (Beta, Partial) 的客户端屏蔽器, 默认屏蔽包括但不限于迅雷等客户端. A client blocker compatible with qBittorrent/Transmission (Beta)/BitComet (Beta, Partial) which is prohibited to include but not limited to clients such as Xunlei.
At a glance
- What is it?
- Simple-Tracker/qBittorrent-ClientBlocker is a Go program that logs into your torrent client's web interface, reads the peer list, and blocks peers whose client identifier matches a block list, with regex support, a hot reloaded rule set and an optional Docker image. It is a tracker-side filter, not a security tool, and it depends on the web UI of qBittorrent, Transmission or BitComet.
- Who is it for?
- qBittorrent-ClientBlocker fits a private tracker operator who wants to keep a known set of clients out of a swarm without touching the client software, and who accepts that the tool works by reading the client's own web interface. It does not fit a user who wants a firewall, a rate limit, or protection against a determined attacker, since it filters by a self declared string.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What it actually blocks, and on whose side of the connection
The project description says it is a client blocker for qBittorrent, Transmission in beta, and BitComet in beta and partial, and that by default it blocks clients including but not limited to Xunlei.
The mechanism is worth being precise about, because it determines what the tool can and cannot do. Every BitTorrent peer announces a client identifier, a short string such as qBittorrent or Transmission, in the peer handshake. This program reads the peer list from your torrent client's web interface, compares each announced identifier against a block list, and asks the client to ban the ones that match.
So it is a filter on a self declared string, applied by the client you already run. It is not a firewall rule, it does not rate limit, and it does not inspect payload. A peer that announces a benign identifier and is actually the software you are trying to exclude is not affected by it, and a peer that announces a banned identifier is excluded regardless of what it is doing. That is a fine thing for a tracker operator trying to steer a swarm toward a preferred client ecosystem, and it is not a security control.
The description also makes clear the intent, and it is worth naming the context so the tool is not mistaken for something else. The topic tags are qbittorrent, transmission and bitcomet, and the project name is prefixed with Simple-Tracker, a private tracker operation. The audience is an operator of a private tracker who wants a specific client mix on their swarm.
For a public tracker or an individual user, the same code runs and means something different, and the rule set that makes sense is not the same.
The web UI is the API, and that is the whole integration
The prerequisite is stated in one line: the client web UI feature must be enabled.
That is the entire integration surface. The program logs into the torrent client's web interface with a username and password, and drives the client over HTTP rather than through a plugin. The dependency list backs this up. PuerkitoBio/goquery is an HTML parser, and the program uses it to read the client's pages. dlclark/regexp2 is the regular expression engine for the block list matching, and tidwall/jsonc parses the client's JSON responses, which is how the Web API based clients such as qBittorrent are handled.
The consequence is that the tool is coupled to the shape of the client's web pages, not to a stable documented interface. When a client changes its login flow or its peer list markup, this program has to change with it, and the fix is not in your hands.
The README does say that occasional errors can usually be ignored, and it lists three reasons: network problems, client timeouts, and Transmission periodically rotating its CSRF token. That third one is the clearest admission of the coupling. A client that rotates a token under the program is a client whose web interface has a state model the program has to follow.
The dependency on the credentials is also worth stating plainly. The configuration needs clientURL, clientUsername and clientPassword, and the README explains that you must fill these in if the blocker does not run on the same machine as the client, or if the client is not installed in the default path, or if the client does not support reading its configuration file automatically. The one exception is when the client has an IP subnet allowlist enabled, in which case the username and password can be left empty.
There is also a client version detection feature, currently supported for qBittorrent, and the README says it is safe to ignore errors that occur during detection.
The screening loop runs every six seconds, and the cleanup every hour
The configuration table is where the actual behaviour of the tool becomes clear, and the intervals are the most consequential settings.
The interval setting, in seconds, is the screening loop interval and it does not support hot reload. Each cycle fetches the relevant information from the backend and uses it to decide and to ban, and the documentation states that a short interval reduces the time before a ban takes effect but may cause the client to stutter, while a long interval lowers CPU usage.
The default is 6 seconds. The cleanInterval setting, the ban cleanup interval, defaults to 3600 seconds, and a short interval unbans expired peers sooner once they reach the ban duration, while a long interval helps merge the cleanup of expired peer logs. The banTime setting, also 3600 seconds by default, is how long a peer stays banned, and the documentation notes that a short value unbans peers faster.
So the shape of the behaviour is: poll the client, ban what matches, and periodically unbban what has served its time. The polling interval is what determines how long a banned peer keeps uploading, and the default of six seconds is a compromise rather than a guarantee.
The history settings are the memory side of the same design. historyRetention, 3600 seconds by default, is how long IP and torrent peer statistics are kept, with 0 disabling the expiry. historyMaxEntries, 100000 by default, caps the number of entries of each kind of statistic, and when the cap is reached the least recently updated records are cleared first, with 0 meaning no limit. Cleaning does not unban peers.
The gcInterval setting, 60 seconds by default, is the active garbage collection interval, and 0 disables it, with a shorter interval controlling memory at the cost of CPU. The restartInterval setting, also 6 seconds by default, exists for clients where the block list does not take effect immediately, Transmission being the case, and works by restarting the torrent, with the documentation warning that too short an interval may cause the ban not to apply.
Running it: a release archive, a config file, and the client shortcut
The normal install path is a download. Get the archive from the GitHub Release page, extract it, and you may need to modify the bundled config.json.
The project ships binaries for a wide range of targets, and the download table in the README is the most useful part of it. On macOS there is darwin-arm64 for Apple M series and darwin-amd64 for Intel. On Windows there is windows-amd64, windows-386 for older PCs, windows-arm64 for newer tablets and laptops, and windows-arm for old ARMv7 hardware such as Surface RT. On Linux there is linux-amd64 for most NAS and server machines, linux-386, linux-arm64 for servers and boards such as Oracle or Raspberry Pi, and linux-armv* for older boards, with the note to check /proc/cpuinfo or try from the highest architecture down. Other Linux, NetBSD, FreeBSD, OpenBSD and Solaris builds follow the same pattern.
The configuration decision comes next. If the blocker runs on the same machine as the client and the option to skip local client authentication is not enabled, and the password is not empty and has not been set manually, then the config file must be changed and clientPassword filled in. If the blocker is not on the same machine, or the client is not in the default path, or the client does not support reading its config file automatically, then clientURL, clientUsername and clientPassword must be filled in.
After that, start the blocker and watch the output to confirm it is working. On Windows you can optionally change the client's shortcut so that the client and the blocker start together, and the README gives the exact command string for qBittorrent, which launches the blocker if it is not already running and then starts the client.
For background operation there are three platform specific options, all optional. A LaunchAgent user agent on macOS, a systemd service configuration on Linux, and on Windows the tray icon and a global hotkey, CTRL+ALT+B, to show and hide the window.
The Docker image, and why the config file beats the environment variables
There is a Docker image on Docker Hub, and the README documents two ways to configure it.
The first is a config file mount. Create a config.json somewhere sensible, fill in clientURL, clientUsername and clientPassword, and run the container with the file and the rule cache directory mounted.
docker run -d \
--name=qbittorrent-clientblocker --network=bridge --restart unless-stopped \
-v /path/config.json:/app/config.json \
-v /path/rule-cache:/app/cache/rules \
simpletracker/qbittorrent-clientblocker:latestThe second uses environment variables, and it is the one the project warns about. You have to set useENV to true first, and then the settings are passed as environment variables with the same names as the configuration file.
docker run -d \
--name=qbittorrent-clientblocker --network=bridge --restart unless-stopped \
-v /path/rule-cache:/app/cache/rules \
-e useENV=true \
-e debug=false \
-e logPath=logs \
-e ruleCachePath=cache/rules \
-e blockList='["ExampleBlockList1", "ExampleBlockList2"]' \
-e clientURL=http://example.com \
-e clientUsername=exampleUser \
-e clientPassword=examplePass \
simpletracker/qbittorrent-clientblocker:latestThe warning is specific. If the settings are relatively complex, the blockList may not take effect, and the recommendation is therefore that using environment variables is not advised for complicated setups.
That is a fair warning, because the environment variable path converts variables to a configuration file, and a conversion that has to carry a JSON array of block list entries is exactly where a subtle quoting mistake becomes a rule that silently does not match.
Both examples are marked as templates for reference, and both tell you to replace the paths, with a note that the file has to exist before the mount. The Dockerfile at the repository root shows what the image contains, an Alpine base with jq and socat installed, the compiled binary, the lang/ directory for localisation, and an entrypoint.sh that is the container entry point.
Block lists, hot reload, and the config file that is not a config file
A few details are worth pulling out because they explain how the tool stays current.
The block list is configurable, case insensitive, and supports regular expressions. That last point matters, because a client identifier is a short arbitrary string and a plain substring match gets both false positives and false negatives. The default list ships in the repository as blockList.json, with an optional blockList-Optional.json beside it, and there is also a list URL mechanism, with updateInterval set to 86400 seconds by default, described as the interval for updating the list URLs, blockListURL and ipBlockListURL, with the note that a sensible interval improves update efficiency and lowers network use.
Hot reloading of the configuration is supported, and the ruleCachePath setting, defaulting to cache/rules, is the remote rule cache directory. The description says the valid cache is restored first at startup and on configuration reload, with the update running in the background, and that an empty string disables the disk cache.
The repository root is slightly unusual, and it explains itself. There is both config.json and config.toml, plus a config_additional.json referenced by the command line flag for an additional config file path. The config table is headed by the note that the Docker version is configured through environment variables of the same names, by automatically converting environment variables into a configuration file.
The language directory, lang/, is shipped in the Docker image, which tells you the interface is localised, and the dependency Xuanwo/go-locale is there to detect the system locale. The Go module itself is small and mostly free of opinion, and the go.mod asks for Go 1.20, with the release build pinned to a slightly newer 1.20.13 alpine image.
Editorial conclusion
qBittorrent-ClientBlocker fits a private tracker operator who wants to keep a known set of clients out of a swarm without touching the client software, and who accepts that the tool works by reading the client's own web interface. It does not fit a user who wants a firewall, a rate limit, or protection against a determined attacker, since it filters by a self declared string. Check three things before you rely on it. Check the client you run, because the web UI must be enabled and the supported versions are qBittorrent 4.1 and up, Transmission 3.0 and up in beta, and BitComet 2.0 and up in beta with partial support. Check the Docker path if you use it, because the image is built for amd64 and arm variants and the README recommends the config file mount over the environment variables, since complex settings may not take effect through the environment. And check the timing defaults, because the screening loop runs every six seconds by default while the cleanup loop runs every hour, so a peer is not blocked instantly. The last push was on 2026-10-06, the newest release listed is 3.8b9 from 2026-10-01, and the license is MIT.
Frequently asked questions
What does qBittorrent-ClientBlocker block?
It blocks torrent peers whose announced client identifier matches a block list, by driving the web interface of qBittorrent, Transmission or BitComet. By default it blocks clients including but not limited to Xunlei, and the block list supports custom entries, is case insensitive and supports regular expressions.
Which torrent clients does qBittorrent-ClientBlocker support?
qBittorrent 4.1 and later, Transmission 3.0 and later in beta, and BitComet 2.0 and later in beta with partial support. The web UI of the client must be enabled, and the program logs in with clientURL, clientUsername and clientPassword.
How do I run qBittorrent-ClientBlocker with Docker?
Pull the image with docker pull simpletracker/qbittorrent-clientblocker:latest, then run it with a config.json mounted to /app/config.json and a rule cache directory mounted to /app/cache/rules. You can also configure it with environment variables, but the project says that is not advised for complicated setups because the blockList may not take effect.
How quickly does qBittorrent-ClientBlocker ban a peer?
The screening loop runs on the interval setting, which defaults to 6 seconds and does not support hot reload, while the ban cleanup interval and the ban duration default to 3600 seconds each. A shorter screening interval reduces the delay before a ban takes effect but may cause the client to stutter.
Does qBittorrent-ClientBlocker need extra software for Windows?
On Windows the program can show and hide its window from the system tray or with the global hotkey CTRL+ALT+B, and the README notes that some users have reported this feature may affect blocking, for reasons that are unclear. The image for Linux, macOS and the BSDs does not need it.
What license is qBittorrent-ClientBlocker released under?
MIT, with a LICENSE file at the root of the repository. The newest listed release is 3.8b9 from 2026-10-01, and the last push was on 2026-10-06.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/simple-tracker-qbittorrent-clientblocker)