最近实验室领了主机,一台windows 32GB i7-14,平时也不用win,想着搞成linux server挂在实验室挺好的,24小时不断电,远程操控codex完成一些横向😃。实验室也有一些共用的server,但是共享的总还是不如私有的舒服,安全性也不可控(实验室的server几天前被人下了挖矿脚本,整成矿机了...),再说,性能也不如这台主机。于是我开始了折腾。
正常来说,想要外网访问内网机器,一个frp内网穿透就可以用了,这是最简单的。但是frp需要一台公网服务器,而我手上的腾讯云vps恰好快到期了,这时候我想起了之前经常听说的tailscale,好像是用来组网的,我一直想试试。
tailscale原理
先问了一下gpt这个tailscale是什么原理,gpt吐出p2p的时候,兴趣就来了,我想起来了一些远古的p2p下载软件例如迅某雷软件的辉煌过去。
tailscale的核心是一种叫做UDP打洞的技术,我查了一下,这项技术已经很老了,以前的bt也用过UDP打洞的方式,是一种很p2p的方式。最常用的目的是为了让两个躲在各自内网(躲在各自的NAT背后)的主机直接建立通信。

具体的打洞并建立直连的完整过程是这样的:
Tailscale有一台协调服务器(tracker,login.tailscale.com)
- tracker是认证中心,但这部分Tailscale做得其实很薄,他们在博客中也写到,这部分主要是外包给像Gmail这样的中心化服务厂商来做的。
- tracker主要负责登录认证、公钥分发等一些常见服务。这里的公钥分发最关键的应该是WireGuard的公钥分发。后面会提到,两台主机之间的PTP连接主要依靠WireGuard这种隧道来连接,所以公钥分发是很重要的一步。
两个内网主机需要先登录Tailscale,经过登录认证和公钥分发之后,就算加入了同一个虚拟内网(常说的Tailnet)。
- Tailnet是Tailscale的核心特色,你可以实现很多有意思的,之后会提到。就像使用真正的局域网一样去使用Tailnet中的所有设备,这件事是非常舒服的。
两台主机正式开始尝试建立建立P2P直连了。首先,两台主机需要拿到自己的候选地址。
- 候选地址一般是为了让对方连接,且对方可以连接的地址。你可以基本理解为这两台主机各自的公网IP地址和端口信息。为什么要说候选地址,而不直接说公网地址呢?因为有可能你的两台主机并不在两个独立的内网里。这种情况下,这个候选地址可能就是局域网内的地址,所以统一称为候选地址。
- 探测候选地址的过程一般会使用STUN。STUN 是一种网络探测协议,借助外部服务器看到自己的公网 IP 和端口是什么,全称是 Session Traversal Utilities for NAT。
- 一般的STUN服务是由DERP中继服务器同时提供的。DERP我们后面会讲。
- 在两台主机都拿到自己的候选地址之后,它们需要把候选地址发送给对方。但是他们现在又没有直接途径连接到对方并发送这个信息。如果有,就不用搭Tailscale了,他们可以直接直连。这时候,Tailscale中最重要的角色——DERP中继服务器就出现了。
由DERP负责协商两台主机,就是在两条主机之间提供一条转发通道,交换它们的候选地址和其他加密信息,使两台主机都可以拿到对方的候选地址,并以此为目的地尝试建立WireGuard直连隧道。
- DERP 全称 Designated Encrypted Relay for Packets,Encrypted表示DERP只负责转发加密的WireGuard数据包,没有能力解密。WireGuard的私钥始终只留在节点本地,永远不上传。
- Tailscale官方提供全球各个常见地区的DERP,没有大陆哈
- 以上海为例,不配自己的DERP的话,一般走官方的洛杉矶DERP,200ms的延迟,总体能用,只是有时候不稳定。但是如果打洞直连失败,fallback到使用DERP转发数据失败就很卡了,这个后面会说。
具体建立WireGuard直连隧道的过程是这样的:一方主机拿到对方的候选地址之后,向对方的公网地址发 disco 探测包(Ping),一边通过DERP给对方发一条叫做 CallMeMaybe 的信息,里面带着自己的公网地址。对方收到后也向这些地址发探测包。Ping pong完成之后,路径就可用了,整个WireGuard的数据直连就建立起来了。
A B ├──────── UDP DISCO Ping,探测 B 的地址 ───────────→ │ ├──────── DERP:CallMeMaybe(附 A 的候选地址) ───→ │ ←──────── UDP DISCO Ping,探测 A 的地址 ───────────┤ │ ├──────────────── DISCO Ping / Pong ──────────────┤ │ └──────── 路径可用后,WireGuard 数据直连 ──────────┘
- 详细的分析可以看官方的这篇博客:https://tailscale.com/blog/how-tailscale-works
上面的整个过程,是建立P2P直连成功的理想情况。
仍然有一定概率无法建立P2P直连。这时候,所有数据流量也会通过之前提到的官方DERP做中继转发。注意,在上面提到的整个过程中,DERP几乎只是做控制平面的转发功能,用来协商两台内网主机形成P2P直连。形成直连之后,几乎不用再用到DERP了。它们的数据将通过直连的WireGuard隧道传播,这样速度比较快。
如果建立P2P直连失败,这时候就会fallback到用官方的DERP做数据转发。只用官方的DERP,就会非常卡。这时候你就需要买一台公网vps来自建的DERP了,由于我手头正好有一台公网VPS,应该是腾讯云一年68元的轻量应用服务器,这个我也搭建了,后面会提到。
好了,你已经完全懂得tailscale了,之后可以让agent一把梭开始配置了,本地配好 ~/.ssh/config 就好了,agent会自己ssh上去配好所有的tailscale节点的哈哈。
配置的过程唯一需要人操作的就是在每台机器上都要登录tailscale的网站认证一下,这个agent也会给你网址的,常规的设备码的认证方式。
你的mac上可以下载一个tailscale客户端,可以看看有哪些机器,但是大部分高级的操作还是只能在官方网页上完成,比如加自己的中继和peer relay

