使用 Docker 部署自定义 DERP 服务器,支持域名反代和纯 IP 两种方案,配合 ACL 配置,支持 IPv6。

Tailscale 默认使用官方的 DERP 中继服务器,但在某些网络环境下延迟较高。自建 DERP 服务器可以显著降低中继延迟,特别是当你的节点分布在特定地区时。

前置条件

  • 一台有公网 IP 的 VPS(建议选择延迟低的地区)
  • 已安装 Docker 和 Docker Compose
  • 域名并配置好 DNS 解析(方案一需要,方案二不需要)
  • Nginx(或其他反向代理)处理 SSL(方案一需要,方案二不需要)

方案一:域名部署 DERP(反向代理模式)

Docker Compose 配置

创建 docker-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
derper:
container_name: derper
image: fredliang/derper
restart: always
network_mode: host # 直接使用宿主机网络,支持 IPv6
environment:
- DERP_DOMAIN=derp.example.com
- DERP_ADDR=:55555
- DERP_HTTP_PORT=55555
- DERP_VERIFY_CLIENTS=true
volumes:
- /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock

关键配置说明

配置项说明
network_mode: host必须。使用宿主机网络栈,支持 IPv6 和 STUN
DERP_DOMAIN你的 DERP 服务器域名
DERP_ADDR监听地址和端口
DERP_VERIFY_CLIENTS设为 true 验证客户端身份,防止滥用
tailscaled.sock挂载 Tailscale socket,用于客户端验证

注意:DERP_VERIFY_CLIENTS=true 需要服务器上运行 Tailscale 客户端,并且挂载其 socket 文件。

启动服务

1
docker compose up -d

Nginx 反向代理配置

DERP 使用 WebSocket 进行通信,需要正确配置反向代理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name derp.example.com;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

location ^~ / {
proxy_pass http://127.0.0.1:55555;

# 核心:强制发送 WebSocket 头
# 解决 HTTP/2 下头丢失导致 426 错误的问题
proxy_set_header Upgrade "websocket";
proxy_set_header Connection "upgrade";

# 必须:协议版本与关闭缓存
proxy_http_version 1.1;
proxy_buffering off;

# 基础头
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_set_header X-Forwarded-Port $server_port;

# 超时(保持长连接)
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

# 安全头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
}
}

重要配置解释

  1. 强制 WebSocket 头:proxy_set_header Upgrade "websocket" 和 Connection "upgrade" 是必须的,否则在 HTTP/2 下会出现 426 错误

  2. 使用 HTTP/1.1:proxy_http_version 1.1 确保 WebSocket 正常工作

  3. 关闭缓冲:proxy_buffering off 避免中继数据被缓存

  4. 长超时:86400 秒(24 小时)保持连接不断开

重载 Nginx:

1
sudo nginx -t && sudo nginx -s reload

Tailscale ACL 配置

登录 Tailscale Admin Console,进入 Access Controls,添加 derpMap 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
// 自定义 DERP 服务器
"derpMap": {
// 只使用自定义 DERP,禁用官方 DERP
"OmitDefaultRegions": true,
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "hkg",
"RegionName": "Tencent Cloud Hong Kong",
"Nodes": [
{
"Name": "hk1",
"RegionID": 900,
"HostName": "derp.example.com",
"DERPPort": 443,
"STUNPort": 3478
}
]
}
}
},
"acls": [
{
"action": "accept",
"src": ["*"],
"dst": ["*:*"]
}
]
}

配置说明

字段说明
OmitDefaultRegions设为 true 禁用官方 DERP,只用自建的
RegionID自定义区域 ID,建议用 900+ 避免冲突
RegionCode区域代码,如 hkg、sgp、tyo
HostNameDERP 服务器域名
DERPPortDERP 端口,通过 Nginx 反代后是 443
STUNPortSTUN 端口,保持 3478

可选:指定 IP 地址

如果不想走 DNS 解析,可以直接指定 IP:

1
2
3
4
5
6
7
8
9
{
"Name": "hk1",
"RegionID": 900,
"HostName": "derp.example.com",
"IPv4": "[IP_ADDRESS]",
"IPv6": "[IP_ADDRESS]",
"DERPPort": 443,
"STUNPort": 3478
}

方案二:无域名部署 DERP(纯 IP 模式)

如果你没有域名,或者不想折腾 DNS 和 SSL 证书,可以直接用 IP 地址部署 DERP 服务器。这种方式使用 ip_derper 镜像,会自动生成自签名证书,无需 Nginx 反向代理。

Docker Compose 配置

