为TailScale部署私有DERP中继服务器
什么是 TailScale
后面再补充,先写重点的 TailScale DERP 中继服务器。
关键词:UDP打洞,NAT,点对点连接,大局域网。
好处/场景:待补充
怎么用 TailScale:待补充
什么是 TailScale DERP 中继服务器
前面提到,TailScale 的作用是实现多设备点到点的直连通讯。所以相比 frp 这种星形的穿透,TailScale 不会存在传输速度被中转服务器限制的问题。
但有的时候,打洞会失败,这个时候就只能老老实实通过中继服务器来转发流量了。也就是说,DERP 的作用是打洞失败的兜底。
值得一提的是,TailScale 的中继服务器还有另外一个作用,在两个客户端刚建立连接的时候,TailScale会先使用 DERP 快速建立一条可用的连接,然后再尝试打洞,如果打洞成功,就会切换到直连。
为什么要自建 DERP 中继服务器
TailScale 是默认提供了中继服务器的,因为某些原因,国内没有中继,所以如果打洞失败的时候,延迟能达到几百上千 ms。
我们可以使用 tailscale netcheck
命令来看看所有的(官方和自建)中继服务器的延迟。
如何搭建
- 一台公网服务器
- 最好拥有一个备案了的域名
主要基于 docker compose
来安装,如果你喜欢折腾 Kubernetes
,也可以配一下 Ingress
什么的(未测试)。
证书准备
准备一个域名,并签发证书,放到某个独立文件夹(用于挂载到容器内)。
假如我们的子域名是 derp.example.com
,文件夹是 /home/xxx/infra/derper/certs
证书签发可以使用 acme.sh。
泛域名的证书可以直接给子域名用,但是要注意证书名要和子域名一致。即,文件夹内要有 derp.example.com.crt
和 derp.example.com.key
两个文件。
注:如果已经有 cert-manager 签发证书了,也可以偷懒直接把 Secret 复制过来改个名字(就是可能要手动定期更新证书)。或者尝试直接用 K8s 部署 DERP,把 Secret 挂到容器里。
Compose 文件
话不多说,直接准备 docker-compose.yml
文件。
version: '3.3'
services:
derper:
environment:
- DERP_DOMAIN=derp.example.com # DERP 域名,请解析到自己的服务器,并确保域名已备案
- DERP_CERT_MODE=manual # 证书模式,请设置成手动模式,自动的我貌似会有问题
ports:
- '80:80' # 这个端口貌似用不太到,一般不会用 http
- '443:443'
- '3478:3478/udp'
image: fredliang/derper
volumes:
- /home/xxx/infra/derper/certs:/app/certs # 冒号左边的是证书在宿主机内存放的路径,右边的不要改,建议用绝对路径
按需修改,注释说得挺详细,这里主要说一下端口:
- 如果冲突的话,改掉冒号左边的端口,并暴露出去就好。
- 亲测443端口可以改成8888什么的,可用。
- 3478 的这个我没改过,但理论上也可以改。
最后 docker compose up -d
或者 docker-compose up -d
就 OK 了!
配置 TailScale 客户端使用 DERP 服务器
网页登录 TailScale 账号,打开 控制台的 Access Control 页面,添加这样一段注释(也就是在原来的 json 里加个 "derpMap"
的 key)
{
// 这里是其他的原有的一些 key
"derpMap": {
// "OmitDefaultRegions": true,
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "my-derp",
"RegionName": "这里一般写机房的位置(纯标示用)",
"Nodes": [
{
"Name": "自己的derp",
"RegionID": 900,
"DERPPort": 443,
"STUNPort": 3478,
"HostName": "derp.example.com",
},
],
},
},
},
}
主要就是改三个字段,一个是 HostName
,一个是 DERPPort
和 STUNPort
。
完整的配置详见 go package ERPNode
测试
终端运行 tailscale netcheck
看看 DERP 有没有正常显示出来
也可以用 tailscale ping 节点名
看看走的什么中继(还是直连),以及延迟
甚至可以把上面的 json 被注释掉的 "OmitDefaultRegions": true
反注释了,然后保存。这样就是只用自己的 derp 节点,不用官方的。
出问题了的话,可以 docker compose logs
看看日志。(常见错误可能有:端口没开,证书无效,域名在A服务商备案了没在B备案导致直接被拦截等)
后记/资料
- 官方 DERP 文档
- 按照本文操作的话,只要别人知道你的域名和端口就能用你的DERP,耗你带宽。可以通过在 DERP 服务器上也装一个 TailScale 并在 DERP 启动的时候 加上
--verify-clients
参数来防止白嫖。具体的可以参考网上资料 - 这里还有一个不用域名只用 IP 来搭建 DERP 的教程,相对复杂,有兴趣的可以看看