Skip to content

Instantly share code, notes, and snippets.

@unbelauscht
Last active April 23, 2025 11:51
Show Gist options
  • Select an option

  • Save unbelauscht/b0227f3a3b4797ad23600952a0eac527 to your computer and use it in GitHub Desktop.

Select an option

Save unbelauscht/b0227f3a3b4797ad23600952a0eac527 to your computer and use it in GitHub Desktop.
Updates the qbittorrent listener port if natpmp public port of protonvpn changes
#!/usr/bin/env python3
# im too lazy to package that shit, enjoy
# - pip install --break-system-packages qbittorrent-api py-natpmp
import natpmp.natpmp_client
import qbittorrentapi
import time
try:
import natpmp as NATPMP
except ImportError:
import NATPMP
protocol = NATPMP.NATPMP_PROTOCOL_TCP
gateway_ip = "10.2.0.1"
timeout = 55
qbt_conn = dict(
host="127.0.0.1",
port="8080",
username="admin",
password="adminadmin",
)
while True:
mapping = NATPMP.map_port(protocol, 0, 0, 60, gateway_ip)
qbt_client = qbittorrentapi.Client(**qbt_conn)
try:
qbt_client.auth_log_in()
except qbittorrentapi.LoginFailed as e:
print(e)
print("Current port: ", qbt_client.app.preferences.listen_port, "Mapped port: ", mapping.public_port)
if qbt_client.app.preferences.listen_port == mapping.public_port:
print("Port is already correct!")
else:
print("Updating port!")
try:
qbt_client.app.preferences = dict(listen_port=mapping.public_port)
except e:
print(e)
time.sleep(timeout)
# /etc/systemd/system/qbittorrent-portmapper.service
[Unit]
Description=qBittorrent port updater for ProtonVPN
Wants=wg-netns.target
After=wg-netns.target
[Service]
Restart=on-failure
RestartSec=15s
User=qbittorrent
Group=qbittorrent
UMask=0002
Type=simple
ExecStart=python3 -u /usr/bin/proton-qb-updater.py
NoNewPrivileges=true
MemoryDenyWriteExecute=true
ProtectSystem=true
PrivateTmp=true
NetworkNamespacePath=/var/run/netns/protonvpn
BindReadOnlyPaths=/etc/netns/protonvpn/resolv.conf:/etc/resolv.conf:norbind
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/qbittorrent-protonvpn.service
[Unit]
Description=qBittorrent under ProtonVPN
Wants=wg-netns.target
After=wg-netns.target
[Service]
Restart=on-failure
RestartSec=15s
User=qbittorrent
Group=qbittorrent
UMask=0002
Type=exec
ExecStart=/usr/bin/qbittorrent-nox
ExecStop=/bin/kill -s STOP $MAINPID
ExecReload=/bin/kill -s HUP $MAINPID
NoNewPrivileges=true
MemoryDenyWriteExecute=true
ProtectSystem=true
PrivateTmp=true
NetworkNamespacePath=/var/run/netns/protonvpn
BindReadOnlyPaths=/etc/netns/protonvpn/resolv.conf:/etc/resolv.conf:norbind
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/wg-netns.target
[Unit]
Description=WireGuard in Network Namespaces
# /etc/systemd/system/[email protected]
[Unit]
Description=WireGuard Network Namespace (%i)
Wants=network-online.target nss-lookup.target
After=network-online.target nss-lookup.target
[Service]
Type=oneshot
Environment=WG_ENDPOINT_RESOLUTION_RETRIES=infinity
Environment=WG_VERBOSE=1
ExecStart=wg-netns up %i
ExecStop=wg-netns down %i
RemainAfterExit=yes
WorkingDirectory=%E/wireguard
ConfigurationDirectory=wireguard
ConfigurationDirectoryMode=0700
CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_ADMIN
LimitNOFILE=4096
LimitNPROC=512
LockPersonality=true
MemoryDenyWriteExecute=true
NoNewPrivileges=true
ProtectClock=true
ProtectHostname=true
RemoveIPC=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=mnt net
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
[Install]
WantedBy=multi-user.target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment