Deployed April 29, 2026 on CT100. Replaces the per-app SOCKS5 proxy approach for outbound privacy on torrent indexers, Hardcover lookups, etc.
Before: Shelfmark and the *arr stack used a SOCKS5 proxy (autossh tunnel to seedbox at port 1080) for outbound traffic that needed to look non-residential. Each app had to be individually configured.
After: A WireGuard interface on CT100 (wg0) routes all outbound from every container through UltraCC’s NL endpoint. Apps don’t need any per-service proxy config; they just talk to the internet normally and the tunnel handles the rest.
| Tunnel endpoint | UltraCC NL โ 45.86.221.26:13012 |
| Server pubkey | bOBo86jrNKBikLqOFdksL41bTnQHWWHynM3/v3yq2Vg= |
| Client (CT100) IP | 10.13.13.2/32 |
| Listen port | 51820 (CT100 side) |
| AllowedIPs | 0.0.0.0/0 (full tunnel) |
| MTU | 1420 |
| Public IP from CT100 | 45.86.221.26 (NL exit) |
Private key + PSK for this tunnel were passed through chat โ rotation pending. Replace the peer in the UltraCC panel and re-import the config to rotate.
Container (e.g., sonarr)
โ HTTPS to indexer.com
โผ
Docker bridge 172.16.x.0/24
โ (MASQUERADE in nat POSTROUTING)
โผ
CT100 routing table
โ default via wg0 (table 51820, fwmark 0xca6c)
โผ
wg0 โ WireGuard interface
โ encrypted UDP to 45.86.221.26:13012
โผ
CT100 eth0 โ OPNsense โ ISP โ UltraCC NL
โ
โผ
Public internet (source IP appears as 45.86.221.26)
LAN traffic (192.168.8.0/24, 172.16.0.0/12, 100.123.0.0/16) bypasses the tunnel. Only outbound to the public internet goes through wg0.
The pre-existing CT100 firewall acts as the kill-switch โ if wg0 drops, the OUTPUT chain has no rules permitting public-internet egress, so all packets are dropped (with explicit LOG+DROP rule at the end). No traffic leaks to the ISP if the tunnel fails.
Permitted egress (whitelist in /etc/iptables/rules.v4):
192.168.8.0/24โ LAN172.16.0.0/12โ Docker bridges100.123.0.0/16โ NetBird overlay- DNS to
192.168.8.53โ Pi-hole - SSH to
46.232.210.50:22โ seedbox (for autossh tunnels still in use) - UDP to
45.86.221.26:13012โ WireGuard handshake to UltraCC - Anything via
wg0(the tunnel itself)
Everything else: LOG + DROP.
WireGuard’s MTU (1420) is smaller than Docker bridges (1500). Without MSS clamping, TCP from containers fails on TLS handshake โ packets get fragmented or silently dropped, connections hang. Symptoms: ping works (small packets) but curl https://... times out.
Fix is in the mangle table:
iptables -t mangle -A FORWARD -o wg0 -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -A POSTROUTING -o wg0 -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Both rules are persisted in /etc/iptables/rules.v4.
# Enabled on CT100:
systemctl is-enabled wg-quick@wg0 # โ enabled
systemctl status wg-quick@wg0 # โ active
/etc/wireguard/wg0.conf holds the peer config (chmod 600, root-only). On boot, wg-quick@wg0.service brings up the interface, applies the iptables rules in /etc/iptables/rules.v4 via iptables-restore, and the kill-switch + MSS clamp + tunnel are all live.
Verify tunnel from CT100:
pct exec 100 -- wg show wg0
# Expect: handshake within last 2-3 minutes, transfer counters incrementing.
pct exec 100 -- curl -s https://api.ipify.org
# Expect: 45.86.221.26 (NOT your home WAN IP).
Verify from a container (e.g., Sonarr):
pct exec 100 -- docker exec sonarr sh -c \
'curl -sS -o /dev/null -w "%{http_code} via %{remote_ip}" https://api.ipify.org'
# Expect: 200 via <some-ipify-IP>; the response body shows 45.86.221.26
Uptime Kuma monitor (id 76, “WireGuard Exit IP (UltraCC)”) does this exact check every 5 minutes โ keyword 45.86.221.26 against https://api.ipify.org. Alerts via Gotify if the tunnel drops or routing changes.
If TCP fails but ping works: MSS clamp rules are missing (see MSS clamping).
If the whole tunnel is dead: check for handshake errors. Often the cure is systemctl restart wg-quick@wg0. If UltraCC re-keyed, you’ll need a fresh config from their panel.
All of them โ every CT100 container’s outbound traffic exits via 45.86.221.26. This is by design.
The WireGuard tunnel replaced the SOCKS5 proxy (autossh-socks / seedbox-socks) for outbound privacy routing โ apps no longer need per-service proxy configuration. However, the SSH RPC tunnels are NOT redundant and remain actively required:
| Tunnel | Purpose | Status |
|---|---|---|
transmission-tunnel.service (hpve) |
SSH tunnel :13010 โ seedbox Transmission RPC. Used by Sonarr/Radarr/Lidarr for download management | Active โ required |
autossh-transmission.service (CT100) |
AutoSSH tunnel :13010 โ seedbox Transmission RPC | Active โ required |
autossh-nzbget.service (CT100) |
AutoSSH tunnel :16789 โ seedbox NZBGet | Active โ required |
autossh-socks.service (CT100) |
SOCKS5 :1080 โ seedbox NL exit | Active โ legacy, replaced by WireGuard for most apps |
WireGuard handles privacy routing (making outbound traffic appear from NL); it does not replace the RPC control tunnels that let the *arr apps communicate with download clients on the seedbox.
When the tunnel was deployed, a snapshot was taken at:
/root/wg-deploy-backup-20260429-150327/
rules.v4.before # iptables before WG
iptables.live.before
To roll back: iptables-restore < /root/wg-deploy-backup-*/rules.v4.before && systemctl stop wg-quick@wg0 && systemctl disable wg-quick@wg0.