Peer relay和DERP这两个中继区别
这里逻辑上有一点小绕,因为它们两个本质上都是一种中继服务。
DERP我们之前已经频繁提到过,它是用来协商两台主机之间交换候选地址及一些其他连接信息的一种中继服务。它的协商主要体现在控制层面;Peer Relay的中继主要体现在数据层面。
Peer relay是指对等中继,它提供的是一种在两台主机之间转发数据流量的服务。
Peer relay一般在无法建立P2P直连的情况下使用。我们前面已经提到过,官方的DERP中继服务器会转发你的数据包,这时候Peer relay这种服务就是由官方的DERP来提供的。
但是我们之前提到过,在中国大陆,官方的DERP,也就是官方免费的DERP中继服务器,有最低200ms的延迟。在无法建立P2P的情况下,单纯用官方DERP提供的Peer Relay服务,网速很难令人满意。所以这时候我们就需要一台公网VPS来自建DRP,并提供Peer Relay服务。一般来说,Peer Relay都是由DERP中继服务器同时提供的。
配置也很简单。你只需要让Agent在自己的公网vps上配置DERP的时候,顺便也加上Peer Relay功能就行。这部分也需要到官方网站上手动填写一些JSON配置,Agent都会一步一步教你。
一些好玩的
当你把手机、电脑和一台永不关机的内网服务器都连上之后,就可以实现:随时随地在iPhone的codex上,像访问内网设备一样访问远在学校实验室里的那台24小时服务器,在上面跑一些任务,远程Vibe Coding,跟踪任务状态,甚至临时处理一些运维事情,都非常方便。
这时候你可能会说:我直接用FRP内网穿透把那台机器透出来不就完事了吗?是的,我以前也是这么做的。但FRP有两个很明显的弊端:
FRP本身必须需要一台公网VPS做穿透服务,而Tailscale在很多场景下几乎不需要,它可以通过尝试打洞的方式建立直连。在我生活中80% 的情况下,它的直连都是可以成功的。
第二个情况是一个很现实的使用场景:比如你想在手机的Codex上打开部署在内网服务器的内网地址的一个网页,你是做不到的。因为你需要额外配置一个SSH转发,把内网服务器localhost/内网IP的端口的web服务转发到你手机的localhost。这件事情在iPhone上并不是那么方便实现。
但是假如你拥有一个真正的虚拟内网Tailnet,就可以直接访问那台服务器上在它的内网IP某个端口监听的服务,这件事非常丝滑。如果你在上面部署了很多端口的web服务,就不再需要一个一个SSH去做端口转发了,你可以直接访问任意端口。
出口节点 Exit Node
出口节点是指你可以指定Tailscale内网中的一台设备节点,作为当前这台设备的出网节点。这件事在具体场景下非常有用。
当你在iPhone上安装Tailscale之后,它是作为一个VPN代理设置存在的,和手机上原本的Shadowrocket或Surge这类代理App冲突。这个时候,你就需要将iPhone这台设备的出口节点设置为虚拟内网中的一台服务器。
我的内网那台服务器本身就配置了代理服务,clash/singbox这些,让iPhone复用这个内网服务器的代理服务去出口,几乎是一键配置的事情。