August 29, 2026 Technical Release

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:

  1. No Dedicated Public IPv4: Access depends on host-level port forwarding rules, requiring non-standard external ports ($\ge 1024$) and manual configurations.
  2. Missing Kernel TUN Devices: Lightweight containers (LXC / Docker) often lack /dev/net/tun permissions, making standard WireGuard or OpenVPN unusable without privileged mode.
  3. Control Plane Overhead: Traditional VPNs and standard Tailscale require account registration, auth keys, device limits, and coordinating nodes.
  4. 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:

  1. 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/tun device, and makes zero modifications to system routing tables or DNS.
  2. 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.
  3. Seamless DERP Relay Fallback: If strict symmetric NAT prevents direct UDP hole-punching, encrypted traffic falls back seamlessly to DERP relays.
  4. 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.

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 with tc... or tcom.... 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.json for 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:

  1. Generate a client key on your workstation:
    client$ tailcat genkey --client
    # nodekey:cfb6bfa77a0654d7450947fd6acef17d2cd848da1d30b2540b13dac272ddfd16
  2. Start Tailcat on the NAT VPS with --allow:
    server$ tailcat --serve=22 --allow=nodekey:cfb6bfa77a0654d7450947fd6acef17d2cd848da1d30b2540b13dac272ddfd16
  3. 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)   │
 └───────────────┘                                   └───────────────┘
  1. Generate a fixed-region key on the server:
    server$ tailcat genkey --fixed-region
    # Output: tcMyFixedVpsToken123456789...
  2. Add a DNS TXT record in your DNS manager:
    • Name: vps.yourdomain.com
    • Type: TXT
    • Value: tailcat=tcMyFixedVpsToken123456789...
  3. Start the server daemon on the NAT VPS:
    server$ tailcat --serve=22 --allow=nodekey:<your-client-public-key>
  4. 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:

  1. Run derper on a server with a public IP:
    go install tailscale.com/cmd/derper@latest
    derper -hostname derp.yourdomain.com -certmode manual -certdir /etc/ssl/derper
  2. Generate a server key bound to your custom DERP:
    server$ tailcat genkey --region=derp.yourdomain.com
    The generated token embeds the custom DERP server address, so connecting clients require zero manual configuration.

🌐 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-node with --allow containing 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 --allow parameter.
  • 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

DimensionTailcatFull TailscaleFRP / NPSCloudflare Tunnel
ProtocolWireGuard + userspace netstackWireGuard (tun / userspace)Custom TCP/KCPHTTP/2 / QUIC / WebSockets
Requires Root / TUNNoRequires TUN or userspace flag❌ No❌ No
Account / Server RequiredZero AccountTailscale / Headscale accountSelf-hosted server requiredCloudflare Account & Domain
P2P NAT TraversalTop Tier (magicsock)✅ Top Tier⚠️ Basic (limited NAT hole-punch)❌ Relayed only via CF edge
Ephemeral Session SupportNative (destroyed on exit)❌ Node cleanup required❌ Manual rule cleanup❌ Dashboard routing changes
Zero-Trust Access ControlNative (--allow=nodekey)✅ Tailscale SSH / ACLsManual firewall configurationCloudflare Access policies
Setup ComplexitySingle 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.