自建 Tailscale DERP 服务

/ dousha

近来搬了一次家,新屋的宽带是 NAT 套 NAT 套 cgNAT, 意味着家里的 NAS 只能通过 DERP 中转来通联了。虽然从技术上来说,距离最近的公用 DERP 服务器应该是香港节点,但是不知为何,NAS 偏偏对德克萨斯情有独钟。

顶着按秒计算的延迟和按位计算的带宽连 SSH 操作都很困难,而且短时间内我也不太可能找到换宽带的方法,那看来只有选择自建 DERP 这一个方案了。

DERP 服务器选型

和 Headscale 服务器不同,DERP 服务是要实打实转发流量的。2M 小水管肯定是没法承接这些任务的。况且我也不太希望流量需要绕一圈出省之后再进省,万一触发了 PCDN 一刀切我还得再各种扯皮。所以需要找到一个满足以下条件的服务器:

为了省钱,CPU 和内存指标都可以压得尽可能低,1 CPU + 1 GB 内存已经足够使用。一般来说,国内各个大厂云的轻量服务器就能满足要求。或者,如果你人缘够好,说不定别人已经建好了 DERP 服务器,你只需要加入即可。

之后的部分假定你有一台专门作为 DERP 的服务器(至少,80, 443 和 3478 端口空闲的服务器),安装 Debian 系的系统。同时假定你已经有一个备案过的可签发证书的域名。如果你需要直接通过 IP 访问的话,可以参考这个或者这个方案来爆改 DERP 服务器实现。

配置安全组 / 防火墙

需要放行以下端口和协议:

3478 端口是为了 STUN 打洞。

安装 DERP 服务

首先安装好 Go:

sudo apt install golang-go

如果你的 DERP 机器选在了国内,则还需要配置好 Go 的代理服务:

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

安装 DERP 服务只需要一行:

go install tailscale.com/cmd/derper@latest

这会把 derper 安装到 ${HOME}/go/bin/ 下。你可以把这个路径加到 PATH 中方便操作。

配置 DERP 服务

你的域名不一定非得是 derp.my.server.arpa. 之后遇到这个域名时替换成你的实际域名即可。

弄个证书

derper 无法指定证书文件,它要求证书名称一定是 $hostname.crt$hostname.key. 假如你通过 CertBot 或者 acme.sh 签发的证书不是这个格式,则还需要稍加修改。以 acme.sh 签发为例:

签发的证书在 ${HOME}/.acme.sh/derp.my.server.arpa_ecc 下,分别为 ${HOME}/.acme.sh/derp.my.server.arpa_ecc/fullchain.cer${HOME}/.acme.sh/derp.my.server.arpa_ecc/derp.my.server.arpa.key. 我们可以通过符号链接的方式创建满足 derper 要求的证书:

sudo mkdir -p /etc/derp/cert
sudo -E ln -s ${HOME}/.acme.sh/derp.my.server.arpa_ecc/fullchain.cer /etc/derp/cert/derp.my.server.arpa.crt
sudo -E ln -s ${HOME}/.acme.sh/derp.my.server.arpa_ecc/derp.my.server.arpa.key /etc/derp/cert/derp.my.server.arpa.key

之后可以手动启动 derper 测试配置是否正确:

sudo -E ${HOME}/go/bin/derper --certmode manual --certdir /etc/derp/cert --hostname derp.my.server.arpa

derper 启动后,访问 https://derp.my.server.arpa 应该可以看到 DERP 服务器的默认页面。

设置 Systemd 服务

derper 由于不是很稳定,经常会自己把自己跑崩溃,所以需要每隔 12 小时重启一下这个服务。如果你的 Systemd 版本比较新,可以通过指定 RestartRuntimeMaxSec 属性来设置其自动重启。

你需要替换一下 ExecStartderper 文件的路径

# /etc/systemd/system/derp.service
[Unit]
Description=Tailscale DERP Server
After=network.target
Wants=network.target

[Service]
Type=simple
User=root
Restart=always
RuntimeMaxSec=12h
ExecStart=/home/user/go/bin/derper --hostname derp.srvcdiag.com --certmode manual --certdir /etc/derp/cert
RestartSec=10

[Install]
WantedBy=multi-user.target

重载并使能服务即可:

sudo systemctl daemon-reload
sudo systemctl enable derp.service --now

设置 Headscale

进入到 Headscale 机器,新增一个 DERP 服务器描述文件 /etc/headscale/derp.yml:

# /etc/headscale/derp.yml
regions:
  900:
    regionid: 900
    regioncode: xaa
    regionname: My DERP
    nodes:
      - name: 900a
        regionid: 900
        hostname: derp.my.server.arpa
        stunport: 3478
        stunonly: false
        derpport: 443

然后编辑主配置文件包含 DERP 描述文件:

# /etc/headscale/config.yml
# 前略
derp:
  paths:
    - /etc/headscale/derp.yaml
# 后略

重启 Headscale 服务即可。所有客户端都会自动发现新配置的服务器并尝试与之通联。

冲浪

要验证自己的 DERP 服务器是否正确通联,可以在客户端节点上执行 tailscale netcheck:

$ tailscale netcheck

Report:
        * Time: 2025-09-20T05:38:55.582472335Z
        * UDP: true
        * IPv4: yes, ---.---.---.---:-----
        * IPv6: no, but OS has support
        * MappingVariesByDestIP: false
        * PortMapping: UPnP
        * CaptivePortal: false
        * Nearest DERP: My DERP
        * DERP latency:
                - xaa: 11.7ms  (My DERP)
                - sfo: 170.2ms (San Francisco)
                - lax: 170.8ms (Los Angeles)
                - sea: 178.5ms (Seattle)
                - den: 189.4ms (Denver)
                - hel: 192.6ms (Helsinki)
                - nue: 206.7ms (Nuremberg)
                - hkg: 210.8ms (Hong Kong)
                - dfw: 214.4ms (Dallas)
                - ord: 219.8ms (Chicago)
                - iad: 221.3ms (Ashburn)
                - hnl: 222.8ms (Honolulu)
                - tor: 225.7ms (Toronto)
                - mia: 226ms   (Miami)
                - nyc: 227ms   (New York City)
                - par: 237.7ms (Paris)
                - fra: 245.2ms (Frankfurt)
                - ams: 247.1ms (Amsterdam)
                - lhr: 254.6ms (London)
                - waw: 266.8ms (Warsaw)
                - mad: 271.6ms (Madrid)
                - tok: 273.2ms (Tokyo)
                - syd: 319.9ms (Sydney)
                - sin: 343.3ms (Singapore)
                - sao: 358.9ms (São Paulo)
                - blr: 381.1ms (Bangalore)
                - nai: 390.9ms (Nairobi)
                - dbi: 416.2ms (Dubai)
                - jnb: 437.5ms (Johannesburg)

至此,即使打洞失败,也可以通过 DERP 转发来实现可接受范围内的延迟和带宽了。

正在加载评论……

发表评论

您的评论将由管理员审核后方可公开显示。

Your comments will be submitted to a human moderator and will only be shown publicly after approval.