From b8d0b215e174e75e836596924ccb7e6fed85bab8 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sat, 10 Oct 2026 09:57:29 +0200 Subject: [PATCH] wg firewall: the workout poke moves to tcp/8774 (8773 is book-guard's desktop wrapper); applied on the host 2026-10-10, phone reaches 8774 over the LAN Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01KrBEzjPRdx5oyp8NtTLW5F --- ...firewall-workout-poke-8774-2026-10-10.json | 31 +++++++++++++++++++ .../features/lib/tests/test_wg_firewall.sh | 24 +++++++------- .../features/lib/wg_firewall.sh | 6 ++-- linux_configuration/features/lib/wg_sshd.sh | 2 +- 4 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 docs/superpowers/evidence/wg-firewall-workout-poke-8774-2026-10-10.json diff --git a/docs/superpowers/evidence/wg-firewall-workout-poke-8774-2026-10-10.json b/docs/superpowers/evidence/wg-firewall-workout-poke-8774-2026-10-10.json new file mode 100644 index 00000000..e13d76e6 --- /dev/null +++ b/docs/superpowers/evidence/wg-firewall-workout-poke-8774-2026-10-10.json @@ -0,0 +1,31 @@ +{ + "intent": "The phone's instant workout poke reaches screen-locker on tcp/8774; tcp/8773 is left to book-guard's desktop wrapper (loopback), whose window the poke server had been answering.", + "scope": [ + "linux_configuration/features/lib/wg_firewall.sh, wg_sshd.sh, tests/test_wg_firewall.sh", + "Non-goal: any other firewall rule; the poke stays LAN-only with no wg0 rule" + ], + "changes": [ + "LAN-only poke rule renders 'ip saddr tcp dport 8774 accept' instead of 8773", + "allow-workout-poke help and confirmation text name tcp/8774" + ], + "verification": [ + { + "command": "bash linux_configuration/features/lib/tests/test_wg_firewall.sh", + "result": "pass", + "evidence": "18 passed, 0 failed (nft -c skipped: not permitted unprivileged)" + }, + { + "command": "vm run pokefw 'echo y | sudo bash ~/lc/features/setup_wireguard_ssh.sh allow-workout-poke'", + "result": "pass", + "evidence": "vmbox: exit 0, live ruleset has 'ip saddr 192.168.1.0/24 tcp dport 8774 accept', no 8773 rule, sshd active, second ssh session connects. Not verified on the host at commit time." + } + ], + "risks": [ + "Until the host re-applies, the live ruleset still opens 8773 (nothing listens on the LAN there) and blocks 8774, so the poke fails fast and the regular sync credits workouts", + "nftables-drift reports drift until the host re-applies" + ], + "rollback": [ + "git revert, then sudo bash linux_configuration/features/setup_wireguard_ssh.sh allow-workout-poke", + "Check: sudo nft list ruleset | grep 877 shows the restored port" + ] +} diff --git a/linux_configuration/features/lib/tests/test_wg_firewall.sh b/linux_configuration/features/lib/tests/test_wg_firewall.sh index 736dcba3..179c0e98 100755 --- a/linux_configuration/features/lib/tests/test_wg_firewall.sh +++ b/linux_configuration/features/lib/tests/test_wg_firewall.sh @@ -64,23 +64,23 @@ else _t_pass "ALLOW_DOT=false renders no 853 rule" fi printf '\n-- the workout poke is LAN-only --\n' -if grep -q 'dport 8773' "$RULES"; then - _t_fail "ALLOW_WORKOUT_POKE unset renders no 8773 rule" +if grep -q 'dport 8774' "$RULES"; then + _t_fail "ALLOW_WORKOUT_POKE unset renders no 8774 rule" else - _t_pass "ALLOW_WORKOUT_POKE unset renders no 8773 rule" + _t_pass "ALLOW_WORKOUT_POKE unset renders no 8774 rule" fi ALLOW_WORKOUT_POKE="true" render_nftables_ruleset "$RULES" -_t_file_has "$RULES" 'ip saddr 192.168.1.0/24 tcp dport 8773 accept' \ - "ALLOW_WORKOUT_POKE opens 8773 to the LAN subnet" -_t_eq "1" "$(grep -c 'dport 8773' "$RULES")" \ - "exactly one 8773 rule: no wg0 rule, the poke never rides WireGuard" +_t_file_has "$RULES" 'ip saddr 192.168.1.0/24 tcp dport 8774 accept' \ + "ALLOW_WORKOUT_POKE opens 8774 to the LAN subnet" +_t_eq "1" "$(grep -c 'dport 8774' "$RULES")" \ + "exactly one 8774 rule: no wg0 rule, the poke never rides WireGuard" ALLOW_WORKOUT_POKE="false" render_nftables_ruleset "$RULES" -if grep -q 'dport 8773' "$RULES"; then - _t_fail "ALLOW_WORKOUT_POKE=false renders no 8773 rule" +if grep -q 'dport 8774' "$RULES"; then + _t_fail "ALLOW_WORKOUT_POKE=false renders no 8774 rule" else - _t_pass "ALLOW_WORKOUT_POKE=false renders no 8773 rule" + _t_pass "ALLOW_WORKOUT_POKE=false renders no 8774 rule" fi if command -v nft >/dev/null 2>&1; then ALLOW_DOT="true" @@ -134,8 +134,8 @@ out="$(allow_workout_poke 2>&1)" mapfile -t calls <"$TEST_TMPDIR/calls.log" _t_eq "save_config ALLOW_WORKOUT_POKE=true|apply" "$(IFS='|' && printf '%s' "${calls[*]}")" \ "the flag is saved as true before the ruleset is applied" -_t_file_has "${NFT_CONF}.new" 'ip saddr 192.168.1.0/24 tcp dport 8773 accept' \ - "the applied ruleset carries the LAN-only 8773 rule" +_t_file_has "${NFT_CONF}.new" 'ip saddr 192.168.1.0/24 tcp dport 8774 accept' \ + "the applied ruleset carries the LAN-only 8774 rule" _t_has "$out" 'not wg0' "the confirmation says the port stays off WireGuard" _t_report "test_wg_firewall.sh" diff --git a/linux_configuration/features/lib/wg_firewall.sh b/linux_configuration/features/lib/wg_firewall.sh index 4af03a26..4f0bdf40 100755 --- a/linux_configuration/features/lib/wg_firewall.sh +++ b/linux_configuration/features/lib/wg_firewall.sh @@ -36,12 +36,12 @@ render_nftables_ruleset() { ha_rule+=$'\n\t\tiifname "'"${WG_IFACE}"$'" tcp dport 8123 accept' fi # Workout poke (screen-locker workout-poke.service): the phone POSTs a - # finished workout to tcp/8773 the moment it ends. LAN only, deliberately + # finished workout to tcp/8774 the moment it ends. LAN only, deliberately # NO wg0 rule: off the home LAN the poke fails fast and the normal sync # credits the workout instead. local poke_rule="" if [[ ${ALLOW_WORKOUT_POKE:-false} == "true" ]]; then - poke_rule=$'\n\t\tip saddr '"${LAN_SUBNET}"$' tcp dport 8773 accept' + poke_rule=$'\n\t\tip saddr '"${LAN_SUBNET}"$' tcp dport 8774 accept' fi # DNS-over-TLS (setup_dot_resolver.sh, bound to the WireGuard address): # rendered here so a re-apply keeps it -- a runtime 'nft add rule' did not. @@ -185,5 +185,5 @@ allow_workout_poke() { save_config write_nftables_ruleset verify_nftables_then_apply - log_ok "Opened tcp/8773 from ${LAN_SUBNET:-the LAN} only, not ${WG_IFACE} (persisted)." + log_ok "Opened tcp/8774 from ${LAN_SUBNET:-the LAN} only, not ${WG_IFACE} (persisted)." } diff --git a/linux_configuration/features/lib/wg_sshd.sh b/linux_configuration/features/lib/wg_sshd.sh index 2640958d..5a712693 100755 --- a/linux_configuration/features/lib/wg_sshd.sh +++ b/linux_configuration/features/lib/wg_sshd.sh @@ -236,7 +236,7 @@ Commands: allow-web Open tcp/80 and tcp/443 in the firewall (for a web server on this host). allow-dns Open udp/tcp 53 from the LAN in the firewall (for the DNS blocker on this host). allow-dot Open tcp/853 on wg0 in the firewall (for the DoT resolver on this host). - allow-workout-poke Open tcp/8773 from the LAN only (screen-locker's workout poke). + allow-workout-poke Open tcp/8774 from the LAN only (screen-locker's workout poke). verify Check /etc/nftables.conf matches this script and that the live forward chain still lets Docker through. install-verify Install the units that run 'verify' at every boot, so