Repository navigation
Releases: gioxx/Syno-TransmissionVPNShield
Releases · gioxx/Syno-TransmissionVPNShield
Release list
0.3.0
- New: dead-tunnel detection.
VPN_IFcan stay up, address and all, while the VPN session behind it carries nothing (seen with DSM VPN Center + AirVPN: routing all green, port-testunknown, torrents stalled for hours). When the tunnel has received no bytes since the last reconcile pass, the shield probes it with a request bound toVPN_IF(at most everyTUNNEL_CHECK_SEC, default 60s); 3 failed probes in a row log aWARNand, withAUTO_RECOVER_VPN, reconnect the profile, sharing the existing cooldown and 6-hour cap. A tunnel moving data is never probed. - Fix:
recover-vpngave up with "tun0 is still up after disconnect" when DSM accepted the disconnect but left the profile'sopenvpnrunning. It now terminates those processes (--config client_<id>, TERM then KILL) before reconnecting; Transmission is already stopped at that point, so nothing can leak. - Upgrade notes:
TUNNEL_CHECK_SECis appended toetc/guard.confautomatically.
0.2.9
- Fix (UI): 0.2.8 read Transmission's state with
synopkg status, but the status page doesn't run as root, and as non-rootsynopkgcan't read the service state ("status_code":263, "failed to get unit status") and reportsstopeven for a running Transmission. With the RPC push failing for another reason (wrong credentials) the page would have said "Transmission is stopped". Transmission now counts as running whenever atransmission-daemonprocess exists, and as stopped only when there is none andsynopkgagrees.
0.2.8
- Fix (UI): with Transmission stopped (for example right after a shield upgrade with
AUTOSTART_TRANSMISSION="0"), the status page blamedRPC_USER/RPC_PASSfor the failing peer-port push. It now says Transmission is stopped, how to start it, and suggestsAUTOSTART_TRANSMISSION="1"when it's off; the port chip reads "waiting for Transmission" instead of "push failing". The credentials alert is kept for when Transmission is running, or its state can't be read, and the push still fails.
0.2.7
- New - automatic VPN recovery: with
DSM_VPN_NAMEset (and the newAUTO_RECOVER_VPN, default1), the reconcile daemon runsrecover-vpnby itself when the forwarded port tests closed 3 times in a row, instead of waiting for someone to notice the red chip and run the Task Scheduler script. While the port tests closed it is re-tested every 2 minutes, so a real outage is acted on in ~5 minutes. Rate-limited byAUTO_RECOVER_COOLDOWN_SEC(default 30 min) andAUTO_RECOVER_MAX_PER_6H(default 3); past the cap the shield logs anERRORand stops redialing until the window frees up. - New - Transmission is never left stopped by a failed recovery:
recover-vpnmarks Transmission as held when it stops it; if the run then bails out (tunnel still up after disconnect, slow to come back, script interrupted, reboot mid-run), reconcile restarts Transmission as soon as the VPN, routes and ip rules are all in place - the same safety checks asAUTOSTART_TRANSMISSION. If the run left the profile disconnected (reconnect failed), the shield redials it every 5 minutes until the tunnel is back. - Fix:
recover-vpnre-issues the disconnect once whenVPN_IFis still up 15s after the first one, instead of giving up - seen live, where only a second manual run got through. - Fix:
recover-vpnno longer touches the VPN whensynopkg stopdidn't actually stop Transmission (previously the failure was ignored, which could open a leak window on kernels without the kill switch), and two runs (automatic + manual) can no longer overlap. - Fix: the cached
port-testresult is dropped whenever a newtransmission-daemonprocess is detected, whatever restarted it - previously only a successfulrecover-vpnrun cleared it, so a manual start left a stale "closed" in the UI for up to 10 minutes. - Fix:
/usr/syno/binis added toPATHby the shared library, sosynopkgis found even from contexts with a minimalPATH(plainssh host command, some Task Scheduler runs). - Change: the "failed to set Transmission peer-port via RPC" warning is logged once after 3 consecutive failures (plus a line when pushes work again), instead of every 30 seconds while Transmission is restarting or stopped.
- Tests + CI: new suites for
recover-vpn(disconnect retry, stuck tunnel, failed stop/connect, lock handling, shield stopped mid-run),postinst(upgrade migration ofguard.conf), the web UI alerts and the Kuma push verdict, on top of newreconcilecoverage for the closed-port streak, automatic recovery and Transmission resume. A newTestsGitHub workflow runs all of them on every pull request and push tomain, and the release build now only starts once they pass. Every suite runs against an isolatedPKG_DIR, so running them on a NAS with the shield installed never writes into the live package'svar/. - Fix: the closed-port streak is tied to the port it was counted for, so changing
FORWARDED_PORTstarts a new streak; a recovery lock left behind by a reboot no longer blocks automatic recovery when its PID gets reused by another process; and stopping the shield while a recovery is finishing can no longer leave Transmission running without the shield's rules.
0.2.6
- Fix:
recover-vpndidn't actually fix a stuck forwarded port in practice - confirmed live against a real AirVPN session stuck for days.synovpnc reconnect, the CLI command it used to redial the tunnel, reports success (Reconnect [...] ... done) without actually tearing down and re-establishing the connection whenever DSM still considers it up; the OpenVPN process PID and uptime never changed.recover-vpnnow drives the same DSM web API Control Panel → VPN's own Connect/Disconnect buttons use (SYNO.Core.Network.VPN) - looking up the profile's internal id by name across every VPN Center connection type, then explicitly disconnecting and reconnecting - which is what genuinely redials the tunnel.DSM_VPN_PROTOCOLis no longer needed for this (kept for backward compatibility). - New: every
recover-vpnstep is now also written tovar/shield.log, so a run triggered from Task Scheduler shows up in the web UI's log panel - previously it only echoed to stdout, visible solely in that task's own Task Scheduler run result. - New: the Transmission
port-testcheck now runs from the reconcile daemon itself, once perPORT_TEST_INTERVAL_SEC, instead of only when Uptime Kuma push monitoring is configured. A successful RPC push only means "Transmission was told to listen on this port" - it says nothing about whether your VPN provider actually forwards it, which is exactly what stayed invisible in the all-green dashboard case diagnosed live on this project (tunnel up, RPC push succeeding, port genuinely closed). The web UI's Forwarded Port chip now reflects the realport-testresult, and turns up a dedicated alert (with a link to runrecover-vpnwhen configured) when the port tests closed despite a successful push. - Refactor: the port-test logic moved from
guard-pushinto the shared_common.sh(port_test()), reused by both reconcile and the Kuma push daemon against the same cache file, so there's a single always-current source of truth regardless of which caller last refreshed it.
0.2.5
- New:
recover-vpnnow accepts the DSM VPN Center profile name as an optional first argument (recover-vpn AirVPN), and the protocol as a second (recover-vpn AirVPN l2tp). No more editingguard.confjust to try it once - the argument overridesDSM_VPN_NAME/DSM_VPN_PROTOCOLwhen given, and the script still falls back toguard.confwhen called with no arguments.
0.2.4
- New:
recover-vpn- a one-shot Task Scheduler script for the case where the shield looks fully green (VPN up, RPC push succeeding) but the forwarded port still tests closed. Some VPN providers (AirVPN confirmed) bind a forwarded port to the current tunnel session; if that binding didn't happen cleanly, only reconnecting the VPN itself fixes it. For DSM VPN Center connections,recover-vpnautomates that: it stops Transmission, callssynovpnc reconnectfor the profile in the newDSM_VPN_NAMEguard.conf key (DSM_VPN_PROTOCOLdefaults toopenvpn), waits forVPN_IFto come back up, forces a reconcile, and only restarts Transmission once the shield's reconcile daemon is confirmed actually running - see Port still closed even though everything else is green?. Third-party OpenVPN/WireGuard clients reconnect from their own app instead; the shield reconciles automatically onceVPN_IFcomes back up. - Fix:
ENFORCE_KILLSWITCH_WHEN_VPN_DOWN="0"didn't actually disable the kill switch.reconcilealways installs it while the VPN is up regardless of this setting, and nothing removed it again once the VPN dropped with the setting at0- so "0= blackhole only" wasn't true in practice.reconcilenow removes a stale kill-switch rule in that case, but only once the blackhole route and the UID policy rule that actually routes Transmission's traffic into it are both confirmed in place for this pass - otherwise the kill switch is left alone rather than risk a leak window. - Docs: new consolidated "Task Scheduler scripts" table (README and the web site) listing every script you run manually via Control Panel → Task Scheduler -
activate,set-port,recover-heartbeat,recover-vpn- with the command and when to run each, in one place instead of scattered across sections. - UI: the web status page (
index.cgi) is redesigned - theme-aware (follows the browser's light/dark preference), the old six-card grid plus separate Kuma mini-grid is replaced by a compact clickable status-chip row that jumps to and opens the matching detail section, and detailed data (routing breakdown, kill switch, Kuma, raw status, log) now lives in collapsible sections instead of always-open cards. The page header shows the installed version and links to this documentation and GitHub, and a new Task Scheduler scripts section listsactivate/set-port/recover-heartbeat/recover-vpnin-page. The long in-page configuration guide is trimmed to essentials, linking to the full docs instead of duplicating them.
0.2.3
- Fix:
rpc_call's session-id handshake matched the header twice - once in the realX-Transmission-Session-Idresponse header, and once again inside the 409 response body, which echoes it as<code>X-Transmission-Session-Id: ...</code>in a usage hint. The doubled/corrupted value was then sent back to Transmission on the follow-up request, which rejected it with HTTP 400 - so the RPC push from 0.2.2 still silently failed. Only the first match (the real header) is kept now.
0.2.2
- Fix - RPC session id never read:
rpc_call's handshake request usedcurl -s, which prints the response body only - theX-Transmission-Session-Idresponse header it was grepping for was never in the output, so every reconcile pass silently failed to pushFORWARDED_PORT, even with correctRPC_USER/RPC_PASS. The handshake request now runs with-iso the header is actually there to grep. - New - RPC push status surfaced in the UI:
apply_forwarded_portnow records its outcome (ok/fail+ timestamp) tovar/rpc_port_status. The Forwarded Port card reads it and turns red with a specific hint ("checkRPC_USER/RPC_PASSinetc/guard.secret") when pushes are failing, instead of silently showing nothing wrong while the rest of the dashboard stays green. - New:
AUTOSTART_TRANSMISSIONinguard.conf(default0). The shield always stops Transmission when it goes down but never starts it, so you had to start Transmission by hand after every shield upgrade/reboot. With1,startrestarts Transmission after the reconcile pass - only when the VPN is up and the IPv4 default route is already in the dedicated table, so it is never launched unprotected; a no-op if it is already running. - UI: the Transmission and Forwarded Port status cards are merged into one, so the grid no longer leaves a lone trailing card.
- Rolls up the 0.2.1 fix (
guard.secretsourced only when readable).
0.2.1
A small follow-up to 0.2.0 that removes a cosmetic "Permission denied" line from the web UI.
Fixes
_common.shsourcesetc/guard.secretonly when the caller can read it ([ -r ]instead of[ -f ]).guard.secretischmod 600, so when the web UI runsstart-stop-status statusas the unprivileged DSM web user, the source attempt failed and a "Permission denied" line showed up in the Advanced → raw status output panel. Non-root callers now simply run without RPC credentials - which they never need - and the panel is clean again.
No change to protection behaviour. Routing, the reconcile daemon, the RPC push (as root) and everything else are identical to 0.2.0.
Upgrade notes
- Drop-in upgrade for 0.2.0. No
guard.conf/guard.secretchanges required. - Re-run the activation Task Scheduler job after upgrading - DSM resets the privilege file on package update.
- If you are coming from 0.1.x, read the 0.2.0 notes first.
PR: #19