Introduction to Tailscale VPN Troubleshooting
Tailscale is a modern zero-config VPN built on top of WireGuard that creates secure peer-to-peer mesh networks between your devices. While Tailscale is designed to "just work," developers and sysadmins inevitably encounter issues related to authentication, NAT traversal, DNS resolution, routing, and firewall conflicts. This tutorial walks through the most common Tailscale problems and provides practical, tested fixes you can apply immediately.
Why Troubleshooting Tailscale Matters
When Tailscale fails, your services become unreachable, CI pipelines stall, and remote development environments go dark. Understanding the diagnostic tooling and common failure modes reduces mean time to recovery (MTTR) and helps you design more resilient network topologies. Because Tailscale operates at the intersection of local networking, NAT, DNS, and identity providers, a systematic approach is essential.
Prerequisites and Diagnostic Tooling
Before diving into specific issues, ensure you have the following:
- Tailscale installed and at least partially authenticated on the target machine
- Admin access to the Tailscale admin console at
https://login.tailscale.com/admin - Local sudo or administrator privileges
- Basic familiarity with the command line and networking concepts
The single most important command in your troubleshooting toolkit is tailscale status. It shows the connection state of every peer, including whether traffic is direct or relayed through DERP servers.
# View status of all peers
tailscale status
# Verbose status with more detail
tailscale status --verbose
# Check the local node's IP and identity
tailscale ip
tailscale whois <peer-ip>
For deeper inspection, use tailscale debug subcommands and the built-in netcheck utility:
# Network diagnostics including NAT type and DERP latency
tailscale netcheck
# View current DERP relay map
tailscale debug derpmap
# Capture a bug report for support
tailscale bugreport
Issue 1: Node Stuck in "Idle" or "Relay" State
Symptoms
Peers appear in tailscale status but show idle or relay "xxx" instead of direct. Latency is high, throughput is poor, and connections feel sluggish.
Root Cause
Tailscale attempts direct peer-to-peer connections using STUN and NAT traversal techniques. When both peers are behind restrictive NATs (such as symmetric NAT), a direct connection cannot be established, and traffic falls back to DERP relay servers. This is functional but slow.
Fix
Run tailscale netcheck on both peers to identify NAT types. If symmetric NAT is detected, consider enabling port forwarding on one side or deploying a custom DERP server closer to your infrastructure.
# Enable UPnP and port mapping (if supported by router)
sudo tailscale up --port=41641
# Force a specific exit node or direct connection attempt
sudo tailscale up --direct-file-startup
# Check if UDP is being blocked by inspecting netcheck output
tailscale netcheck
If UDP is blocked entirely by a corporate firewall, DERP relay is your only option. You can deploy a private DERP server to reduce latency:
# Example: running a custom DERP server in Docker
docker run -d \
--name derper \
--restart unless-stopped \
-p 443:443 \
-v /etc/derp:/certs \
ghcr.io/tailscale/derper:latest \
--hostname=derp.example.com \
--certmode=manual \
--certdir=/certs
Issue 2: Authentication and Login Failures
Symptoms
Running tailscale up produces a login URL, but after authenticating, the node does not appear in the admin console, or you receive errors like unexpected HTTP response status: 401.
Fix
First, verify the node is not already authenticated under a different tailnet. Re-authenticate explicitly:
# Log out completely
sudo tailscale logout
# Log back in with a specific auth key
sudo tailscale up --auth-key=tskey-auth-XXXXX
# Or use a reusable auth key from the admin console
sudo tailscale up --auth-key=tskey-auth-YYYYY --hostname=build-server-01
If you use an identity provider (IdP) like Okta, Google Workspace, or Microsoft Entra ID, ensure the user account has access to the tailnet. Check the admin console under Settings > DNS and Access Controls for misconfigurations.
For headless servers and CI environments, always use pre-generated auth keys with appropriate tags:
# Generate an auth key via the API
curl -X POST https://api.tailscale.com/api/v2/tailnet/-/keys \
-H "Authorization: Bearer tskey-api-XXXXX" \
-H "Content-Type: application/json" \
-d '{
"capabilities": {
"devices": {
"create": {
"reusable": true,
"ephemeral": true,
"preauthorized": true,
"tags": ["tag:ci"]
}
}
},
"expirySeconds": 7776000
}'
Issue 3: DNS Resolution Problems
Symptoms
You can ping peers by IP address but not by MagicDNS hostname (e.g., build-server-01.tailnet-name.ts.net). Applications fail to resolve internal service names.
Fix
Verify MagicDNS is enabled in the admin console under DNS > Nameservers. Then check the local resolver configuration:
# Check Tailscale's local DNS state
tailscale status --json | jq .Self
# Inspect what DNS servers Tailscale is using
resolvectl status tailscale0
# On macOS
scutil --dns | grep -A 5 tailscale
# Test MagicDNS resolution directly
nslookup build-server-01.tailnet-name.ts.net
dig @100.100.100.100 build-server-01
If MagicDNS is enabled but not working, the system DNS resolver may be overriding Tailscale. On Linux with systemd-resolved, ensure the Tailscale interface is properly registered:
# Restart systemd-resolved and Tailscale
sudo systemctl restart systemd-resolved
sudo systemctl restart tailscaled
# Verify the tailscale0 interface has DNS configured
resolvectl dns tailscale0
# Expected output: 100.100.100.100
For split DNS configurations where you want internal domains resolved by a private DNS server, configure it in the admin console:
# Add a restricted nameserver for a specific domain via API
curl -X POST https://api.tailscale.com/api/v2/tailnet/-/dns/nameservers \
-H "Authorization: Bearer tskey-api-XXXXX" \
-H "Content-Type: application/json" \
-d '{
"dns": ["10.0.0.53"],
"restrict": ["internal.corp.example.com"]
}'
Issue 4: Subnet Routing Not Working
Symptoms
A node configured as a subnet router advertises routes, but other tailnet peers cannot reach devices in the advertised subnet.
Fix
Subnet routing requires two steps: advertising routes on the router node and accepting routes on the client nodes. A common mistake is forgetting the acceptance step.
# On the subnet router node: advertise routes
sudo tailscale up --advertise-routes=10.0.1.0/24,192.168.50.0/24
# Enable IP forwarding on the router (Linux)
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf
# On client nodes: accept the advertised routes
sudo tailscale up --accept-routes
Verify the routes are approved in the admin console under the node's settings. Advertised routes must be explicitly approved by an admin before they become active.
# Verify which routes are being advertised and accepted
tailscale status --json | jq '.Self.AllowedIPs'
# Test connectivity to a device in the routed subnet
ping 10.0.1.50
traceroute 10.0.1.50
Issue 5: Exit Node Configuration Failures
Symptoms
You configure a node as an exit node, but when clients try to use it, internet connectivity is lost or traffic does not route through the exit node.
Fix
Like subnet routing, exit nodes require both advertisement and acceptance. Additionally, the exit node must have proper NAT and IP forwarding configured.
# On the exit node: advertise as exit node
sudo tailscale up --advertise-exit-node
# Enable IP forwarding (Linux)
sudo sysctl -w net.ipv4.ip_forward=1
# Configure NAT masquerading if needed
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# On client nodes: use the exit node
sudo tailscale up --exit-node=<exit-node-ip-or-hostname>
# Verify traffic is routing through the exit node
curl https://api.ipify.org
# This should return the exit node's public IP
To check whether an exit node is properly configured, use the built-in check:
# Verify exit node status
tailscale exit-node list
# Check if the current node is acting as an exit node
tailscale debug exit-node
Issue 6: Firewall and Port Conflicts
Symptoms
Tailscale connects intermittently, or specific applications fail when Tailscale is running. You may see errors about the tun interface failing to create.
Fix
Tailscale uses UDP port 41641 for direct connections and creates a tun network interface. Ensure these are not blocked by local firewalls.
# Allow Tailscale traffic through ufw (Ubuntu/Debian)
sudo ufw allow 41641/udp
sudo ufw allow in on tailscale0
sudo ufw allow out on tailscale0
# For firewalld (RHEL/CentOS/Fedora)
sudo firewall-cmd --permanent --add-port=41641/udp
sudo firewall-cmd --permanent --add-interface=tailscale0
sudo firewall-cmd --reload
# Check if another VPN is conflicting
ip link show
# Look for multiple tun/wg interfaces that might conflict
On macOS, the system may prompt for permission to load a system extension. If the prompt was dismissed, manually allow it under System Settings > Privacy & Security > Network Extensions.
Issue 7: Tailscaled Daemon Not Starting
Symptoms
The tailscale CLI returns errors like tailscaled is not running or failed to connect to local tailscaled.
Fix
# Check daemon status
sudo systemctl status tailscaled
# View daemon logs for errors
sudo journalctl -u tailscaled --no-pager -n 50
# Restart the daemon
sudo systemctl restart tailscaled
# Run tailscaled in foreground for debugging
sudo tailscaled --tun=userspace-networking --sockpath=/tmp/tailscaled.sock --verbose
If the daemon fails due to a corrupted state file, reset the local state:
# Stop the daemon
sudo systemctl stop tailscaled
# Backup and remove state
sudo mv /var/lib/tailscale/tailscaled.state /var/lib/tailscale/tailscaled.state.bak
# Start fresh
sudo systemctl start tailscaled
sudo tailscale up
On containers and minimal environments, use userspace networking mode to avoid requiring tun device access:
# Run Tailscale in userspace networking mode
tailscaled --tun=userspace-networking &
tailscale up --auth-key=tskey-auth-XXXXX
Best Practices for Reliable Tailscale Deployments
- Use ACLs aggressively: Define least-privilege access controls in the admin console to restrict which nodes can communicate. Tag machines by role (e.g.,
tag:web,tag:db) and write ACLs against tags rather than individual users. - Monitor with health checks: Use the Tailscale API to periodically check node health and alert on nodes that go offline unexpectedly.
- Keep clients updated: Tailscale ships frequent updates with NAT traversal improvements. Run
tailscale updateor use your package manager to stay current. - Use ephemeral nodes for CI: Generate ephemeral auth keys for short-lived CI runners so stale nodes do not accumulate in your tailnet.
- Deploy redundant DERP servers: For latency-sensitive workloads, deploy your own DERP servers in regions close to your infrastructure.
- Document your tailnet topology: Maintain a record of subnet routers, exit nodes, and ACL policies alongside your infrastructure-as-code repositories.
Here is an example ACL configuration that enforces least privilege:
{
"tagOwners": {
"tag:web": ["group:devops"],
"tag:db": ["group:devops"],
"tag:ci": ["autogroup:member"]
},
"acls": [
{
"action": "accept",
"src": ["group:developers"],
"dst": ["tag:web:80", "tag:web:443"]
},
{
"action": "accept",
"src": ["tag:web"],
"dst": ["tag:db:5432"]
},
{
"action": "deny",
"src": ["*"],
"dst": ["tag:db:*"]
}
]
}
Apply this ACL via the API:
curl -X POST https://api.tailscale.com/api/v2/tailnet/-/acl \
-H "Authorization: Bearer tskey-api-XXXXX" \
-H "Content-Type: application/json" \
-d @acl-policy.json
Conclusion
Tailscale simplifies secure networking, but its reliance on underlying system networking components means issues can arise from NAT types, DNS resolvers, firewalls, daemon state, and configuration mismatches between advertised and accepted routes. By mastering the diagnostic commands covered in this tutorial — tailscale status, tailscale netcheck, tailscale debug, and tailscale bugreport — you can quickly isolate and resolve the vast majority of Tailscale problems. Combine these tools with disciplined ACL policies, regular client updates, and proper subnet router and exit node configuration to maintain a fast, secure, and reliable tailnet across all your development and production environments.