用了大半年 Tailscale,最大的感受不是”网速快”,而是它把一整类问题从根上消掉了。
传统组网你得处理:公网 IP、端口转发、DDNS、路由器防火墙规则、两边能不能互通、运营商 CGNAT……每一个都是单独的坑。Tailscale 的做法是:这些全都不需要你想。
它到底怎么做到的?
一、先说结论:这是”控制平面 / 数据平面”分离的经典范式
理解 Tailscale 只要抓住一句话:
协调服务器只负责”介绍大家认识”,数据从来不经过它。
┌─────────────────────────────────────────────────────────┐│ 控制平面(Control Plane)—— 只交换元数据,永不见明文 ││ ││ coordination server ││ ├─ 认证:这个设备是谁? ││ ├─ 分发:把 peer 的公钥 和 当前可达 endpoint 告诉 everyone││ └─ 策略:ACL / 子网路由 / DNS 记录 │└─────────────────────────────────────────────────────────┘ │ 交换公钥 + endpoint 地址(就这些) │┌───────────────────────────┴─────────────────────────────┐│ 数据平面(Data Plane)—— 设备之间直连,端到端加密 ││ ││ 笔记本 100.x.y.z ◄──── WireGuard (UDP) ────► 家里 PC ││ ││ 打洞失败时降级: ││ 笔记本 ◄── WireGuard over DERP(TLS 443) ──► 家里 PC │└─────────────────────────────────────────────────────────┘这个切分带来的直接后果:协调服务器被入侵,攻击者拿到的是一堆公钥和 IP 地址,不是你的文件内容。 数据平面的加密密钥在设备本地,服务器没有。
二、阶段 A:把设备加进同一个 tailnet
controlplane.tailscale.com participant A as 已在线的设备
(家里 PC) D->>D: 生成设备密钥 (curve25519) Note over D: 私钥永不离开本机,只上传公钥 D->>C: 发起登录 (SSO / auth key) C->>C: 验证身份,绑定到你的 tailnet C-->>D: 下发节点密钥 + 网络策略(ACL) + DNS 配置 D->>C: 上报本机 endpoint
(公网 IP:随机端口列表) C-->>A: 推送 peer 信息:新设备的公钥 + endpoint C-->>D: 推送 peer 列表:家里 PC 的公钥 + endpoint Note over D,A: 两端现在互相知道对方"是谁"和"在哪" Note over D,A: 但还没有任何一包数据通过
这里有个容易被忽略的点:协调服务器给的是公钥,不是私钥。 所以它从架构上就不可能解密你的流量。
身份体系是另一层东西。Tailscale 的设备身份有三类密钥:
| 密钥 | 作用 |
|---|---|
| 设备密钥(machine key) | 标识”这是哪台设备”,设备身份的生命周期 |
| 节点密钥(node key) | WireGuard 会话密钥,每次连接协商 |
| 预授权密钥(auth key / preauth key) | 给无头设备(服务器、树莓派、容器)用,免交互加入 |
第三类在自动化场景里非常有用。我 NAS 上跑的 Tailscale 就是用预授权密钥直接加入的,没有弹过任何登录页面:
tailscale up --authkey=tskey-auth-xxxxx --advertise-routes=192.168.1.0/24NOTE预授权密钥的泄露风险比密码高 —— 它是可重复使用的,能直接往你的 tailnet 里加设备。所以一般签发一次性(ephemeral)版本,且定期轮转。
三、阶段 B:NAT 打洞,然后直连
拿到对方 endpoint 之后,两台设备同时开始发包,目标是让中间的 NAT 设备在状态表里打开一个洞。
(协调服务器附属) participant P as 家里 PC (NAT 后) Note over L,P: 第一步:先经 DERP 完成真正的握手 L->>D: 中继包裹(内含 WireGuard 握手发起) D->>P: 转发给 P P->>D: 中继包裹(WireGuard 握手响应) D->>L: 转发给 L Note over L,P: ★ 隧道已建立,且双方都知道了
对方的 NAT 映射地址:端口 par 同时打洞 L->>P: UDP 直发(经对方 NAT 映射地址) and P->>L: UDP 直发(经对方 NAT 映射地址) end Note over L,P: 双向流量都通过了 → NAT 表已打开 L->>P: ⚡ WireGuard 直连,绕开 DERP P->>L: ⚡ WireGuard 直连,绕开 DERP Note over D: DERP 此后只在心跳阶段参与,不再承载数据
这是整个设计里最漂亮的一步。DERP 在这里的作用不是”中转流量”,而是”牵个线”:
NAT 穿越的难点在于:你不知道对方在 NAT 后的映射地址,而且通常只有一方能主动建连(对称型 NAT 双方都难)。DERP 让双方先通过中继完成握手,握手过程中双方互相通告了自己的源地址:源端口,然后同时向这个地址发包。
NAT 设备看到”有出站流量到 X
打洞失败怎么办
不是所有网络都允许 UDP —— 有些企业防火墙、有些酒店 Wi-Fi、有些移动网络会直接封 UDP。这时候自动降级到 DERP 中继,数据走 WireGuard over TLS 443:
tailscale status# 100.x.y.z laptop linux - 直接连接# 100.x.y.z nas linux relay "iad" 走 DERP 中继功能完全正常,只是延迟高一点。tailscale netcheck 可以看当前网络的 NAT 类型和 UDP 可用性。
TIP这也是为什么 Tailscale 在受限网络里”总能用”—— 它有一个永远能通的降级路径。中继走 443/TLS,几乎不可能被企业防火墙完全拦死。
四、拿到”局域网体验”的三层能力
直连只是基础。让人觉得”跟在一个局域网里”的其实是这三样:
1. MagicDNS —— 不用记 IP
tailscale status# 100.101.102.103 my-nas linux -# 100.104.105.106 my-laptop windows -ssh my-nasping my-laptop背后是 Tailscale 内置的 DNS resolver,把 my-nas 解析到 100.x.y.z,再由 netfilter 把这个网段的流量送进 WireGuard 隧道。
WARNING
100.64.0.0/10是 CGNAT 保留段(RFC 6598)。Tailscale 选它是为了几乎不可能和你的真实局域网冲突 —— 家宽和运营商内网正好也用这个段,所以反向的情况(你的设备真实地址就在 100.x 里)才是要小心的那个。Tailscale 也确实因此和某些 CGNAT 场景下的本地路由撞车,官方文档里明确列了这个已知冲突。
2. 子网路由 —— 访问”根本不在 tailnet 里”的机器
如果家里有一台没装 Tailscale 的打印机或摄像头,可以让装了 Tailscale 的那台 PC 当路由器:
# 在家里 PC 上tailscale up --advertise-routes=192.168.1.0/24
# 在管理后台批准这条路由(必须手动批准)批准后,其他 tailnet 设备就能直接访问 192.168.1.0/24,只有一台设备需要装 Tailscale。IP 转发和 SNAT 由 tailscaled 自动开好。
3. Exit Node —— 把整个出口搬到别处
tailscale up --exit-node=my-nas所有设备的默认流量都从 NAS 出去。典型用途是:人在国外想让国内设备走回国出口,或者反过来。
CAUTIONExit Node 和子网路由别同时无脑开。Exit Node 会接管默认路由,容易和本地 VPN(Clash 之类)打架 —— 这也是 Tailscale 和 Clash 共存时最常见的冲突点。配合使用时,一般要么让 Clash 跑在 Tailscale 之上(子网路由/Exit Node 出口),要么反过来明确指定
--exit-node只处理特定流量。
五、和 OpenTunnel 怎么选
上一篇写了用 OpenTunnel 把 opencode 暴露到公网。这里对比一下,因为两者经常被放在一起问:
| Tailscale | OpenTunnel | |
|---|---|---|
| 形态 | 私有网络,设备间互联 | 单点公网入口,一个 URL |
| 暴露面 | 只有 tailnet 内的设备 | 任何人拿到 URL 都能访问(要自己加鉴权) |
| 加密位置 | WireGuard,内核态,端到端 | TLS 在本地终结,盲转发 |
| 移动端 | 装 App | 浏览器直接开 |
| 适合 | 多台设备互联、访问内网服务 | 临时把本地 web 服务甩到公网 |
实际用法是组合拳:
Tailscale ──▶ 手机安全地回到家里内网OpenTunnel ──▶ 把某个服务单独甩到公网(带密码)TIP如果你只是想让手机访问家里几个服务,只用 Tailscale 就够了,别开 OpenTunnel —— 前者暴露面是”你的设备列表”,后者是”一个公网 URL”。安全边界完全不同。
小结
Tailscale 之所以能用得这么舒服,是因为它把三个本该由用户操心的问题各自交给了正确的层:
- 身份问题 → 协调服务器(但只管公钥,不管数据)
- 可达性问题 → DERP 中继做握手辅助 + NAT 打洞,失败自动降级中继
- 加密问题 → WireGuard 端到端,密钥在设备本地,服务端物理上无法解密
学 networking 的时候,“VPN = 加密隧道”这个印象会束缚你很久。Tailscale 告诉你的是:加密隧道只是数据平面,前面还需要一个不碰数据的控制平面;而可达性问题,可以用”先借道、再打洞、最后直连”的时序来解决。