Tailcat:无需控制平面的点对点 WireGuard 与 NAT 穿透工具
Tailcat 将 Tailscale 的 magicsock 和 WireGuard 数据平面集成到一个轻量级的用户空间 CLI 工具中,无需依赖集中式协调服务。
Tailscale 通过将 WireGuard 与巧妙的 NAT 穿透技术(magicsock)以及加密中继回退(DERP)相结合,彻底革新了网状网络(Mesh VPN)。然而,典型的 Tailscale 配置需要向集中式协调服务器(控制平面)注册节点,并运行需要修改系统路由表和虚拟网络接口(TUN/TAP)的特权守护进程。
Tailcat 改变了这一模式。Tailcat 由 Tailscale 团队构建,将 Tailscale 的核心数据平面组件封装成一个独立的用户空间 CLI 和 Go 语言库。它的使用体验类似于 netcat,但每个连接都使用 WireGuard 进行了端到端加密,能够自动穿透 NAT,并且既不需要 root 权限,也不需要 Tailscale 账户。
深入剖析:零 Root 权限的用户空间架构
Tailcat 完全剥离了 Tailscale 的控制平面。它不再通过中心控制服务器协调对等节点状态,而是使用紧凑的连接令牌在带外(out-of-band)传递所有会合元数据。
在进程内部,Tailcat 结合了四大核心组件:
- 用户空间 WireGuard:处理点对点加密(Curve25519、ChaCha20-Poly1305),无需触碰 Linux 内核 WireGuard 模块或需要管理员权限。
magicsock:Tailscale 的多路径传输引擎。它通过 STUN 动态探测 UDP 端点,并执行 UDP 打洞以建立直接的点对点连接。- DERP(指定数据包加密中继,Designated Encrypted Relay for Packets):基于 HTTPS 的中继机制,既充当会合通道,也是在对称 NAT 阻止直接 UDP 打洞时的可靠回退方案。
- gVisor
netstack:在用户空间内存中运行的完整 TCP/IP 栈。由于netstack在进程内终止连接,Tailcat 可以在不修改操作系统路由表或本地网络接口的情况下接受传入流或转发传出流量。
+-------------------------------------------------------------+
| Tailcat CLI |
| +-------------------------------------------------------+ |
| | gVisor netstack (用户空间 TCP/IP) | |
| +-------------------------------------------------------+ |
| | 用户空间 WireGuard | |
| +-------------------------------------------------------+ |
| | magicsock | |
| +---------------------------+---------------------------+ |
| | STUN / UDP 打洞 | DERP 加密中继 | |
+--+---------------------------+---------------------------+--+
连接令牌(ConnBlob)剖析
当 Tailcat 服务器启动时,它会输出一个以 tc 为前缀的临时地址令牌(例如 tcomFwWCCcjS5nKNqAod034...)。
在内部,该字符串是一个经过 Base64 编码的 CBOR 数据块,包含:
- 服务器的 32 字节 Curve25519 WireGuard 公钥(
nodekey:...)。 - DERP 会合元数据(整数区域 ID 或完整的节点主机名和 IP)。
你可以使用 CLI 查看任意令牌的详细内容:
$ tailcat parse tcomFwWCCcjS5nKNqAod034nWoJZW0LZqDhhC8U_dKdnDRYQ8uNGFpGQEu
{
"ServerPublic": "nodekey:9c8d2e6728da80a1dd37e275a82595b42d9a838610bc53f74a7670d1610f2e34",
"RegionID": 302
}
握手流程
- 引导启动(Bootstrap):客户端解析令牌,提取服务器的公钥和 DERP 区域,并连接到共享的 DERP 中继。
- 发现交换(Discovery Exchange):客户端通过 DERP 发送一个包含自身临时公钥的轻量级
Meow数据包。服务器注册该客户端并回复Meowed。 - WireGuard 握手:标准的 WireGuard 握手通过 DERP 隧道进行。
- NAT 穿透:与此同时,双方端点通过 DERP disco 消息交换候选 UDP 地址(STUN 端点和本地 IP)。如果 UDP 打洞成功,数据流将无缝升级为直接的 UDP 连接。
实用场景
1. 管道标准输入 / 输出(加密版 Netcat)
在接收端机器上:
$ tailcat
# 🐈 Server listening with new address: tcXXXXXXXXX
在发送端机器上:
$ tar -czf - ./project | tailcat tcXXXXXXXXX
2. 转发防火墙背后的本地端口
无需端口转发、UPnP 或 ngrok,即可暴露本地服务(如预发布 Web 服务器):
# 在服务器端
$ tailcat --serve=8080
# 🐈 Server listening with new address: tcXXXXXXXXX
# 在客户端
$ tailcat tcXXXXXXXXX 8080
GET / HTTP/1.1
Host: localhost
3. 通过 DNS TXT 记录进行 WireGuard 认证的 SSH
Tailcat 可以在暴露 SSH 守护进程之前,提供受 WireGuard 密钥保护的 SSH 访问:
生成客户端密钥对:
client$ tailcat genkey --client # Public key: nodekey:cfb6bfa77a0654d7450947fd6acef17d2cd848da1d30b2540b13dac272ddfd16运行经过认证的 SSH 服务器:
server$ tailcat genkey --fixed-region server$ tailcat --serve=22 --allow=nodekey:cfb6bf...ddfd16通过 DNS 发布: 创建一个指向生成的服务器令牌的 DNS
TXT记录:bastion.internal.example.com. 300 IN TXT "tailcat=tcXXXXXXXXX"直接通过域名连接:
client$ tailcat ssh bastion.internal.example.com
未授权的连接尝试将在 WireGuard 层被直接丢弃——端口扫描器甚至无法探测到 SSH 守护进程正在运行。
4. SOCKS5 代理和出口节点(Exit Node)
通过远程对等节点路由 CLI 流量:
# 远程主机
$ tailcat --serve=exit-node
# 本地机器
$ tailcat socks <token> curl http://internal-service.local/
将 Tailcat 作为 Go 语言库使用
Tailcat 经过专门设计,可以直接嵌入到 Go 服务中。
服务端示例
package main
import (
"fmt"
"log"
"net"
"github.com/tailscale/tailcat"
)
func main() {
s := &tailcat.Server{
OnTCP: func(port uint16) func(net.Conn) {
return func(c net.Conn) {
defer c.Close()
fmt.Fprintf(c, "Connected to in-process service on port %d\n", port)
}
},
}
if err := s.Start(); err != nil {
log.Fatal(err)
}
// 与客户端共享此令牌
fmt.Println("Connection Token:", s.ConnBlob())
select {}
}
客户端示例
package main
import (
"context"
"io"
"log"
"os"
"github.com/tailscale/tailcat"
)
func main() {
token := tailcat.ConnBlob(os.Args[1])
cl := tailcat.NewClient(token)
defer cl.Close()
conn, err := cl.DialTCPPort(context.Background(), 80)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
io.Copy(os.Stdout, conn)
}
自建中继(BYO Relay):脱离公共基础设施运行
Tailcat 默认使用公共 DERP 中继(https://tailcat.dev/derpmap.json),但你并不受限于此。你可以将服务器令牌直接绑定到自建的 DERP 服务器:
server$ tailcat genkey --region=derp.myinfra.net
# 生成内嵌 derp.myinfra.net 的令牌
由于 DERP 节点地址直接存储在令牌内部,连接的客户端会自动解析会合中继,无需配置任何本地参数。
核心要点
- 零配置:无需账户、API 令牌或集中协调器。
- 用户空间安全性:以非特权方式运行;无需虚拟网卡、DNS 覆盖或防火墙修改。
- WireGuard 高性能:通过自动化 NAT 穿透,隧道连接可从 DERP 中继自动升级为点对点 UDP 连接。
- 高度可组合:可用作开箱即用的命令行工具、临时代理,或作为分布式服务的可嵌入 Go 语言库。
来源
tailscale/tailcat: like netcat, but over Tailscale's data plane, without Tailscale's control plane