Clloz's Blog

Back

Ubuntu 24.04 部署自建 Tailscale DERP Ubuntu 24.04 部署自建 Tailscale DERP

本文记录一套已经验证成功的部署流程:在腾讯云上海 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 HTTPSTCP 443
ACME HTTPTCP 80
STUNUDP 3478
自定义 Region ID901
自定义 Region Codeprivate-shanghai

请把文中的域名和公网 IP 替换为自己的值。

2. 前置条件#

  • 一台具有固定公网 IPv4 的腾讯云 CVM。

  • Ubuntu Server 24.04 LTS。

  • 一个域名,并已创建 A 记录,例如:

    derp.example.com → 腾讯云公网 IPv4
    text
  • 可以管理腾讯云安全组。

  • 使用官方 Tailscale 控制面,并有权限编辑 Tailnet Policy。

  • 公司端和家庭端均已安装并登录同一个 Tailnet。

先检查 DNS:

dig +short A derp.example.com
bash

返回结果必须是服务器的公网 IPv4。

3. 腾讯云安全组#

添加以下 IPv4 入站规则:

来源协议端口用途
0.0.0.0/0TCP80Let’s Encrypt HTTP-01 验证及跳转
0.0.0.0/0TCP443DERP over TLS
0.0.0.0/0UDP3478STUN
管理员固定公网 IP(推荐)TCP22SSH 管理

注意腾讯云会分别配置 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 100
bash

把公钥加入服务器:

ssh-copy-id ubuntu@SERVER_PUBLIC_IP
bash

确认新终端能使用密钥登录后,再创建 SSH 配置片段:

sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
bash

写入:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
text

检查语法并平滑重载:

sudo sshd -t
sudo systemctl reload ssh
bash

不要在验证密钥登录前关闭密码认证。确认安全组已将 TCP 22 限制到自己的公网 IP 后,再结束原 SSH 会话。

5. 安装基础工具#

sudo apt update
sudo apt install -y curl wget git jq build-essential libcap2-bin
bash

本文不执行完整系统升级,以避免在部署过程中引入不必要的服务重启;系统升级可单独安排维护窗口。

6. 安装最新版 Go#

Tailscale 官方没有提供 derper 的 apt 包或独立安装包,官方流程是使用最新稳定版 Go 执行 go install

Go 官方下载页 查询当前稳定版本,并根据架构选择包:

uname -m
bash
  • x86_64:下载 linux-amd64
  • aarch64:下载 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 version
bash

应看到类似:

go version go1.25.1 linux/amd64
text

7. 构建并安装 derper#

go install tailscale.com/cmd/derper@latest
~/go/bin/derper -version
bash

将生成的二进制安装到系统目录:

sudo install -m 0755 ~/go/bin/derper /usr/local/bin/derper
/usr/local/bin/derper -version
bash

以后升级时重新运行 go installinstall,然后重启服务。官方建议 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/certs
bash

当前版本的 derper 需要通过 -c 指定持久化配置文件。首次启动时会创建该文件,其中包含 DERP 私钥。不要公开或粘贴其内容。

9. 创建 systemd 服务#

创建服务文件:

sudo nano /etc/systemd/system/derper.service
bash

写入:

[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.target
ini

derp.example.com 替换为真实域名,然后启动:

sudo systemctl daemon-reload
sudo systemctl enable --now derper
sudo systemctl status derper --no-pager
bash

查看实时日志:

sudo journalctl -u derper -f
bash

正常启动日志应包含类似内容:

STUN server listening on [::]:3478
No mesh key configured
derper: serving on :443 with TLS
text

单节点部署出现 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 -ls
bash

备份 /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;不要放入 grantsssh 数组内部。

保留官方 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": false
json

这样自建 DERP 不可用时,客户端仍可回退到官方 DERP。只有拥有多节点高可用设计并明确理解故障影响时,才考虑移除默认区域。

保存策略后通常无需重新执行 tailscale up;客户端会从控制面取得更新。若短时间内未出现新区域,可稍等片刻后重新执行检查命令。

12. 最终验证#

12.1 两端检查 DERP 延迟#

在公司端和家庭端分别执行:

tailscale netcheck
bash

预期包含:

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_NAME
bash

最终成功结果示例:

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 14ms
text

其中:

  • via DERP(private-shanghai):确认实际中继使用的是自建 DERP。
  • direct:说明 P2P 直连成功,这是更优路径,不是故障。
  • 其他 Region Code:说明当前使用了别的 DERP,需要比较两端 netcheck、策略下发和网络连通性。

还可以执行:

tailscale status
tailscale debug derp
bash

12.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 today
bash

重启并复查:

sudo systemctl restart derper
sudo systemctl status derper --no-pager
bash

升级 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 -version
bash

验证开机自启:

sudo systemctl is-enabled derper
sudo systemctl is-active derper
bash

建议定期执行:

curl --noproxy '*' -fsS https://derp.example.com/ >/dev/null
tailscale netcheck
bash

生产环境可进一步使用官方 derpprobe 进行持续健康监控。

14. 备份与恢复#

建议备份:

/etc/systemd/system/derper.service
/var/lib/derper/derper.json
Tailnet Policy 中的 derpMap
text

其中 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 derper
bash

15. 安全和设计注意事项#

  • DERP 不应和另一台 DERP 共用同一个公网 IP。
  • 不要在 DERP 前放普通 HTTP 反向代理或全局负载均衡器。
  • 不要限速 STUN 的 UDP 3478,也不建议限制 DERP 的出站 TCP。
  • 自定义 DERP 不支持设备共享等跨 Tailnet 功能。
  • 单节点部署优先保持一个 Region 一个 Node;多节点同 Region 需要正确 mesh 和监控。
  • 本指南未启用 -verify-clients。该功能要求同机运行 tailscaled,并且官方建议 derpertailscaled 来自同一 Git revision,维护复杂度更高。
  • 保留官方 DERP 可以避免单台腾讯云服务器维护或故障时中断连接。

16. 官方参考#

Ubuntu 24.04 部署自建 Tailscale DERP
https://clloz.com/blog/tailscale-derp-server
Author Clloz
Published at July 20, 2026
Comment seems to stuck. Try to refresh?✨