本文记录一套已经验证成功的部署流程:在腾讯云上海 CVM 上运行官方 derper,使用 Let’s Encrypt 自动签发和续期证书,通过 systemd 托管服务,并在官方 Tailscale Tailnet Policy 中加入自定义 derpMap。
适用场景:两端因公司防火墙、严格 NAT 等原因无法建立 Tailscale P2P 直连,官方 DERP 延迟过高,希望使用靠近两端的自建 DERP 降低中继延迟。
DERP 只转发端到端加密的 WireGuard 流量,无法解密业务数据。客户端仍会优先尝试直连;只有直连和其他更优路径不可用时才使用 DERP。
1. 最终架构#
公司设备 ── Tailscale ──┐
├── 腾讯云上海 DERP ── 加密中继
家庭设备 ── Tailscale ──┘
控制面:官方 Tailscale
中继面:自建 DERP(失败时保留官方 DERP 作为回退)text本文示例参数:
| 项目 | 示例值 |
|---|---|
| 系统 | Ubuntu Server 24.04 LTS |
| 登录用户 | ubuntu |
| DERP 运行用户 | derper(不可登录的系统用户) |
| 域名 | derp.clloz.top |
| DERP HTTPS | TCP 443 |
| ACME HTTP | TCP 80 |
| STUN | UDP 3478 |
| 自定义 Region ID | 901 |
| 自定义 Region Code | private-shanghai |
请把文中的域名和公网 IP 替换为自己的值。
2. 前置条件#
-
一台具有固定公网 IPv4 的腾讯云 CVM。
-
Ubuntu Server 24.04 LTS。
-
一个域名,并已创建 A 记录,例如:
textderp.example.com → 腾讯云公网 IPv4 -
可以管理腾讯云安全组。
-
使用官方 Tailscale 控制面,并有权限编辑 Tailnet Policy。
-
公司端和家庭端均已安装并登录同一个 Tailnet。
先检查 DNS:
dig +short A derp.example.combash返回结果必须是服务器的公网 IPv4。
3. 腾讯云安全组#
添加以下 IPv4 入站规则:
| 来源 | 协议 | 端口 | 用途 |
|---|---|---|---|
0.0.0.0/0 | TCP | 80 | Let’s Encrypt HTTP-01 验证及跳转 |
0.0.0.0/0 | TCP | 443 | DERP over TLS |
0.0.0.0/0 | UDP | 3478 | STUN |
| 管理员固定公网 IP(推荐) | TCP | 22 | SSH 管理 |
注意腾讯云会分别配置 IPv4 和 IPv6。若域名只有 A 记录,必须明确放行“全部 IPv4 地址”的 TCP 443;只放行 IPv6 443 不会生效。
若服务器拥有公网 IPv6 和 AAAA 记录,可另外添加对应的 IPv6 80/TCP、443/TCP、3478/UDP 规则。
本方案不要求启用 UFW。若 sudo ufw status 显示 inactive,流量主要由腾讯云安全组控制。若决定启用 UFW,必须先放行 SSH 和以上三个 DERP 端口,避免把自己锁在服务器外。
4. SSH 加固#
先在本地生成密钥(已有密钥可跳过):
ssh-keygen -t ed25519 -a 100bash把公钥加入服务器:
ssh-copy-id ubuntu@SERVER_PUBLIC_IPbash确认新终端能使用密钥登录后,再创建 SSH 配置片段:
sudo nano /etc/ssh/sshd_config.d/99-hardening.confbash写入:
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yestext检查语法并平滑重载:
sudo sshd -t
sudo systemctl reload sshbash不要在验证密钥登录前关闭密码认证。确认安全组已将 TCP 22 限制到自己的公网 IP 后,再结束原 SSH 会话。
5. 安装基础工具#
sudo apt update
sudo apt install -y curl wget git jq build-essential libcap2-binbash本文不执行完整系统升级,以避免在部署过程中引入不必要的服务重启;系统升级可单独安排维护窗口。
6. 安装最新版 Go#
Tailscale 官方没有提供 derper 的 apt 包或独立安装包,官方流程是使用最新稳定版 Go 执行 go install。
在 Go 官方下载页 ↗ 查询当前稳定版本,并根据架构选择包:
uname -mbashx86_64:下载linux-amd64aarch64:下载linux-arm64
以下用 GO_VERSION 表示当前稳定版本,请替换为实际版本号:
cd /tmp
GO_VERSION=1.25.1
GO_ARCH=amd64
wget "https://go.dev/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "go${GO_VERSION}.linux-${GO_ARCH}.tar.gz"bash把 Go 加入当前用户 PATH:
echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> ~/.profile
source ~/.profile
go versionbash应看到类似:
go version go1.25.1 linux/amd64text7. 构建并安装 derper#
go install tailscale.com/cmd/derper@latest
~/go/bin/derper -versionbash将生成的二进制安装到系统目录:
sudo install -m 0755 ~/go/bin/derper /usr/local/bin/derper
/usr/local/bin/derper -versionbash以后升级时重新运行 go install 和 install,然后重启服务。官方建议 derper 的更新频率大致与 Tailscale 客户端一致。
8. 创建专用系统用户和数据目录#
ubuntu 用于登录和管理;derper 系统用户只负责运行服务,两者职责不同。
sudo useradd \
--system \
--home /var/lib/derper \
--create-home \
--shell /usr/sbin/nologin \
derper
sudo mkdir -p /var/lib/derper/certs
sudo chown -R derper:derper /var/lib/derper
sudo chmod 750 /var/lib/derper /var/lib/derper/certsbash当前版本的 derper 需要通过 -c 指定持久化配置文件。首次启动时会创建该文件,其中包含 DERP 私钥。不要公开或粘贴其内容。
9. 创建 systemd 服务#
创建服务文件:
sudo nano /etc/systemd/system/derper.servicebash写入:
[Unit]
Description=Tailscale DERP Server
Documentation=https://github.com/tailscale/tailscale/tree/main/cmd/derper
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=derper
Group=derper
WorkingDirectory=/var/lib/derper
ExecStart=/usr/local/bin/derper \
-c /var/lib/derper/derper.json \
-hostname derp.example.com \
-certdir /var/lib/derper/certs \
-certmode letsencrypt \
-a :443 \
-http-port 80 \
-stun=true \
-stun-port 3478
Restart=on-failure
RestartSec=5s
# 仅允许非 root 服务绑定 80/443 等特权端口。
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=full
[Install]
WantedBy=multi-user.targetini将 derp.example.com 替换为真实域名,然后启动:
sudo systemctl daemon-reload
sudo systemctl enable --now derper
sudo systemctl status derper --no-pagerbash查看实时日志:
sudo journalctl -u derper -fbash正常启动日志应包含类似内容:
STUN server listening on [::]:3478
No mesh key configured
derper: serving on :443 with TLStext单节点部署出现 No mesh key configured 是正常的;mesh key 仅用于多个 DERP 节点互联。
10. Let’s Encrypt 自动证书#
-certmode letsencrypt 会按需申请证书,并自动轮换。首次收到带正确 SNI 的 HTTPS 请求时会触发签发。
从客户端直接访问,避免本地 HTTP 代理干扰测试:
curl --noproxy '*' -v https://derp.example.com/bash成功标志:
- TCP 443 连接成功。
- 证书域名匹配。
- 证书颁发机构为 Let’s Encrypt。
SSL certificate verify ok。- 返回
HTTP/2 200和 DERP 首页。
检查监听端口:
sudo ss -lntup | grep -E ':(80|443|3478)\b'bash应看到 TCP 80、TCP 443 和 UDP 3478 均由 derper 监听。
检查持久化文件:
sudo ls -la /var/lib/derper
sudo find /var/lib/derper/certs -maxdepth 2 -type f -lsbash备份 /var/lib/derper/derper.json 时要按私钥对待,不要提交到 Git 或公开分享。
不要把
derper放在 Nginx、Caddy、Traefik 等普通 HTTP 反向代理后面。DERP 会在 TLS 内从 HTTP 切换为自己的双向二进制协议,许多 HTTP 代理与此不兼容。
11. 配置 Tailnet Policy 的 derpMap#
打开 Tailscale 管理控制台,进入 Access controls / Policy file,使用 JSON 编辑器。在策略文件最外层加入 derpMap;不要放入 grants 或 ssh 数组内部。
保留官方 DERP 作为故障回退的示例:
{
"derpMap": {
"OmitDefaultRegions": false,
"Regions": {
"901": {
"RegionID": 901,
"RegionCode": "private-shanghai",
"RegionName": "Shanghai Private DERP",
"Nodes": [
{
"Name": "901a",
"RegionID": 901,
"HostName": "derp.example.com",
"IPv4": "203.0.113.10",
"DERPPort": 443,
"STUNPort": 3478
}
]
}
}
},
"grants": [{ "src": ["*"], "dst": ["*"], "ip": ["*"] }],
"ssh": [
{
"action": "check",
"src": ["autogroup:member"],
"dst": ["autogroup:self"],
"users": ["autogroup:nonroot", "root"]
}
]
}jsonc替换:
HostName:DERP 的真实域名。IPv4:服务器的真实公网 IPv4。RegionID:选择一个没有与现有 DERP 区域冲突的自定义编号,例如901。RegionCode:简短、稳定、唯一的标识,例如private-shanghai。
建议保持:
"OmitDefaultRegions": falsejson这样自建 DERP 不可用时,客户端仍可回退到官方 DERP。只有拥有多节点高可用设计并明确理解故障影响时,才考虑移除默认区域。
保存策略后通常无需重新执行 tailscale up;客户端会从控制面取得更新。若短时间内未出现新区域,可稍等片刻后重新执行检查命令。
12. 最终验证#
12.1 两端检查 DERP 延迟#
在公司端和家庭端分别执行:
tailscale netcheckbash预期包含:
Nearest DERP: Shanghai Private DERP
DERP latency:
- private-shanghai: 14.3ms (Shanghai Private DERP)text这证明客户端已取得自定义 DERP Map,并能连接该 DERP。
12.2 验证实际流量确实经过自建 DERP#
从一端 ping 另一端的 MagicDNS 主机名或 Tailscale IP:
tailscale ping PEER_NAMEbash最终成功结果示例:
pong from keenon (100.100.194.119) via DERP(private-shanghai) in 16ms
pong from keenon (100.100.194.119) via DERP(private-shanghai) in 14mstext其中:
via DERP(private-shanghai):确认实际中继使用的是自建 DERP。direct:说明 P2P 直连成功,这是更优路径,不是故障。- 其他 Region Code:说明当前使用了别的 DERP,需要比较两端
netcheck、策略下发和网络连通性。
还可以执行:
tailscale status
tailscale debug derpbash12.3 验证 RDP#
确认 tailscale ping 稳定后,在家庭设备上使用公司 Windows 设备的 MagicDNS 名称或 Tailscale IP 连接 RDP。DERP 中继延迟通常接近“两端到 DERP 的网络路径之和”,实际流畅度还受腾讯云带宽、RDP 画质、丢包和公司出口限制影响。
5 Mbps 公网带宽通常可用于基础办公型 RDP,但高分辨率、多屏、视频和动画场景可能触及带宽上限。若出现卡顿,应同时观察腾讯云出入带宽、丢包和 RDP 画质设置,而不能只看 ICMP/DERP 延迟。
13. 日常运维#
查看服务状态与日志:
sudo systemctl status derper --no-pager
sudo journalctl -u derper --since todaybash重启并复查:
sudo systemctl restart derper
sudo systemctl status derper --no-pagerbash升级 derper:
source ~/.profile
go install tailscale.com/cmd/derper@latest
sudo install -m 0755 ~/go/bin/derper /usr/local/bin/derper
sudo systemctl restart derper
/usr/local/bin/derper -versionbash验证开机自启:
sudo systemctl is-enabled derper
sudo systemctl is-active derperbash建议定期执行:
curl --noproxy '*' -fsS https://derp.example.com/ >/dev/null
tailscale netcheckbash生产环境可进一步使用官方 derpprobe 进行持续健康监控。
14. 备份与恢复#
建议备份:
/etc/systemd/system/derper.service
/var/lib/derper/derper.json
Tailnet Policy 中的 derpMaptext其中 derper.json 含私钥,备份必须加密并限制访问。Let’s Encrypt 证书可重新签发,证书缓存通常不需要作为核心备份。
恢复后执行:
sudo chown -R derper:derper /var/lib/derper
sudo chmod 750 /var/lib/derper /var/lib/derper/certs
sudo chmod 600 /var/lib/derper/derper.json
sudo systemctl daemon-reload
sudo systemctl enable --now derperbash15. 安全和设计注意事项#
- DERP 不应和另一台 DERP 共用同一个公网 IP。
- 不要在 DERP 前放普通 HTTP 反向代理或全局负载均衡器。
- 不要限速 STUN 的 UDP 3478,也不建议限制 DERP 的出站 TCP。
- 自定义 DERP 不支持设备共享等跨 Tailnet 功能。
- 单节点部署优先保持一个 Region 一个 Node;多节点同 Region 需要正确 mesh 和监控。
- 本指南未启用
-verify-clients。该功能要求同机运行tailscaled,并且官方建议derper与tailscaled来自同一 Git revision,维护复杂度更高。 - 保留官方 DERP 可以避免单台腾讯云服务器维护或故障时中断连接。