Tailscale 自建 DERP 中继连接失败(Nginx 404)排查与解决记录
一、问题现象
Tailscale 客户端(Windows)无法连接自建 DERP 中继,健康检查持续提示:
# Health check: # - Tailscale could not connect to the 'LLY' relay server. Your Internet connection might be down, or the server might be temporarily unavailable.
tailscale netcheck 显示到该中继延迟正常(约 30ms),UDP 可用,NAT 穿透成功,但实际无法建立 DERP 连接。
二、环境说明
控制平面:Headscale 或类似自建方案(用户标识非标准邮箱)
客户端:Windows,Tailscale 版本较新
自建 DERP 服务器:Linux,使用 Nginx 作为 443 端口入口
DERP 区域配置:自定义区域 900(广州 / LLY),指向自有域名
后端 DERP 服务:
derper,监听本地端口(如127.0.0.1:1234)
三、排查过程与关键发现
1. 基础网络检查
tailscale netcheck
输出显示 UDP 可用、IPv4 正常、NAT 类型为 UPnP/NAT-PMP/PCP,最近 DERP 为 LLY,延迟约 29.7ms。说明网络层可达,问题不在基础连通性。
2. 查看客户端实时日志
tailscale debug daemon-logs
日志中出现关键错误:
derphttp.Client.Recv: connecting to derp-900 (广州) derphttp.Client.Recv connect to region 900 (广州): GET failed: <nil>: <html> <head><title>404 Not Found</title></head> <body> <center><h1>404 Not Found</h1></center> <hr><center>nginx</center> </body> </html>
101 Switching Protocols。说明请求被 Nginx 的 HTTP 七层反向代理拦截,没有正确转发给后端的 derper 服务。3. 直接测试 DERP 端点
使用 curl 模拟 DERP 的 HTTP Upgrade 请求:
curl.exe -v --noproxy "*" -H "Upgrade: websocket" -H "Connection: Upgrade" https://your-derp-domain.com/derp
修复前返回 404 Not Found(Nginx 页面)。
修复后返回:
< HTTP/1.1 101 Switching Protocols < Connection: upgrade < Upgrade: DERP < Derp-Version: 2 < Derp-Public-Key: <公钥>
这证明 DERP 握手成功。
4. 检查 Nginx 配置
原始 Nginx 配置片段(位于 http {} 块内):
location ^~ /
{
proxy_pass http://127.0.0.1:1234;
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 REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
add_header X-Cache $upstream_cache_status;
set $static_fileHlIrpUOR 0;
if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" )
{
set $static_fileHlIrpUOR 1;
expires 1m;
}
if ( $static_fileHlIrpUOR = 0 )
{
add_header Cache-Control no-cache;
}
}关键点:
proxy_http_version 1.1;必须设置,HTTP/1.1 才支持协议升级。proxy_set_header Upgrade $http_upgrade;将客户端的 Upgrade 头传递给后端。proxy_set_header Connection $connection_upgrade;将 Connection 头传递给后端。后端
derper必须实际监听127.0.0.1:1234。
四、解决方案
1. 启动并配置 derper 服务
derper -a :1234 -c /path/to/cert -hostname your-derp-domain.com
建议使用 systemd 管理 derper,确保开机自启和自动重启。
2. 配置 Nginx 反向代理(HTTP 七层 + Upgrade)
在 http {} 块顶层定义 $connection_upgrade 变量:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}然后为 DERP 域名配置 location(见上文「原始 Nginx 配置片段」)。
3. 配置 Headscale 的 DERP 地图
{
"derpMap": {
"OmitDefaultRegions": true,
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "广州",
"RegionName": "LLY",
"Nodes": [{
"Name": "1",
"RegionID": 900,
"HostName": "your-derp-domain.com",
"DERPPort": 443
}]
}
}
}
}注意:HostName 必须是可解析的域名,且证书有效。DERPPort 通常为 443。
4. 重启服务并刷新客户端
重载 Nginx:
nginx -s reload重启 Headscale 使 ACL 生效(如果修改了配置)
在客户端执行:
tailscale down tailscale up
五、验证方法
1. 测试 DERP 端点
curl.exe -v --noproxy "*" -H "Upgrade: websocket" -H "Connection: Upgrade" https://your-derp-domain.com/derp
期望输出:
< HTTP/1.1 101 Switching Protocols < Connection: upgrade < Upgrade: DERP < Derp-Version: 2
2. 检查 TCP 端口
Test-NetConnection your-derp-domain.com -Port 443
期望:TcpTestSucceeded : True
3. 查看 Tailscale 状态
tailscale netcheck
应显示自定义 DERP 区域及延迟,例如:
Nearest DERP: LLY DERP latency: - 广州: 29.7ms (LLY)
tailscale status
健康检查部分不再出现 could not connect to the 'LLY' relay server。
六、备份配置建议
| 文件 / 内容 | 路径示例 |
|---|---|
| Nginx 主配置及站点配置 | /etc/nginx/nginx.conf、conf.d/ |
| derper systemd 单元文件 | /etc/systemd/system/derper.service |
| Headscale 配置及 ACL | /etc/headscale/config.yaml、acl.hujson |
| TLS 证书与私钥 | /path/to/cert/ |
| 版本信息 | tailscale version、derper version |
建议将上述配置纳入版本控制(如 Git),并定期备份。
七、注意事项
DERP 协议升级与 WebSocket 类似,因此 Nginx 的 HTTP 七层反代 + Upgrade/Connection 头可以工作。但必须确保
proxy_http_version 1.1和正确的头传递。如果同一 443 端口还要服务其他网站,
location ^~ /会全部匹配,可能冲突。此时建议使用 Nginxstream {}四层转发 +ssl_preread按 SNI 分流。证书必须有效,且域名与
derper -hostname一致,否则客户端会拒绝连接。防火墙需放行 TCP 443,如果启用 STUN,还需放行 UDP 3478。
修改 Headscale ACL 后,客户端可能需要重新登录或重启 Tailscale 服务才能拉取新配置。
不要将敏感信息(域名、IP、公钥、用户 ID)公开分享,本文档已做脱敏处理。
八、总结
排查时,直接使用
curl 模拟 DERP 握手是最快的验证手段。看到 101 Switching Protocols 和 Upgrade: DERP 即表示链路正常。