tailscale / tailscale/tailscale
Exit-node PeerAPI /dns-query TCP timeout while WireGuard stays up; clients remain DNS-dead until Tailscale toggle
- Dominant language
- Go
- Stars
- 36.5k
- Forks
- 3.2k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 123
Description
## Summary
With an exit node selected, official Tailscale clients send app DNS as HTTPS PeerAPI DoH to the exit (`http://:/dns-query`), not UDP/53 to control-plane global nameservers. When that PeerAPI listener times out on TCP, WireGuard to the same exit stays up and the UI looks connected, but OS DNS is dead. Clients that connect during the outage stay DNS-dead even after PeerAPI recovers, until Tailscale is toggled off/on.
Control plane is **Headscale**. Clients are **official Tailscale** (Linux + Android). This is a client / PeerAPI-DNS reliability bug, not a request to change Headscale config.
## What happened
- Linux `dns: Set` showed `DefaultResolvers` as the PeerAPI DoH URL: `http://:/dns-query`.
- PeerAPI TCP to that ephemeral port timed out.
- WireGuard to the same exit stayed up (`online=yes`, `lastRecv` updating). The UI looked connected.
- Explicit `dig` to a reachable resolver succeeded; OS / `curl` DNS timed out.
- Phones that (re)connected **during** the PeerAPI outage stayed broken **after** PeerAPI recovered, until Tailscale was toggled off/on. Easy to miss for hours (mail/messages).
- Clearing the control-plane “use with exit node” setting matched the docs for “use the exit’s DNS”; it did **not** restore the PeerAPI listener on the exit.
- Rebooting the exit node restored the PeerAPI `/dns-query` listener.
`tailscale debug netmap` did **not** show `"UseWithExitNode": true` (Headscale still does not emit that flag on the wire; see juanfont/headscale#2816). Clients still used exit PeerAPI DoH because an exit node was selected.
This is not a duplicate of tailscale#3842 (closed 2022 firewall/netstack) or tailscale#14411 unless the client actually received `UseWithExitNode: true`.
## Asks
1. Fail closed in the UI when PeerAPI DNS is down even if WireGuard is up.
2. Retry / recover after the exit’s PeerAPI comes back **without** requiring a client Tailscale toggle.
3. Do not treat “VPN connected” as “DNS works.”
## Environment
- Control plane: Headscale
- Clients: official Tailscale on Linux and Android
- Exit node selected on the clients
Contributor guide
Research direction
Start by reproducing the exit-node failure and tracing the client path reported by `dns: Set`, the PeerAPI `/dns-query` listener, and `tailscale debug netmap`. Compare behavior while PeerAPI TCP is timed out and after it recovers; done means the UI reflects DNS failure and clients recover DNS without toggling Tailscale.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100