Tailcat in NAT Environments: Rootless, Accountless P2P NAT Traversal Guide
"A comprehensive guide to Tailscale's open-source tool Tailcat (tailscale/tailcat). Achieve rootless, account-free WireGuard P2P tunnels, automatic NAT hole-punching, and secure SSH remote access on NAT VPS, Docker/LXC containers, and CGNAT environments."
When running services on NAT VPS instances (such as shared-IPv4 instances, LXC containers, Docker containers, or behind CGNAT home routers), developers frequently face several common challenges:
- No Dedicated Public IPv4: Access depends on host-level port forwarding rules, requiring non-standard external ports ($\ge 1024$) and manual configurations.
- Missing Kernel TUN Devices: Lightweight containers (LXC / Docker) often lack
/dev/net/tunpermissions, making standard WireGuard or OpenVPN unusable without privileged mode. - Control Plane Overhead: Traditional VPNs and standard Tailscale require account registration, auth keys, device limits, and coordinating nodes.
- Relay Bottlenecks in Traditional Port Forwarders: Tools like FRP or reverse SSH tunnels require a permanent VPS with a dedicated public IP and funnel all traffic through that relay rather than establishing direct P2P connections.
Tailscale recently open-sourced Tailcat (tailscale/tailcat), coined as “Tailscale without Tailscale, by Tailscale”.
This guide covers everything you need to know about Tailcat: its underlying architecture, installation, and hands-on scenarios including zero-port SSH, multi-port forwarding, DNS-based connection, streaming pipes, and custom DERP relay hosting on NAT VPS and container environments.
🧭 What is Tailcat?
Tailcat is a modern netcat-like tool that runs on Tailscale’s data plane, completely decoupled from Tailscale’s control plane.
┌─────────────────────────────────────────────────────────────────┐
│ Tailcat Architecture │
├───────────────────────────────┬─────────────────────────────────┤
│ Tailscale Data Plane │ Tailcat Features │
├───────────────────────────────┼─────────────────────────────────┤
│ • WireGuard (E2E encryption) │ • Zero account, zero login │
│ • magicsock (P2P hole-punch) │ • 100% Userspace (No Root/TUN) │
│ • gVisor Netstack (TCP/IP) │ • Token or DNS TXT signaling │
│ • DERP Relay (Failover relay) │ • Ephemeral or saved keys │
└───────────────────────────────┴─────────────────────────────────┘
Key Highlights:
- Pure Userspace Networking: Powered by gVisor’s Netstack, Tailcat terminates and manages TCP/IP stacks inside the process itself. It requires no root privileges, no
/dev/net/tundevice, and makes zero modifications to system routing tables or DNS. - First-Class P2P NAT Traversal: Using Tailscale’s battle-tested
magicsock, peers discover STUN endpoints and perform UDP hole-punching. Once punched, traffic upgrades to full line-rate, low-latency direct P2P connections. - Seamless DERP Relay Fallback: If strict symmetric NAT prevents direct UDP hole-punching, encrypted traffic falls back seamlessly to DERP relays.
- Instant, Zero-Registration Setup: No central servers to configure, no authentication keys to generate. Peers connect by exchanging short Base64 tokens or via DNS TXT records.
🛠️ Installation
Tailcat is written in Go and compiles to a single, dependency-free binary.
Method 1: Go Install (Recommended)
go install github.com/tailscale/tailcat/cmd/tailcat@latest
sudo cp $(go env GOPATH)/bin/tailcat /usr/local/bin/
Method 2: Build from Source
git clone https://github.com/tailscale/tailcat.git
cd tailcat
go build -o tailcat ./cmd/tailcat
sudo mv tailcat /usr/local/bin/
Method 3: Nix Flakes
nix run github:tailscale/tailcat
# or install to profile
nix profile install github:tailscale/tailcat
Verify the installation:
tailcat --help
💡 Connection Tokens & Key Models
- Connection Token (
ConnBlob): Starts withtc...ortcom.... It contains the server’s Curve25519 WireGuard public key and DERP rendezvous metadata. - Ephemeral Key (Default): Generates a new keypair in memory per execution. When the process terminates, the key and token are permanently discarded.
- Saved Key: Generated with
tailcat genkey, persisting the keypair to~/.config/tailcat/keys/default.private.jsonfor persistent connections and domain binding.
🚀 Practical Scenarios in NAT Environments
Scenario 1: Port-Free, Rootless SSH Access to NAT VPS
Option A: Ephemeral Auth-Free Debug Shell
On the NAT VPS:
tailcat --serve=no-auth-ssh
Output:
# Selected bootstrap relay region 302, San Francisco
🐈 Server listening with new address: tcomFwWCCcjS5nKNqAod034nWoJZW0LZqDhhC8U_dKdnDRYQ8uNGFpGQEu
On your local workstation:
tailcat ssh tcomFwWCCcjS5nKNqAod034nWoJZW0LZqDhhC8U_dKdnDRYQ8uNGFpGQEu
You get an immediate interactive shell inside the NAT VPS. When done, Ctrl+C terminates the session and invalidates the token.
Option B: Forward System SSH Port 22 with Zero-Trust Public Key Whitelist
To proxy to the system’s actual sshd and restrict access exclusively to your client machine:
- Generate a client key on your workstation:
client$ tailcat genkey --client # nodekey:cfb6bfa77a0654d7450947fd6acef17d2cd848da1d30b2540b13dac272ddfd16 - Start Tailcat on the NAT VPS with
--allow:server$ tailcat --serve=22 --allow=nodekey:cfb6bfa77a0654d7450947fd6acef17d2cd848da1d30b2540b13dac272ddfd16 - Connect from the authorized client:
client$ tailcat ssh tcXXXXXXXXX
Any unauthorized client attempting to connect will have their WireGuard handshakes dropped silently at the transport layer.
Scenario 2: Multi-Port Service Exposure & SOCKS5 Routing
Expose internal web apps, APIs, or databases listening on 127.0.0.1:
# Expose selected ports
tailcat --serve=8080,3000,3306
# Or expose all TCP ports
tailcat --serve=all
On your client, route requests through a SOCKS5 tunnel:
tailcat socks <Token> curl http://localhost:8080/
tailcat socks <Token> curl http://localhost:3000/api/status
Scenario 3: Domain-Based Direct Access via DNS TXT Records
Instead of copying long Base64 tokens, link your Tailcat token to a domain:
┌─────────────────────────┐
│ Cloudflare / DNS Provider│
│ TXT: tailcat=tc... │
└────────────┬────────────┘
│ DNS Lookup
┌───────────────┐ ▼ ┌───────────────┐
│ Local Client │ ─────────────────────────────────▶ │ Remote NAT VPS│
│ tailcat ssh │ P2P Direct UDP Tunnel │ tailcat serve │
│ vps.domain.me │ ◀──────────────────────────────── │ (Port 22) │
└───────────────┘ └───────────────┘
- Generate a fixed-region key on the server:
server$ tailcat genkey --fixed-region # Output: tcMyFixedVpsToken123456789... - Add a DNS TXT record in your DNS manager:
- Name:
vps.yourdomain.com - Type:
TXT - Value:
tailcat=tcMyFixedVpsToken123456789...
- Name:
- Start the server daemon on the NAT VPS:
server$ tailcat --serve=22 --allow=nodekey:<your-client-public-key> - Connect by domain name:
client$ tailcat ssh vps.yourdomain.com client$ tailcat ping vps.yourdomain.com
You can also add this to your local ~/.ssh/config:
Host my-nat-vps
HostName vps.yourdomain.com
ProxyCommand tailcat %h 22
User root
Then simply connect with:
ssh my-nat-vps
Scenario 4: Fast Stream Pipes & File Transfers
Transfer files or database dumps across NAT networks without third-party cloud storage:
-
Receive file on NAT VPS:
tailcat > backup.tar.gz -
Send file from local computer:
cat backup.tar.gz | tailcat <Token> -
Live Database Migration:
# On target: tailcat | mysql -u root -p my_database # On source: mysqldump -u root -p my_database | tailcat <TargetToken>
Scenario 5: NAT VPS as an Exit Node
Turn your NAT VPS into an egress proxy:
server$ tailcat --serve=exit-node
Client SOCKS proxy test:
client$ tailcat socks <Token> curl https://ipinfo.io
Scenario 6: Real-time P2P Hole Punching & Ping Diagnostics
Test connection paths and verify P2P direct UDP status:
tailcat ping --until-direct <Token or Domain>
Output:
pong in 42.1ms via DERP(sfo)
pong in 41.8ms via DERP(sfo)
pong in 3.2ms via 103.145.22.88:41641
pong in 3.1ms via 103.145.22.88:41641
Notice how the initial DERP relay connection (42ms) seamlessly upgrades to a direct UDP connection (3.1ms) once STUN hole-punching succeeds.
Scenario 7: Self-Hosted Private DERP Relay
For low latency and uncapped throughput, host your own DERP relay using Tailscale’s derper:
- Run
derperon a server with a public IP:go install tailscale.com/cmd/derper@latest derper -hostname derp.yourdomain.com -certmode manual -certdir /etc/ssl/derper - Generate a server key bound to your custom DERP:
The generated token embeds the custom DERP server address, so connecting clients require zero manual configuration.server$ tailcat genkey --region=derp.yourdomain.com
🌐 Multi-Node Mesh & Topologies: Can Tailcat Network Multiple Nodes?
Yes! Tailcat supports flexible multi-node networking across diverse topologies.
Internally, Tailcat’s Server is not limited to a single 1-to-1 session. Its onMeow handshake dynamically registers multiple incoming clients (client2.tailcat, client3.tailcat…), creating and managing multi-peer WireGuard routing states inside userspace Netstack.
Topology 1: Hub-and-Spoke Gateway
- One core NAT VPS or dedicated server runs
tailcat --serve=all,exit-nodewith--allowcontaining all authorized client public keys. - Multiple distributed clients connect simultaneously to the hub.
- Clients can route traffic through the hub’s SOCKS5 proxy to access internal services and private subnets.
Topology 2: Decentralized Ad-Hoc P2P Mesh
- Each NAT VPS node (e.g. Hong Kong, Tokyo, US-West) runs a persistent Tailcat server bound to its own domain (
hk-vps.example.com,jp-vps.example.com,us-vps.example.com). - Each node includes other nodes’ public keys in its
--allowparameter. - Nodes communicate directly with each other via on-demand P2P WireGuard tunnels with line-rate UDP speed.
🛡️ Production Systemd Service on NAT VPS
Create /etc/systemd/system/tailcat.service:
[Unit]
Description=Tailcat P2P WireGuard Tunnel Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/tailcat --serve=22 --allow=nodekey:cfb6bfa77a0654d7450947fd6acef17d2cd848da1d30b2540b13dac272ddfd16
Restart=always
RestartSec=5s
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
Enable and start:
systemctl daemon-reload
systemctl enable --now tailcat
systemctl status tailcat
📊 Comparison: Tailcat vs Alternative Tools
| Dimension | Tailcat | Full Tailscale | FRP / NPS | Cloudflare Tunnel |
|---|---|---|---|---|
| Protocol | WireGuard + userspace netstack | WireGuard (tun / userspace) | Custom TCP/KCP | HTTP/2 / QUIC / WebSockets |
| Requires Root / TUN | ❌ No | Requires TUN or userspace flag | ❌ No | ❌ No |
| Account / Server Required | ❌ Zero Account | Tailscale / Headscale account | Self-hosted server required | Cloudflare Account & Domain |
| P2P NAT Traversal | ✅ Top Tier (magicsock) | ✅ Top Tier | ⚠️ Basic (limited NAT hole-punch) | ❌ Relayed only via CF edge |
| Ephemeral Session Support | ✅ Native (destroyed on exit) | ❌ Node cleanup required | ❌ Manual rule cleanup | ❌ Dashboard routing changes |
| Zero-Trust Access Control | ✅ Native (--allow=nodekey) | ✅ Tailscale SSH / ACLs | Manual firewall configuration | Cloudflare Access policies |
| Setup Complexity | ⭐ Single command | ⭐⭐ Easy | ⭐⭐⭐ Manual server/client config | ⭐⭐ Moderate |
🎯 Summary
tailscale/tailcat combines the best aspects of WireGuard, userspace networking, and magicsock P2P hole punching into an effortless, account-free CLI utility. For NAT VPS instances, container clusters, and temporary remote debugging, it provides an unbeatable blend of performance, simplicity, and security.