fix(nh3-svos): strip Tailscale-User-* and X-Forwarded-* as whole families at the SVOS front door
svos-dev review: the Caddyfile deleted named headers only. Prefix deletes cover the families; the named strays (Tailscale-Headers-Info, X-Real-IP, Forwarded, X-SVOS-Peer) stay. Wildcard semantics checked on a scratch Caddy (case-insensitive; look-alikes outside the family survive). Deployed, validated via systemd-run with EnvironmentFile, reloaded; deny tests re-run (403). README: safe validate recipe, pending acceptance list.
This commit is contained in:
@@ -21,13 +21,11 @@ https://svos.phasefinal.com:443 {
|
|||||||
resolvers 1.1.1.1 8.8.8.8
|
resolvers 1.1.1.1 8.8.8.8
|
||||||
}
|
}
|
||||||
route {
|
route {
|
||||||
request_header -Tailscale-User-Login
|
# Whole families by prefix (Caddy header-delete wildcard; tested 2026-10-05: case-insensitive, and
|
||||||
request_header -Tailscale-User-Name
|
# X-Forwardedness / Tailscale-Other survive), plus the named strays outside them.
|
||||||
request_header -Tailscale-User-Profile-Pic
|
request_header -Tailscale-User-*
|
||||||
|
request_header -X-Forwarded-*
|
||||||
request_header -Tailscale-Headers-Info
|
request_header -Tailscale-Headers-Info
|
||||||
request_header -X-Forwarded-For
|
|
||||||
request_header -X-Forwarded-Proto
|
|
||||||
request_header -X-Forwarded-Host
|
|
||||||
request_header -X-Real-IP
|
request_header -X-Real-IP
|
||||||
request_header -Forwarded
|
request_header -Forwarded
|
||||||
request_header -X-SVOS-Peer
|
request_header -X-SVOS-Peer
|
||||||
|
|||||||
@@ -44,10 +44,20 @@ scripts/elway infra-ops@10.100.50.43 --playbook playbooks/nh3-svos-host.yaml
|
|||||||
(phasefinal.com only), in `/etc/caddy/env` (root:caddy 0640), vaulted `nh3-svos/cloudflare-caddy-dns01-token`.
|
(phasefinal.com only), in `/etc/caddy/env` (root:caddy 0640), vaulted `nh3-svos/cloudflare-caddy-dns01-token`.
|
||||||
- **Identity:** `svos-whois-auth.service` (`configs/svos-front/svos-whois-auth.py`, DynamicUser, 127.0.0.1:8405). Caddy's
|
- **Identity:** `svos-whois-auth.service` (`configs/svos-front/svos-whois-auth.py`, DynamicUser, 127.0.0.1:8405). Caddy's
|
||||||
`forward_auth` passes the SOCKET peer; the responder asks tailscaled WhoIs and answers 200 + `Tailscale-User-Login` only
|
`forward_auth` passes the SOCKET peer; the responder asks tailscaled WhoIs and answers 200 + `Tailscale-User-Login` only
|
||||||
for logins in **`/etc/svos-front/allowed-logins`** (empty = nobody). Client identity/forwarding headers are deleted first.
|
for logins in **`/etc/svos-front/allowed-logins`** (empty = nobody). Client identity/forwarding headers are deleted
|
||||||
- **Tested 2026-10-05:** LAN → no connection; mesh peer fv-ml1 (login `pfi`) → 403; forged `Tailscale-User-Login` → 403;
|
first, as whole families by prefix (`Tailscale-User-*`, `X-Forwarded-*`, svos-dev's ask) plus `Tailscale-Headers-Info`,
|
||||||
the responder directly with a bogus, garbage or empty peer → 403. Still to run once a login is allowed: an allowed
|
`X-Real-IP`, `Forwarded` and `X-SVOS-Peer`. The wildcard was tested on a scratch Caddy first: case-insensitive, and
|
||||||
device gets 200, its forged header is replaced, and a stopped tailscaled gives 403.
|
look-alikes outside the family (`X-Forwardedness`, `Tailscale-Other`) survive.
|
||||||
|
- **Config changes:** validate WITHOUT putting the token on a command line, then reload:
|
||||||
|
`sudo systemd-run --wait --pipe --collect -p User=caddy -p Group=caddy -p EnvironmentFile=/etc/caddy/env
|
||||||
|
-p "Environment=XDG_DATA_HOME=/var/lib/caddy XDG_CONFIG_HOME=/var/lib/caddy" /usr/local/bin/caddy validate --config
|
||||||
|
<file> --adapter caddyfile`, then `systemctl reload caddy-svos`. (`env $(cat /etc/caddy/env) caddy …` leaked the first
|
||||||
|
token into sudo's argv log on 2026-10-05; it was revoked.)
|
||||||
|
- **Tested 2026-10-05:** LAN → no connection; mesh peer fv-ml1 (login `pfi`) → 403; forged `Tailscale-User-Login`,
|
||||||
|
`Tailscale-User-Whatever` and `X-Forwarded-For` → 403; the responder directly with a bogus, garbage or empty peer → 403.
|
||||||
|
- **Still to run (handoff to svos-dev's acceptance):** once a login is allowed, an allowed device gets 200 and its forged
|
||||||
|
`Tailscale-User-*` / `X-Forwarded-*` headers (arbitrary family members included) are replaced or gone at the app; a
|
||||||
|
stopped tailscaled gives 403; and the live-service vzdump + restore-mount drill once the SVOS services run.
|
||||||
- ⚠ **Every mesh node, servers included, has WhoIs LoginName `pfi`** (headscale has one user). `pfi` must never go in
|
- ⚠ **Every mesh node, servers included, has WhoIs LoginName `pfi`** (headscale has one user). `pfi` must never go in
|
||||||
the allow-list: it would admit every server and LAN traffic SNAT'd through a subnet router. Prime's decision pending:
|
the allow-list: it would admit every server and LAN traffic SNAT'd through a subnet router. Prime's decision pending:
|
||||||
a separate headscale user for his devices (recommended) or a device allow-list.
|
a separate headscale user for his devices (recommended) or a device allow-list.
|
||||||
|
|||||||
Reference in New Issue
Block a user