docs: Tailscale SSH ACL set to accept

Tailnet SSH policy changed from the default action:"check" to accept. The
effective policy is now a single rule covering all tailnet nodes, with no
expiry and port forwarding allowed, so the per-device ~12h grants and the
browser re-auth prompt are gone.

Verified unattended with BatchMode=yes: a plain command, a -L forward
returning HTTP 302, and the Herdr fallback leg.

Records the trade-off: check acted as a second factor, so a compromised
tailnet device now reaches root on Unraid without a further step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kaloyan DanchevandClaude Opus 5 committed 2026-11-03 23:03:47 +02:00
1 parent 9a102511ea
commit 27f5a7d5af
3 files changed
+26 -15

No files matched your search

+9 -4
View File
@@ -262,10 +262,15 @@ ssh root@xtrm-unraid.tailf789e1.ts.net
ssh -N -L 18089:127.0.0.1:80 root@100.100.208.69 ssh -N -L 18089:127.0.0.1:80 root@100.100.208.69
``` ```
The default tailnet ACL uses `action: "check"`, so the first connection in each The tailnet SSH ACL was switched from the default `action: "check"` to
period opens a browser re-auth prompt. Fine interactively, but it will stall an `accept` on 2026-11-03, so this needs no browser re-auth and works unattended.
unattended tunnel; switching that rule to `accept` for `autogroup:self` in the Before the change the policy minted ~12 h grants per device and prompted when
admin console removes the prompt. they lapsed. The effective policy is now a single rule: accept for all tailnet
nodes, with local and remote port forwarding and agent forwarding allowed.
The trade-off: `check` acted as a second factor, so a compromised tailnet device
now reaches root on Unraid without a further step. Acceptable here because every
node in the tailnet is the owner's own hardware.
### The other path — via the MikroTik subnet router ### The other path — via the MikroTik subnet router
+12 -11
View File
@@ -81,22 +81,23 @@ failed first attempt would consume stdin and corrupt the retry. It costs about
245 ms on the success path. `HERDR_VIA_TARGET=lan|ts` forces a leg for testing; 245 ms on the success path. `HERDR_VIA_TARGET=lan|ts` forces a leg for testing;
both were verified 2026-11-03. both were verified 2026-11-03.
The fallback leg inherits the tailnet ACL caveat below: with the default The fallback leg is fully unattended since the tailnet SSH ACL was set to
`action: "check"` it works until the grant lapses, then wants a browser `accept` on 2026-11-03. Verified the same day with `BatchMode=yes`: a plain
re-auth. Setting that rule to `accept` for `autogroup:self` makes the fallback command, a `-L` port forward (HTTP 302 from the Unraid web UI) and the Herdr leg
fully unattended. itself all ran without a prompt.
## Why the LAN address is the primary and not the Tailscale IP ## Why the LAN address is the primary and not the Tailscale IP
`--via` requires a transport that passes bytes untouched and **asks nothing**. `--via` requires a transport that passes bytes untouched and **asks nothing**.
Tailscale SSH on `100.100.208.69` sits behind the default tailnet ACL When this was set up, Tailscale SSH sat behind the default tailnet ACL
`action: "check"`, which demands browser re-authentication each period — fine `action: "check"`, which demanded browser re-authentication every ~12 h — fine
interactively, fatal for a long-lived Herdr connection. interactively, fatal for a long-lived Herdr connection. That ACL was changed to
`accept` on 2026-11-03, so either address would now serve.
Key auth on `192.168.10.20:422` asks nothing, and from outside the LAN it still The LAN address stays primary anyway: key auth on `192.168.10.20:422` depends on
travels over Tailscale via the MikroTik subnet router (see nothing but the SSH key, while Tailscale SSH depends on the tailnet policy
`docs/09-TAILSCALE-VPN.md`). Changing that ACL rule to `accept` for staying permissive. From outside the LAN it still travels over Tailscale via the
`autogroup:self` would make the `100.x` address usable here too. MikroTik subnet router (see `docs/09-TAILSCALE-VPN.md`), so there is no loss.
## Reboot persistence ## Reboot persistence
+5
View File
@@ -13,6 +13,11 @@
- **[SERVICE]** Exit node advertised from Unraid as a fallback to the hAP, and approved in the Tailscale admin console the same day. The tailnet now has two exit nodes: `mikrotik-tailscale` (100.74.219.35, primary) and `xtrm-unraid` (100.100.208.69, fallback). Neither has been exercised in anger from the Mac — without `--exit-node-allow-lan-access` an exit node cuts the client's own LAN access. - **[SERVICE]** Exit node advertised from Unraid as a fallback to the hAP, and approved in the Tailscale admin console the same day. The tailnet now has two exit nodes: `mikrotik-tailscale` (100.74.219.35, primary) and `xtrm-unraid` (100.100.208.69, fallback). Neither has been exercised in anger from the Mac — without `--exit-node-allow-lan-access` an exit node cuts the client's own LAN access.
- Detail, including the root-only `AllowTcpForwarding` behaviour in Unraid's stock sshd config, in `docs/09-TAILSCALE-VPN.md`. - Detail, including the root-only `AllowTcpForwarding` behaviour in Unraid's stock sshd config, in `docs/09-TAILSCALE-VPN.md`.
### Network: Tailscale SSH ACL set to accept
- **[NETWORK]** Tailnet SSH policy changed from Tailscale's default `action: "check"` to `accept` for `autogroup:member` -> `autogroup:self`. Before the change the control plane minted ~12 h per-device grants and prompted for browser re-auth when they lapsed, which would stall any unattended connection. Effective policy is now a single rule: accept for all 10 tailnet nodes, no expiry, with local and remote port forwarding and agent forwarding allowed.
- **[NETWORK]** Verified unattended with `BatchMode=yes`: a plain command over Tailscale SSH, a `-L` port forward (HTTP 302 from the Unraid web UI) and the Herdr fallback leg all ran without a prompt.
- Trade-off recorded in the docs: `check` acted as a second factor, so a compromised tailnet device now reaches root on Unraid without a further step. Accepted because every node in the tailnet is owner-controlled hardware.
### Tooling: Unraid registered as a Herdr (hc) machine ### Tooling: Unraid registered as a Herdr (hc) machine
- **[SERVICE]** Unraid added to Herdr as the machine `unraid` (`hc` 0.1.17 on the remote). `herdr-core machine add` had been failing with `core did not start within 5 s`: `hc` puts its core socket under `XDG_RUNTIME_DIR`, which on Unraid is `/run/user/0` — a directory elogind creates and destroys per login session, so the socket disappeared the moment the session that started the core ended. The core kept running with an unlinked socket, and `core.log` stayed empty because the failure is client side. - **[SERVICE]** Unraid added to Herdr as the machine `unraid` (`hc` 0.1.17 on the remote). `herdr-core machine add` had been failing with `core did not start within 5 s`: `hc` puts its core socket under `XDG_RUNTIME_DIR`, which on Unraid is `/run/user/0` — a directory elogind creates and destroys per login session, so the socket disappeared the moment the session that started the core ended. The core kept running with an unlinked socket, and `core.log` stayed empty because the failure is client side.
- **[SERVICE]** Fixed from the Mac only, via `~/.local/bin/herdr-via-unraid`, a `--via` transport that exports `XDG_RUNTIME_DIR=/var/run/herdr-rt` on every connection. Nothing on the server was changed. Uses key auth on 192.168.10.20:422 rather than Tailscale SSH, because `--via` needs a transport that asks nothing and the default tailnet ACL `check` would demand periodic browser re-auth. - **[SERVICE]** Fixed from the Mac only, via `~/.local/bin/herdr-via-unraid`, a `--via` transport that exports `XDG_RUNTIME_DIR=/var/run/herdr-rt` on every connection. Nothing on the server was changed. Uses key auth on 192.168.10.20:422 rather than Tailscale SSH, because `--via` needs a transport that asks nothing and the default tailnet ACL `check` would demand periodic browser re-auth.