创建 docker-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
derper:
container_name: derper
image: ghcr.io/yangchuansheng/ip_derper:latest
restart: always
network_mode: host # 直接使用宿主机网络,支持 IPv6
environment:
- DERP_ADDR=:55555
- DERP_HTTP_PORT=55580
- DERP_CERTS=/app/certs
- DERP_VERIFY_CLIENTS=true
volumes:
- /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock

关键配置说明

配置项说明
ip_derper 镜像基于官方 derper 修改,支持纯 IP 运行,自动生成自签名证书
DERP_ADDR监听端口,这里使用 55555
DERP_CERTS自签名证书存放路径(容器内部自动生成)
DERP_VERIFY_CLIENTS设为 true 验证客户端身份,防止滥用
network_mode: host使用宿主机网络栈,支持 IPv6 和 STUN

与域名版本的区别:无域名版本不需要配置 Nginx 反向代理,DERP 服务器直接暴露端口,使用自签名 TLS 证书。

启动服务

1
docker compose up -d

ACL 配置

登录 Tailscale Admin Console,进入 Access Controls,添加 derpMap 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
// 自定义 DERP 服务器
"derpMap": {
// 只使用自定义 DERP,禁用官方 DERP,true 是只使用自己的节点,false 是自己的节点+官方节点
"OmitDefaultRegions": false,
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "chn",
"RegionName": "China",
"Nodes": [
{
"Name": "server",
"RegionID": 900,
"IPv4": "[IP_ADDRESS]",
"IPv6": "[IP_ADDRESS]",
"InsecureForTests": true,
"DERPPort": 55555,
"STUNPort": 3478
}
]
}
}
}
}

核心配置说明

字段说明
OmitDefaultRegionsfalse 表示同时使用自建和官方 DERP;true 表示只用自建
IPv4 / IPv6直接指定服务器 IP 地址,不走 DNS 解析
InsecureForTests核心配置:设为 true 允许跳过 TLS 证书校验(因为使用自签名证书)
DERPPort与 DERP_ADDR 配置的端口一致,这里是 55555
STUNPortSTUN 端口,默认 3478;设为 -1 可禁用该节点的 STUN

注意:InsecureForTests 虽然名称中包含 “ForTests”,但这是 Tailscale 官方提供的跳过 TLS 校验的正式配置项,在纯 IP 无域名场景下是必须的。

防火墙端口

端口协议用途
55555TCPDERP 中继
3478UDPSTUN
1
2
3
# UFW 示例
sudo ufw allow 55555/tcp
sudo ufw allow 3478/udp

验证 DERP 服务器

检查 DERP 状态

在任意 Tailscale 客户端执行:

1
tailscale netcheck

输出应显示你的自定义 DERP 区域及其延迟:

1
2
3
4
5
6
Report:
* UDP: true
* IPv4: yes, ...
* IPv6: yes, ...
* DERP latency:
- hkg: 25.3ms (Tencent Cloud Hong Kong)

检查连接方式

1
tailscale status

如果显示 relay "hkg" 或类似内容,说明正在使用你的 DERP 中继。

开放防火墙端口

确保服务器防火墙允许以下端口:

端口协议用途
443TCPHTTPS/DERP
3478UDPSTUN
1
2
3
# UFW 示例
sudo ufw allow 443/tcp
sudo ufw allow 3478/udp

常见问题

Q: 状态显示 IPv6: No

检查以下几点:

  1. 服务器是否有 IPv6 地址
  2. DNS 是否配置了 AAAA 记录
  3. Docker 是否使用 network_mode: host
  4. 防火墙是否放行 IPv6

Q: 426 Upgrade Required 错误

Nginx 配置问题,确保:

  1. 设置了 proxy_set_header Upgrade "websocket"
  2. 设置了 proxy_set_header Connection "upgrade"
  3. 使用 proxy_http_version 1.1

Q: 客户端验证失败

确保:

  1. 服务器上运行了 Tailscale 客户端
  2. 正确挂载了 /var/run/tailscale/tailscaled.sock
  3. 容器有权限访问该 socket

总结

自建 DERP 服务器的优势:

  • 降低中继延迟
  • 提升数据隐私性
  • 完全控制中继节点位置
  • 支持 IPv6

配置要点:

  • 使用 network_mode: host 支持完整网络功能
  • 方案一(域名):Nginx 反向代理需要正确配置 WebSocket 头
  • 方案二(纯 IP):使用 ip_derper 镜像 + InsecureForTests: true,无需域名和 Nginx
  • ACL 配置中可禁用官方 DERP 只用自建的