Skip to content

Releases: gioxx/Syno-TransmissionVPNShield

0.3.0

Choose a tag to compare

@gioxx gioxx released this 14 Oct 18:01
a52c8d0
  • New: dead-tunnel detection. VPN_IF can stay up, address and all, while the VPN session behind it carries nothing (seen with DSM VPN Center + AirVPN: routing all green, port-test unknown, torrents stalled for hours). When the tunnel has received no bytes since the last reconcile pass, the shield probes it with a request bound to VPN_IF (at most every TUNNEL_CHECK_SEC, default 60s); 3 failed probes in a row log a WARN and, with AUTO_RECOVER_VPN, reconnect the profile, sharing the existing cooldown and 6-hour cap. A tunnel moving data is never probed.
  • Fix: recover-vpn gave up with "tun0 is still up after disconnect" when DSM accepted the disconnect but left the profile's openvpn running. 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_SEC is appended to etc/guard.conf automatically.

0.2.9

Choose a tag to compare

@gioxx gioxx released this 29 Sep 19:54
6f73c03
  • Fix (UI): 0.2.8 read Transmission's state with synopkg status, but the status page doesn't run as root, and as non-root synopkg can't read the service state ("status_code":263, "failed to get unit status") and reports stop even 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 a transmission-daemon process exists, and as stopped only when there is none and synopkg agrees.

0.2.8

Choose a tag to compare

@gioxx gioxx released this 29 Sep 19:39
4615a40
  • Fix (UI): with Transmission stopped (for example right after a shield upgrade with AUTOSTART_TRANSMISSION="0"), the status page blamed RPC_USER/RPC_PASS for the failing peer-port push. It now says Transmission is stopped, how to start it, and suggests AUTOSTART_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

Choose a tag to compare

@gioxx gioxx released this 29 Sep 19:16
5647bf6
  • New - automatic VPN recovery: with DSM_VPN_NAME set (and the new AUTO_RECOVER_VPN, default 1), the reconcile daemon runs recover-vpn by 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 by AUTO_RECOVER_COOLDOWN_SEC (default 30 min) and AUTO_RECOVER_MAX_PER_6H (default 3); past the cap the shield logs an ERROR and stops redialing until the window frees up.
  • New - Transmission is never left stopped by a failed recovery: recover-vpn marks 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 as AUTOSTART_TRANSMISSION. If the run left the profile disconnected (reconnect failed), the shield redials it every 5 minutes until the tunnel is back.
  • Fix: recover-vpn re-issues the disconnect once when VPN_IF is still up 15s after the first one, instead of giving up - seen live, where only a second manual run got through.
  • Fix: recover-vpn no longer touches the VPN when synopkg stop didn'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-test result is dropped whenever a new transmission-daemon process is detected, whatever restarted it - previously only a successful recover-vpn run cleared it, so a manual start left a stale "closed" in the UI for up to 10 minutes.
  • Fix: /usr/syno/bin is added to PATH by the shared library, so synopkg is found even from contexts with a minimal PATH (plain ssh 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 of guard.conf), the web UI alerts and the Kuma push verdict, on top of new reconcile coverage for the closed-port streak, automatic recovery and Transmission resume. A new Tests GitHub workflow runs all of them on every pull request and push to main, and the release build now only starts once they pass. Every suite runs against an isolated PKG_DIR, so running them on a NAS with the shield installed never writes into the live package's var/.
  • Fix: the closed-port streak is tied to the port it was counted for, so changing FORWARDED_PORT starts 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

Choose a tag to compare

@gioxx gioxx released this 09 Sep 10:22
34cd229
  • Fix: recover-vpn didn'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-vpn now 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_PROTOCOL is no longer needed for this (kept for backward compatibility).
  • New: every recover-vpn step is now also written to var/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-test check now runs from the reconcile daemon itself, once per PORT_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 real port-test result, and turns up a dedicated alert (with a link to run recover-vpn when configured) when the port tests closed despite a successful push.
  • Refactor: the port-test logic moved from guard-push into 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

Choose a tag to compare

@gioxx gioxx released this 09 Sep 07:21
207a3ec
  • New: recover-vpn now 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 editing guard.conf just to try it once - the argument overrides DSM_VPN_NAME/DSM_VPN_PROTOCOL when given, and the script still falls back to guard.conf when called with no arguments.

0.2.4

Choose a tag to compare

@gioxx gioxx released this 09 Sep 06:35
5ef894b
  • 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-vpn automates that: it stops Transmission, calls synovpnc reconnect for the profile in the new DSM_VPN_NAME guard.conf key (DSM_VPN_PROTOCOL defaults to openvpn), waits for VPN_IF to 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 once VPN_IF comes back up.
  • Fix: ENFORCE_KILLSWITCH_WHEN_VPN_DOWN="0" didn't actually disable the kill switch. reconcile always installs it while the VPN is up regardless of this setting, and nothing removed it again once the VPN dropped with the setting at 0 - so "0 = blackhole only" wasn't true in practice. reconcile now 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 lists activate/set-port/recover-heartbeat/recover-vpn in-page. The long in-page configuration guide is trimmed to essentials, linking to the full docs instead of duplicating them.

0.2.3

Choose a tag to compare

@gioxx gioxx released this 08 Sep 10:45
7fca3d2
  • Fix: rpc_call's session-id handshake matched the header twice - once in the real X-Transmission-Session-Id response 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

Choose a tag to compare

@gioxx gioxx released this 08 Sep 10:05
c7bc188
  • Fix - RPC session id never read: rpc_call's handshake request used curl -s, which prints the response body only - the X-Transmission-Session-Id response header it was grepping for was never in the output, so every reconcile pass silently failed to push FORWARDED_PORT, even with correct RPC_USER/RPC_PASS. The handshake request now runs with -i so the header is actually there to grep.
  • New - RPC push status surfaced in the UI: apply_forwarded_port now records its outcome (ok/fail + timestamp) to var/rpc_port_status. The Forwarded Port card reads it and turns red with a specific hint ("check RPC_USER/RPC_PASS in etc/guard.secret") when pushes are failing, instead of silently showing nothing wrong while the rest of the dashboard stays green.
  • New: AUTOSTART_TRANSMISSION in guard.conf (default 0). 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. With 1, start restarts 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.secret sourced only when readable).

0.2.1

Choose a tag to compare

@gioxx gioxx released this 31 Aug 21:05
b347558

A small follow-up to 0.2.0 that removes a cosmetic "Permission denied" line from the web UI.

Fixes

  • _common.sh sources etc/guard.secret only when the caller can read it ([ -r ] instead of [ -f ]). guard.secret is chmod 600, so when the web UI runs start-stop-status status as 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.secret changes 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