DERP 是一个开源的、高性能的、基于 UDP 的 NAT 穿透解决方案,它可以帮助你在内网环境中搭建一个 VPN 服务。
Tailscale
是一个组网神器,可以让自己处于不同位置、不同网络环境的机器组成一个私有的局域网。但是,由于官方内置的 DERP 中转节点惟独不包含中国大陆,导致在国内使用的话,延迟非常高。网络不好的话,甚至不可用。所以,可以自建 Tailscale
的中转节点(DERP节点)方法。
1.服务介绍
DERP 是 Tailscale 自研的一个协议!
Tailscale
的终极目标是让多台处于网络上的任何位置的机器建立点对点直连效果,但是现实世界错综复杂,并不是所有设备都能直接通信,而且大部份情况下机器都位于 NAT 和防火墙后面,这时候就需要通过打洞来实现直连。为了解决这个问题,引入了 DERP 服务器作为中间节点,帮助在不同网络环境下的机器建立安全、可靠的点对点连接。
DERP(DERP Overlay Routing Protocol
)是 Tailscale
自研的一个协议,它根据目的公钥来中继加密的流量。其是 Tailscale
用于在不同网络环境中建立安全、可靠的点对点连接的协议。它通过在网络中建立一个覆盖网络,让所有连接到这个网络的设备都可以直接通信,而不需要经过传统的路由器。
降低延迟:将 DERP
服务器部署在本地或靠近用户的地区,可以有效减少网络延迟。提高稳定性:自建服务器可以避免因官方服务器故障或网络波动导致的连接不稳定问题。增强安全性:通过自建服务器,可以更好地控制数据传输的安全性。
$ tailscale status
x1 default macOS active; direct xxx:2756; offline, tx 50424 rx 34056
x2 default linux active; direct xxx:2834; offline, tx 1403688 rx 1217620
2. 服务部署(域名方案)
自建私有 DERP 中继节点
为了实现低延迟、高安全性,我们可以参考 Tailscale 官方文档 来搭建私有化的 DERP 服务器。有两种部署模式,一种是基于域名,另外一种不需要域名,可以直接使用 IP。
- 先置条件
首先,服务器需要有公网 IP
地址。其次,如果服务器在国内则域名需要备案,如果服务器在国外则不需要备案。
1.域名
2.SSL证书
3.准备一台或多台云服务器
- 容器化部署(推荐)
默认情况下会开启 STUN 服务,对应的 UDP 端口是 3478;能用 443 端口尽量用 443 端口,实在不行再用别的端口也行;并且申请的域名需要和证书名称进行适配。
# 可以自行构建镜像
$ docker run --restart always \
--name derper -p 443:443 -p 3478:3478/udp \
-v /etc/letsencrypt/live/demain_name:/app/certs \
-e DERP_CERT_MODE=manual \
-e DERP_ADDR=:443 \
-e DERP_DOMAIN=derper.example.com \
-d xxx/derper:latest
- 直接系统服务部署
# 下载
$ go install tailscale.com/cmd/derper@latest
$ cp ~/go/bin/derper /usr/local/bin/
# 配置
$ sudo mkdir -p /etc/derper
$ sudo vim /etc/derper/config.json
{
"RegionID": 900,
"RegionCode": "evh",
"RegionName": "Escape VPN Host",
"DerpPort": 1443,
"StunPort": 3478,
"VerifyClients": true
}
# 验证客户端信息
$ sudo derper --hostname=derper.xxx.com --verify-clients
# 域名添加证书信息
$ sudo derper -certmode manual -certdir ./
# 创建服务文件
$ sudo sudo /etc/systemd/system/derper.service
[Unit]
Description=Tailscale DERP Server
After=network.target
[Service]
ExecStart=/usr/local/bin/derper -c /etc/derper/config.json
Restart=on-failure
User=nobody
Group=nogroup
[Install]
WantedBy=multi-user.target
# 启动并启用服务
$ sudo systemctl enable derper
$ sudo systemctl daemon-reload
$ sudo systemctl start derper
$ sudo systemctl status derper
# 检查日志
$ sudo journalctl -u derper
# 配置防火墙
$ sudo ufw allow 443/tcp
$ sudo ufw allow 3478/udp
$ sudo ufw reload
# 申请域名
$ apt install certbot python3-certbot-nginx
$ sudo certbot certonly --nginx -d derper.xxx.com
# 配置证书(必须配置)
# https://github.com/tailscale/tailscale/issues/4072
$ sudo vim /etc/nginx/sites-available/derper.xxx.com
server {
listen 80;
listen 443 ssl;
server_name derper.xxx.com;
ssl_certificate /etc/letsencrypt/live/derper.xxx.com.crt;
ssl_certificate_key /etc/letsencrypt/live/derper.xxx.com/privkey.key;
location / {
client_max_body_size 50MB;
# websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
# other settings
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:1443;
}
}
3. 服务部署(无需域名)
自建私有 DERP 中继节点
为了实现低延迟、高安全性,我们可以参考 Tailscale 官方文档 来搭建私有化的 DERP 服务器。有两种部署模式,一种是基于域名,另外一种不需要域名,可以直接使用 IP。
# 参考地址
https://github.com/yangchuansheng/ip_derper
# 自签证书
https://github.com/yangchuansheng/ip_derper/blob/main/build_cert.sh
- 先置条件
对很多人来说,就算有自己的域名,如果没有备案,也是没办法部署在国内服务器上使用的。这个时候我们就只能从 derper
源码上动手脚了,找到 tailscale
仓库中的 cmd/derper/cert.go
文件,将与域名验证相关的内容删除或注释,然后自谦证书就可以了。
func (m *manualCertManager) getCertificate(hi *tls.ClientHelloInfo) (*tls.Certificate, error) {
//if hi.ServerName != m.hostname {
// return nil, fmt.Errorf("cert mismatch with hostname: %q", hi.ServerName)
//}
return m.cert, nil
}
- 容器化部署(推荐)
需要注意的是,使用 IP
的话,需要将 InsecureForTests
设置为 true
,以跳过域名验证,并且 hostName
字段需要设置为 IP
地址。
然后,暴露在暴露出来需要使用端口,比如 13443
和 13478
,前者是 HTTPS 端口,后者是 STUN 端口。浏览器访问 https://ip:13443,忽略证书安全看到下面内容表示安装成功。
$ cat docker-compose.yml
services:
tailscale:
restart: on-failure
name: tailscale_agent
container_name: tailscale/tailscale:v1.80.0
environment:
- TS_HOSTNAME=tailscale-docker
- TS_AUTH_ONCE=true
- TS_STATE_DIR=/data
volumes:
- "tailscale:/var/run/tailscale"
- "tailscale_data:/data"
derper:
restart: on-failure
container_name: derper_server
image: yangchuansheng/ip_derper
ports:
- 13443:443
- 13478:3478/udp
environment:
- DERP_VERIFY_CLIENTS=true
volumes:
- "tailscale:/var/run/tailscale"
depends_on:
- tailscale
volumes:
tailscale:
tailscale_data:
4. 配置Tailscale
Tailscale 的配置文件简单了解就行了
服务部署完毕之后,就可以在 Tailscale
/Headscale
中配置 DERP
节点了。一种是在线 URL 是 JSON 格式的,另外一种是本地文件是 YAML 格式的。这里,以在 Tailscale
中配置 DERP
节点为例。
- 进入 Admin console 配置 ACL,在 “ssh” 节点下方增加以下内容并保存。
- https://login.tailscale.com/admin/acls/file
{
"derpMap": {
// 可以设置为true值
// 这样不会下发官方的derper节点;测试或实际使用都可考虑打开
"OmitDefaultRegions": false,
"Regions": {
"900": {
// tailscale的900-999是保留给自定义derper的
"RegionID": 900,
"RegionCode": "escape_derper",
"RegionName": "Escape VPN Host",
"Nodes": [
{
"Name": "escape_derper_1",
"RegionID": 900,
"hostName": "<域名/IP>",
"DERPPort": 13443,
"STUNPort": 13478,
// 自建DERP公网IP地址
"IPv4": "xxx.xxx.xxx.xxx",
// 如果你的服务器没有IPv6
"IPv6": "none",
// 因为是自签名证书所以客户端不做校验
"InsecureForTests": true,
},
],
},
},
},
}
这里,官方也给出了移除官方自带节点的配置,如下所示:
{
// ... other parts of tailnet policy file
"derpMap": { "Regions": { "1": null } }
}
tailscale netcheck
实际上只检测 3478/udp
的端口, 就算 netcheck
显示能连,也不一定代表 443
端口可以转发流量。最简单的办法是直接打开 DERP
服务器的 https://xxx:13443
。页面显示正常且地址栏的 SSL
证书标签显示正常可用,那才是真没问题了。
# 查看DERP节点是否生效
$ tailscale netcheck
Report:
* Time: 2025-03-03T10:19:09.035162866Z
* UDP: true
* IPv4: yes, xxx.xxx.xxx.xxx:36830
* IPv6: no, but OS has support
* MappingVariesByDestIP: false
* PortMapping:
* CaptivePortal: false
* Nearest DERP: evh
* DERP latency:
- evh: 600µs (evh)
- tok: 139.5ms (Tokyo)
5. 防止白嫖
开启安全验证,保护服务安全。
默认情况下,自己的 DERP 服务节点是可以被任何人使用的,如果不想让其他人使用自己的节点,可以设置 DERP_VERIFY_CLIENTS=true
(默认是关闭的) 来限制只有经过认证的客户端才能连接。不然如果你的服务器是使用流量计费的方式,很快就会被别人用光了。需要注意的是,只有域名部署的方式才需要设置。
# 步骤一:在DERP服务器上安装Tailscale
就是上面的那个 docker-compose.yml 的部分,再部署的机器安装并验证。
# 步骤二:Derper服务上添加参数
$ derper --hostname=$DERP_DOMAIN \
--certmode=$DERP_CERT_MODE \
--certdir=$DERP_CERT_DIR \
--a=$DERP_ADDR \
--stun=$DERP_STUN \
--http-port=$DERP_HTTP_PORT \
--verify-clients=$DERP_VERIFY_CLIENTS
6. 参考文档
送人玫瑰,手留余香。