From 60ac868abf91587c2a0cb2369ecd92e96a43caa3 Mon Sep 17 00:00:00 2001 From: Nick Vigilante Date: Sat, 16 May 2026 21:34:56 -0400 Subject: [PATCH] Allow tailnet members to route to internet via exit nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an ACL rule permitting `autogroup:member → autogroup:internet:*`. Without it, Tailscale's control plane strips `Hostinfo.RoutableIPs` from peer netmaps (i.e., hides the exit-node advertisement) as a "this peer can't actually use these routes anyway per ACL" optimization — even when: - the device advertises with `--advertise-exit-node`, - autoApprovers in this policy auto-approves the routes, - per-machine `enabledRoutes` confirms the routes are approved. Diagnosed today: pi-zero-exit's exit-node advertisement was correctly landing in the control plane (verified via the Tailscale API: `enabledRoutes` showed both 0.0.0.0/0 and ::/0) but `tailscale exit-node list` from gandalf/iPhone/MacBook reported "no exit nodes found." Tracing the netmap difference between pi-zero-exit's SelfNode (routes present) and gandalf's view of pi-zero-exit as a peer (Hostinfo sans RoutableIPs) pointed at this ACL filter behavior. Scoped tightly: only `autogroup:member` gets the internet egress permission — homelab-tagged servers can still only reach other homelab-tagged servers. Members are personal devices the operator controls (per the existing tagOwners model). --- homelab/tailscale.tf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/homelab/tailscale.tf b/homelab/tailscale.tf index 375e6f3..31ca707 100644 --- a/homelab/tailscale.tf +++ b/homelab/tailscale.tf @@ -53,6 +53,20 @@ resource "tailscale_acl" "main" { src = ["tag:homelab"] dst = ["tag:homelab:*"] }, + # Tailnet members can route to the public internet via exit nodes. + # Without this, Tailscale's control plane strips `Hostinfo.RoutableIPs` + # (the exit-node advertisement) from peer netmaps as a "won't help + # you anyway" optimization — even when the routes are approved in + # the device's per-machine settings. Symptom: `tailscale exit-node + # list` from a member device says "no exit nodes found" despite an + # advertised + approved exit node existing in the tailnet. + # `autogroup:internet` is Tailscale's special destination representing + # everything external to the tailnet, accessible via exit nodes. + { + action = "accept" + src = ["autogroup:member"] + dst = ["autogroup:internet:*"] + }, ] ssh = [