mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-11-13 12:13:36 +01:00
feat(youko): firewall and tune transmission, stop homepage RPC probes (#326)
* fix(youko): stop homepage from probing the authenticated transmission RPC
The siteMonitor hit /transmission/rpc unauthenticated, so every probe returned 401 and counted against transmission's anti-brute-force threshold.
* feat(youko): tune transmission and firewall its network namespace
Raise the upload limit and queues, relax required encryption to preferred, and add a default-drop nftables input chain inside the netns so the peer port stays open while everything else is closed. Allowlist the nftables 'iif' keyword for typos.
* feat(youko): export transmission metrics and add a Grafana dashboard
nixpkgs has no transmission exporter, so add a small stdlib Python exporter that queries the authenticated netns RPC on loopback, scrape it from VictoriaMetrics, and ship a Transmission dashboard.
* fix(youko): cap transmission upload at 2500 kB/s
30 MB/s ignored the 50 Mbps uplink; keep seeding around 20 Mbps.
* Revert "feat(youko): export transmission metrics and add a Grafana dashboard"
This reverts commit 9df7a26526.
This commit is contained in:
1 parent
e5b95affa6
commit
1256570a84
3 files changed
+41
-7
No files matched your search
@@ -45,4 +45,7 @@ extend-ignore-re = [
|
||||
|
||||
# The upstream dictionary maps UPnP to "UOnP", which is wrong; keep UPnP.
|
||||
"UPnP",
|
||||
|
||||
# nftables keyword `iif` (input interface); the spell checker wants `if`.
|
||||
"iif",
|
||||
]
|
||||
+2
-1
@@ -74,7 +74,8 @@
|
||||
icon: transmission.png
|
||||
href: "https://transmission.writefor.fun/"
|
||||
description: Transmission BitTorrent client
|
||||
siteMonitor: "https://transmission.writefor.fun/"
|
||||
# No siteMonitor: the RPC requires auth, so the probe returns 401 and
|
||||
# every hit counts against transmission's anti-brute-force threshold.
|
||||
- Immich:
|
||||
icon: immich.png
|
||||
href: "https://immich.writefor.fun/"
|
||||
|
||||
@@ -34,6 +34,27 @@ let
|
||||
|
||||
ip = "${pkgs.iproute2}/bin/ip";
|
||||
sysctl = "${pkgs.procps}/bin/sysctl";
|
||||
nft = "${pkgs.nftables}/bin/nft";
|
||||
|
||||
# The namespace is a first-class host on br0, so once the router's IPv6
|
||||
# firewall is relaxed it is reachable from the Internet with no host firewall
|
||||
# in front of it. Keep the peer port open (that is the point) and the RPC
|
||||
# LAN-only; drop everything else.
|
||||
netnsFirewall = pkgs.writeText "transmission-netns.nft" ''
|
||||
table inet transmission-fw {
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
iif "lo" accept
|
||||
ct state established,related accept
|
||||
meta l4proto icmp accept
|
||||
meta l4proto ipv6-icmp accept
|
||||
tcp dport 51413 accept
|
||||
udp dport 51413 accept
|
||||
udp dport 6771 accept
|
||||
ip saddr ${myvars.networking.lanCidr} tcp dport 9091 accept
|
||||
}
|
||||
}
|
||||
'';
|
||||
in
|
||||
{
|
||||
# Join the shared fileshare group so transmission can read/write files
|
||||
@@ -89,7 +110,9 @@ in
|
||||
# 0 = Prefer unencrypted connections,
|
||||
# 1 = Prefer encrypted connections,
|
||||
# 2 = Require encrypted connections; default = 1)
|
||||
encryption = 2;
|
||||
# Keep it at "prefer": forcing encryption drops peers that cannot do
|
||||
# MSE, which costs upload opportunities on public swarms.
|
||||
encryption = 1;
|
||||
|
||||
# rpc = Web Interface
|
||||
rpc-port = 9091;
|
||||
@@ -101,7 +124,9 @@ in
|
||||
# After this amount of failed authentication attempts is surpassed,
|
||||
# the RPC server will deny any further authentication attempts until it is restarted.
|
||||
# This is not tracked per IP but in total.
|
||||
anti-brute-force-threshold = 20;
|
||||
# Health-check probes (homepage/uptime-kuma) hit the authenticated RPC
|
||||
# gateway and each 401 counts, so keep this well above a 401 burst.
|
||||
anti-brute-force-threshold = 100;
|
||||
rpc-authentication-required = true;
|
||||
|
||||
# Comma-delimited list of IP addresses.
|
||||
@@ -144,9 +169,10 @@ in
|
||||
# "normal" speed limits
|
||||
speed-limit-down-enabled = true;
|
||||
speed-limit-down = 30000; # KB/s
|
||||
# Keep seeding under the 50 Mbps uplink (~20 Mbps).
|
||||
speed-limit-up-enabled = true;
|
||||
speed-limit-up = 500; # KB/s
|
||||
upload-slots-per-torrent = 8;
|
||||
speed-limit-up = 2500; # KB/s
|
||||
upload-slots-per-torrent = 16;
|
||||
|
||||
# Start torrents as soon as they are added
|
||||
start-added-torrents = true;
|
||||
@@ -155,7 +181,7 @@ in
|
||||
# When true, Transmission will only download
|
||||
# download-queue-size non-stalled torrents at once.
|
||||
download-queue-enabled = true;
|
||||
download-queue-size = 5;
|
||||
download-queue-size = 10;
|
||||
|
||||
# When true, torrents that have not shared data for
|
||||
# queue-stalled-minutes are treated as 'stalled'
|
||||
@@ -167,7 +193,8 @@ in
|
||||
# When true. Transmission will only seed seed-queue-size
|
||||
# non-stalled torrents at once.
|
||||
seed-queue-enabled = true;
|
||||
seed-queue-size = 10;
|
||||
# With 30+ torrents, 10 was leaving most seeds queued (never uploading).
|
||||
seed-queue-size = 50;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -210,6 +237,9 @@ in
|
||||
${ip} -n ${netns} link set ${nsVeth} up
|
||||
${ip} -n ${netns} addr add ${nsIp}/24 dev ${nsVeth}
|
||||
${ip} -n ${netns} route add default via ${myvars.networking.mainGateway}
|
||||
|
||||
# Apply the namespace firewall after the interface is up.
|
||||
${ip} netns exec ${netns} ${nft} -f ${netnsFirewall}
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user