Tailcat – Like netcat, but over Tailscale’s data plane
Article URL: https://github.com/tailscale/tailcat Comments URL: https://news.ycombinator.com/item?id=49452990 Points: 281 # Comments: 49
Tailcat is a tool similar to netcat, but it operates over Tailscale's data plane rather than its control plane. The data plane utilizes WireGuard encryption to create point-to-point tunnels between machines, employing DERP for NAT hole-punching and serving as a last resort for NAT traversal. Unlike Tailscale's control plane, tailcat connections exchange metadata out-of-band as desired.
Tailcat's CLI is built upon the tailcat Go library, which can be imported as github.com/tailscale/tailcat. When using tailcat as a CLI tool or library, one side acts as a tailcat server (listener) and generates a connection token. The other side utilizes this token with tailcat's client side to establish the connection. All traffic between the two machines remains encrypted end-to-end with WireGuard.
The initial connection is initiated via a DERP server, after which magicsock attempts NAT traversal to establish a direct peer-to-peer UDP connection, whenever feasible. Tailscale accounts are not required, nor is root/admin access on the machine. The tool is merely a userspace library and CLI application, which can be accessed through Tailscale's free rate-limited DERP relays or by running your own.
Tailcat supports various server modes, including forwarding local TCP ports to localhost, running an SSH server with no authentication (or using the system SSH server with authentication), pinging to verify connectivity (displaying whether the connection is via DERP relay or direct path), and using tokens as URL hostnames. The SOCKS5 proxy recognizes and connects to these tokens, making the token argument optional.
Tokens can also be used directly as hostname arguments in curl and most CLI tools, though not in browsers, which lowercase hostnames.
Tailcat can serve as an exit node for clients to reach the server's network. It parses connection tokens and displays their contents as JSON, including the server's WireGuard public key and DERP information, without establishing a connection. Additionally, it resolves short tokens into longer self-contained tokens by embedding DERP server information, enabling quicker client connections. Parsing the resolved token reveals the embedded DERP info.
Each server's address (connection token) is generated from its WireGuard key, so the key utilized determines who can reach the server. Ephemeral keys are generated in memory for each server run and printed with an address that is unique and never used again. Saved keys can be generated with tailcat genkey and saved to disk, allowing for stable addresses across restarts. However, anyone who has ever shared that address can connect to any future server using the same key, unless restricted with --allow.
When a server uses an ephemeral key, it generates a fresh key in memory and prints an address that is unique. Once the process exits, the key is discarded, and the address becomes invalid forever. Conversely, saved keys enable stable addresses across restarts, but anyone who has shared that address can connect to any future server using the same key, unless restricted with --allow.
The CLI indicates whether an ephemeral or saved key is being used at startup, allowing users to differentiate between a fresh single-use server and a server listening on a shared address.
Written by urgent.news from Hacker News Best's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.