打造零维护的私有工业级 Tailscale DERP 中继服务器(Nginx Stream SNI 分流 + 泛域名证书)
打造零维护的私有工业级 Tailscale DERP 中继服务器(Nginx Stream SNI 分流 + 泛域名证书)
在自建 VPN 或组网工具(如 Tailscale)时,官方公共 DERP 中继服务器有时会因为地理位置或网络运营商策略导致延迟较高、丢包严重。为此,我们可以利用一台位于优质线路(如 CN2 GIA)上的 VPS 搭建专属的私有 DERP 中继服务器。
然而,生产环境的 VPS 通常已经部署了 Nginx 并且占用了标准的 443 端口来托管各种 Web 应用。如何在不冲突、不影响现有业务的前提下,让私有 DERP 服务器完美共存并实现端口复用?本文将分享一套基于 Nginx Stream 模块的 SNI 端口多路复用与复用 acme.sh 泛域名证书的"工业级"完美部署方案。
一、 方案设计与优势
- 端口多路复用(SNI Routing):利用 Nginx 的
stream模块在第四层(L4)读取 TLS 握手时的 SNI(Server Name Indication)信息。将访问derper.example.com的流量精准转发至内部的derper监听端口,而其余所有常规 HTTPS 网站流量则正常转发至 Web 后端,实现 443 端口完美共存。Nginx stream 是纯 TCP 四层透传,不改源地址、不终止 TLS,因此不违反 DERP 对直连公网的要求(云厂商七层负载均衡那种不行,四层透传没问题)。 - 零维护证书同步:直接通过软链接(Symlink)复用系统已有的
acme.sh泛域名证书(如*.example.com)。证书由acme.sh自动续期,derper无需占用 80 端口进行独立的 HTTP 验证,做到了真正的"一次配置,永久省心"。
二、 准备工作
- 一台具有公网 IP 的 VPS(建议选择优化线路)。
- 服务器上已安装 Nginx,并且已通过
acme.sh配置好了该域名的泛域名 SSL 证书。 - 确保已安装 Go 语言环境(用于编译安装
derper)。
三、 完整部署步骤
第一步:安装与配置 derper
-
使用 Go 语言官方命令直接安装 Tailscale 的
derper工具:go install tailscale.com/cmd/derper@latest sudo cp ~/go/bin/derper /usr/local/bin/ -
创建专用的证书存放目录:
sudo mkdir -p /etc/derper-certs -
使用软链接将
acme.sh生成的泛域名证书关联到derper目录中(请将路径替换为您实际的acme.sh证书路径):sudo ln -sf /path/to/.acme.sh/example.com_ecc/fullchain.cer /etc/derper-certs/derper.example.com.crt sudo ln -sf /path/to/.acme.sh/example.com_ecc/example.com.key /etc/derper-certs/derper.example.com.key
第二步:配置 Systemd 后台托管服务
为了确保 derper 能够开机自启并异常崩溃后自动拉起,我们需要为其编写一个 systemd 服务文件。
执行以下命令创建服务配置:
sudo bash -c 'cat << "EOF" > /etc/systemd/system/derper.service
[Unit]
Description=Tailscale Private DERP Server
After=network.target
[Service]
User=root
ExecStart=/usr/local/bin/derper --hostname=derper.example.com --http-port=-1 -a=:33443 --certdir=/etc/derper-certs
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF'
- 参数解析:
--hostname=derper.example.com:指定中继服务器的域名。--http-port=-1:关闭内置的 HTTP 验证端口(因为我们直接使用现成证书,不需要它监听 80 端口申请)。-a=:33443:让derper监听在本地的33443端口,等待 Nginx 的流量转发。--certdir:指定证书所在的目录。
重载并启动服务:
sudo systemctl daemon-reload
sudo systemctl enable --now derper
第三步:配置 Nginx Stream SNI 分流
修改 Nginx 的主配置文件(通常位于 /etc/nginx/nginx.conf),在全局层级(与 http { ... } 块同级)添加 stream 模块,实现根据域名进行四层流量分发:
stream {
# 根据客户端请求的 SNI 域名进行分流映射
map $ssl_preread_servername $backend_name {
derper.example.com derper_backend;
default web_backend;
}
# DERP 中继后端(本地 33443 端口)
upstream derper_backend {
server 127.0.0.1:33443;
}
# 常规 Web 网站后端(例如内部 8443 端口或其他服务)
upstream web_backend {
server 127.0.0.1:8443;
}
server {
listen 443 reuseport;
listen [::]:443 reuseport;
proxy_pass $backend_name;
ssl_preread on;
}
}
测试 Nginx 配置并平滑重载:
sudo nginx -t
sudo systemctl reload nginx
第四步:在 Tailscale 控制台中挂载私有节点
登录 Tailscale 管理后台,进入 Access Controls(访问控制),在 ACL 规则的 JSON 中加入自定义的 derpMap 区域配置:
{
"derpMap": {
"OmitDefaultRegions": false,
"Regions": {
"901": {
"RegionID": 901,
"RegionCode": "Custom-Region",
"RegionName": "My Private DERP",
"Nodes": [
{
"Name": "901a",
"RegionID": 901,
"HostName": "derper.example.com"
}
]
}
}
}
}
注:
derpMap之外的字段(如你已有的grants/acls授权规则)请保留自己的配置,无需改动。RegionID 使用 900 系列是 Tailscale 官方示例的做法,避开与官方区域的数字段冲突即可。
保存后,在客户端机器上执行网络检查命令:
tailscale netcheck
如果在输出列表中成功看到了刚才配置的私有区域,说明你的私有 DERP 中继服务器已经正式上线并被客户端识别了!
四、 常见排错与日常维护
- 日志提示
no config path specified; using .../derper.key: 这是derper源码中的标准硬编码提示信息,表示没有通过-c传入额外的 JSON 配置文件。只要命令行参数中正确指定了--certdir和--hostname,此提示可直接忽略。 - 证书自动续期后的更新:
由于我们采用了软链接直接指向
acme.sh的证书目录,当acme.sh定期自动更新证书后,文件内容会自动生效。你只需要在续期脚本的钩子中,或者手动执行一次服务重启即可加载最新证书:sudo systemctl restart derper netcheck里看不到私有节点: 客户端本地策略未及时同步,重跑tailscale up或重启 Tailscale 客户端,强制拉取控制台最新配置即可。- 节点显示但延迟异常/不可用: 检查服务器防火墙是否放行了 UDP 3478 端口。DERP 服务器需要开放 HTTP(80)、HTTPS(443)、STUN(3478) 三个端口,其中 3478 是 STUN 端口,常用于客户端测速与直连探测,只放行 443 会导致节点"注册成功但体验不佳"。
五、 总结
通过这套架构,我们不仅拥有了一个完全自主可控、高带宽低延迟的私有 Tailscale 中继网络,还极其优雅地解决了 443 端口被 Web 服务占用的痛点,并借助 acme.sh 做到了证书管理的"零维护"。如果你也有多服务共存和异地组网的需求,不妨也动手试试吧!