tailscale /tailcat

like netcat, but over Tailscale's data plane, without Tailscale's control plane

★ 8,726⑂ 399👁 27▤ 7
GoCreated 2024-10-30tailscale.com/tailcat
8,726
stars
+0+13+568
399
forks
27
watchers
–
prs
–
issues
7
releases
–
discussions

README

"Tailscale without Tailscale, by Tailscale"


  
  


 Tailcat

Tailcat is a remix of Tailscale open source pieces to act like
netcat, but over Tailscale's data plane,
without Tailscale's control plane. Tailscale's data plane (magicsock,
internally) gives you point-to-point WireGuard®-encrypted tunnels between two
machines with DERP as the NAT-hole-punching communication side channel and the
ultimate relay-of-last-resort if NAT traversal fails. Instead of using the
Tailscale control plane, all tailcat connection metadata is exchanged out of
band, however you want.

The tailcat CLI (in cmd/tailcat) is built on the tailcat Go library
(importable as github.com/tailscale/tailcat).

Whether you use tailcat as a CLI tool or library, one side runs a tailcat
server (listener) and gets back a short tailcat address. The other side passes
that tailcat address to tailcat's client side to connect. All traffic between
the two is
encrypted end-to-end with WireGuard. The initial connection bootstraps through
a DERP server (see below), and then magicsock performs NAT traversal to
upgrade to a direct peer-to-peer UDP connection when possible (usually!).

You don't need a Tailscale account, root/admin access on the machine
(it doesn't alter your machine's routing tables, DNS, etc.). It's just
a userspace library and CLI tool.

And it's all open source.

You can use our free rate-limited DERP relays (the default DERP map is
https://tailcat.dev/derpmap.json) or you can run your own.

There's also an experimental in-browser web demo (tailcat compiled to
WebAssembly) at https://tailscale.github.io/tailcat/ that can send and
receive files or text, interoperating with the CLI. Browser traffic is
relayed over DERP only, with no direct connections until WebRTC
support (4).

 Install

See INSTALL.md for details on each, including notes
for packagers building from source:

| Method | Linux | macOS | Windows | FreeBSD,OpenBSD | Browser(js/wasm) |
|--------|:-----:|:-----:|:-------:|:-------------------:|:--------------------:|
| Static binaries | ✅ | | ✅ | | |
| .deb packages | Debian, Ubuntu, ... | | | | |
| .rpm packages | Red Hat, Fedora, ... | | | | |
| Homebrew | | ✅ | | | |
| Scoop | | | ✅ | | |
| Snap | ✅ | | | | |
| Container image | ✅ | | | | |
| Nix | ✅ | ✅ | | | |
| AUR | Arch | | | | |
| conda-forge | ✅ | ✅ | ✅ | | |
| Build from source | ✅ | ✅ | ✅ | ✅ | ✅ |

 Usage

 Pipe stdin/stdout between two machines

Server starts, printing out its ephemeral address:
sh
$ tailcat
 Selected bootstrap relay region 302, San Francisco
 🐈 Server listening with new address: tcomFwWCCcjS5nKNqAod034nWoJZW0LZqDhhC8U_dKdnDRYQ8uNGFpGQEu
(hangs, waiting...)


And then the client can:

sh
$ echo hello | tailcat tcomFwWCCcjS5nKNqAod034nWoJZW0LZqDhhC8U_dKdnDRYQ8uNGFpGQEu
$ 


Then the server unblocks:

sh
$ tailcat
 Selected bootstrap relay region 302, San Francisco
 🐈 Server listening with new address: tcomFwWCCcjS5nKNqAod034nWoJZW0LZqDhhC8U_dKdnDRYQ8uNGFpGQEu
hello
$


 Expose local por

Snapshot: 2026-11-04T14:00:00Z · Data license Apache-2.0 · JSON