Tailscale VPN¶
Tailscale ACL policy, peer relay, and connection troubleshooting.
ACL Policy¶
{
"tagOwners": {
"tag:relay": ["autogroup:admin"],
"tag:clients": ["autogroup:admin"]
},
"acls": [
{ "action": "accept", "src": ["*"], "dst": ["*:*"] }
],
"grants": [
{
"src": ["tag:clients"],
"dst": ["tag:relay"],
"app": { "tailscale.com/cap/relay": [] }
},
{
"src": ["tag:clients"],
"dst": ["tag:relay"],
"ip": ["*"]
}
]
}
The grants section must be set via the Tailscale API directly -- the MCP ACL tool (manage_acl) silently drops it:
curl -X POST -H "Authorization: Bearer $TAILSCALE_API_KEY" \
-H "Content-Type: application/json" \
"https://api.tailscale.com/api/v2/tailnet/mordasiewicz.com/acl" \
-d '{ ... full ACL with grants ... }'
Peer Relay¶
When direct connections fail (school NAT, mobile hotspot symmetric NAT), devices route through tsrelay instead of Tailscale's DERP servers. No bandwidth throttling unlike DERP.
| Device | tsrelay (Toronto, 100.95.40.19) |
| Relay port | 40000 (tailscale set --relay-server-port=40000) |
| Port forward | Toronto UniFi: UDP 40000 -> tsrelay (192.168.177.228) |
| Systemd override | /etc/systemd/system/tailscaled.service.d/relay.conf |
| Grant | tag:clients -> tag:relay (requires both app and ip grants) |
Do not set --relay-server-static-endpoints -- Bell PPPoE IP is dynamic. STUN + UPnP discovers the public IP automatically.
Connection priority (automatic)¶
flowchart TD
A["Client connects"] --> B{"Direct UDP<br/>hole-punch?"}
B -- "Yes" --> C["Direct connection<br/>~15ms"]
B -- "No" --> D{"Peer relay<br/>available?"}
D -- "Yes" --> E["Peer relay<br/>~15-45ms"]
D -- "No" --> F["DERP relay<br/>~14ms, throttled"]
| Priority | Type | Latency |
|---|---|---|
| 1 | Direct (UDP hole-punch) | Fastest |
| 2 | Peer relay (tsrelay) | ~15ms Toronto-Kingston, no throttling |
| 3 | DERP (Tailscale servers) | ~14ms, throttled |
Grant mechanics¶
src= who can use the relay (tag:clients)dst= the relay device (tag:relay)- Only the initiating device needs the tag, not both sides
- Tags can't be removed without
tailscale up --force-reauth - To test without relay, remove
grantsfrom ACL instead of changing device tags
Connection Results by Location¶
| Mac Location | Connection Type | Latency | Notes |
|---|---|---|---|
| Toronto UniFi | Direct | ~17ms | Requires UPnP enabled on UniFi |
| Toronto Bell Wi-Fi | Direct | ~15ms | Works naturally (permissive NAT) |
| School (university) | Peer relay | ~45ms | EDM NAT + no UPnP, direct fails, relay kicks in |
| Mobile hotspot | Peer relay | ~50-120ms | Carrier CGNAT has symmetric NAT (EDM), no UPnP. Direct to tsrelay may work; workstation goes via peer relay |
| Anywhere (no relay) | DERP Toronto | ~14ms | Bandwidth throttled |
Tailscale Ports¶
| Port | Protocol | Purpose |
|---|---|---|
| 41641 | UDP | Default WireGuard (each device) |
| 40000 | UDP | Peer relay (tsrelay only) |
| 3478 | UDP | STUN (NAT discovery) |