抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

前言

本人是 Tailscale 重度用户,一家八口十几台全球各地的服务器以及笔记本手机 NAS 之类的设备都安装了 Tailscale,爽死了

但是最近电信不知道抽了什么风,早晚高峰Q得妈都不认识,还时不时间歇封锁几个官方中继,导致连接稳定性骤降。
为了对抗封锁和运营商 QoS,提升连接稳定性,萌生了自建中继的想法。
正好赶上阿里云做活动,2C2G 200Mbps 的轻量云服务器首年仅需 79,叠了点券 60 拿下,困了就有人送枕头,这下不得不建了(


准备:编译 derper

官方的 DERP 服务端不提供预编译的二进制文件,需要手动Go建:

1
2
3
4
5
6
git clone https://github.com/tailscale/tailscale.git
cd tailscale/cmd/derper

# 嫌慢也可以用 GOMAXPROCS 并发编译
go build -o derper
# GOMAXPROCS=$(nproc) go build -o derper

若你网络环境不佳(意思是在大陆且没有梯子),可在Go建前预先设置代理:

1
2
export GO111MODULE=on
export GOPROXY=https://goproxy.cn

等一会儿,应该会在构建目录看到一个叫 derper 的二进制文件,将它移动/上传到合适的地方并设置权限:

1
2
cp ./derper /usr/local/bin/
chmod +x /usr/local/bin/derper

测试一下:

1
derper -h

应能看到类似如下输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
Usage of derper:
-a string
server HTTP/HTTPS listen address, in form ":port", "ip:port", or for IPv6 "[ip]:port". If the IP is omitted, it defaults to all interfaces. Serves HTTPS if the port is 443 and/or -certmode is manual, otherwise HTTP. (default ":443")
-accept-connection-burst int
burst limit for accepting new connection (default 9223372036854775807)
-accept-connection-limit float
rate limit for accepting new connection (default +Inf)
-ace
whether to enable embedded ACE server [...]
-bootstrap-dns-names string
optional comma-separated list of hostnames to make available at /bootstrap-dns
-c string
...

到这里,derper 已经安装完毕。


方式一:使用域名运行(推荐,中国大陆需备案)

如果你有中国大陆备案域名,可以看这一段;否则请直接跳到「方式二:使用 IP 运行」。

1. 域名解析

准备一个域名,解析到你的服务器 IP,例如:

1
relay.inm.com → 114.51.41.9

2. 安装 acme.sh 申请证书

安装 acme.sh(网络条件良好时):

1
2
curl https://get.acme.sh | sh
source ~/.bashrc

如果网络条件不佳,可以改用 Gitee 镜像:

1
2
3
4
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m yajyuu_senpai@inm.com
source ~/.bashrc

假设你的域名 在 Cloudflare 托管,可以使用 DNS-01 验证方式:

  1. 在 Cloudflare 控制台创建一个 API Token,权限设定为:DNS 区域 - 编辑 - 你的域名。
  2. 在配置文件里填写凭据:
1
vi ~/.acme.sh/account.conf

添加如下内容:

1
2
CF_Token="你的Cloudflare API Token"
CF_Account_ID="你的AccountID"

然后申请证书并安装:

1
2
3
4
5
6
7
8
9
10
11
acme.sh --issue \
-d relay.inm.com \
--dns dns_cf \
--keylength ec-256

mkdir -p /var/lib/derper

acme.sh --install-cert -d relay.inm.com --ecc \
--fullchain-file /var/lib/derper/relay.inm.com.crt \
--key-file /var/lib/derper/relay.inm.com.key \
--reloadcmd "systemctl restart derper"

3. 将 DERP 节点限制为仅你的 Tailnet 可用

如果不想被人搭便车偷跑流量,最好设置为仅你的 Tailnet 网络设备可用。

在服务器上登录你的 Tailscale 账户,然后把服务器加入 Tailnet:

1
2
tailscale up
tailscale status

确认无误后,编写 systemd 服务文件:

1
sudo vi /etc/systemd/system/derper.service

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Unit]
Description=Tailscale DERP Server (Private)
After=network.target tailscaled.service
Requires=tailscaled.service

[Service]
User=root
ExecStart=/usr/local/bin/derper \
-hostname=relay.inm.com \
-certmode=manual \
-certdir=/var/lib/derper \
-a=:443 \
-stun \
-stun-port=3478 \
-verify-clients \
-socket=/var/run/tailscale/tailscaled.sock
Restart=on-failure
RestartSec=3
LimitNOFILE=500000

[Install]
WantedBy=multi-user.target

重载并启动:

1
2
sudo systemctl daemon-reload
sudo systemctl enable --now derper

检查运行情况:

1
journalctl -u derper -f

若日志中出现:

1
2
DERP server running on :443
STUN server running on :3478

说明已经正常运行。

关于未备案域名

未备案域名绑定大陆 IP,在特定网络环境下会遭遇「部分阻断」:

  • 普通 HTTP/HTTPS/UDP 流量不受干扰;
  • 但在进行 WebSocket Upgrade 时会遭到双向 RST 注入,打断连接。

表现为:

  • 客户端可以侦测到 DERP 节点在线,延迟也有数据;
  • Tailnet 内任何一台主机都无法连接到受影响的客户端;
  • 服务端日志频繁出现如下错误:
1
2
3
4
Apr  1 11:45:14 foxserver-cn derper[11451]: 1919/08/10 11:45:14 http: TLS handshake error from 114.51.41.9:11451: write tcp 191.98.10.1:19198->114.51.41.9:11451: write: connection reset by peer
Apr 1 11:45:14 foxserver-cn derper[11451]: 1919/08/10 11:45:14 http: TLS handshake error from 114.51.41.9:11452: write tcp 191.98.10.1:19198->114.51.41.9:11452: write: connection reset by peer
Apr 1 11:45:14 foxserver-cn derper[11451]: 1919/08/10 11:45:14 http: TLS handshake error from 114.51.41.10:11453: write tcp 191.98.10.1:19198->114.51.41.10:11453: write: connection reset by peer
Apr 1 11:45:14 foxserver-cn derper[11451]: 1919/08/10 11:45:14 http: TLS handshake error from 114.51.41.10:11454: write tcp 191.98.10.1:19198->114.51.41.10:11454: write: connection reset by peer

受影响客户端会看到类似提示:

1
2
3
# Health check:
# - Tailscale could not connect to the 'Yajyuu Senpai DERP Service' relay server.
# Your Internet connection might be down, or the server might be temporarily unavailable.

若出现上述情况,这基本可以判定你受到了阻断,建议更换到 基于 IP 的运行方式


方式二:使用 IP 运行(自签证书)

使用 IP 地址运行 DERP 节点则不需要公网可用的域名,仅需要公网 IP 自签证书即可。

1. 准备证书目录

1
sudo mkdir -p /var/lib/derper

一般情况下,在后续步骤中,derper 会自动生成自签证书,无需手动干预。但如果出现错误或者想更改证书内容,可以手动生成:

1
2
3
4
5
6
7
8
# 以 114.51.41.91 为例
openssl req -x509 -newkey ec \
-pkeyopt ec_paramgen_curve:prime256v1 \
-keyout 114.51.41.91.key \
-out 114.51.41.91.crt \
-days 365 \
-subj "/CN=114.51.41.91" \
-nodes

这里的 CN=114.51.41.91 使得证书只对 114.51.41.91 这个 IP 有效。
有效期可以随便写,但不宜设置得太短,因为到期需要手动更换,可以直接签个 100 年。

将证书和私钥放到 /var/lib/derper 中(如有需要):

1
sudo mv 114.51.41.91.* /var/lib/derper/

2. 编写 systemd 服务

接下来写一个 systemd service 文件用来运行服务(注意更改 IP 和端口):

1
sudo vi /etc/systemd/system/derper.service

内容示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[Unit]
Description=Tailscale DERP Server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=/var/lib/derper
ExecStart=/usr/local/bin/derper \
-hostname 114.51.41.91 \
-a :9810 \
-stun \
-stun-port 3478 \
-http-port -1 \
-certmode manual \
-certdir /var/lib/derper \
-verify-clients \
-socket /var/run/tailscale/tailscaled.sock
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

加载并启动服务:

1
2
sudo systemctl daemon-reload
sudo systemctl enable --now derper

3. 计算自签证书指纹

后续在 ACL 中配置自签证书时,需要用到证书的 SHA256 指纹:

1
openssl x509 -in /var/lib/derper/114.51.41.91.crt -noout -fingerprint -sha256

输出类似:

1
SHA256 Fingerprint=39c6db53804bc0992ea35a1d64dc3ec381a904222a6360cc40c3e6677896f278

请妥善保存该指纹,这是后面会用到的神奇妙妙工具。

检查服务运行情况:

1
journalctl -u derper -f

确认它为 active (running),且日志里没有明显错误或警告即可。

为什么不推荐IP证书?

DERP 路径里,Tailscale 客户端是按我们在 derpMap 里写的 HostName + CertName 来校验证书的:

现在如果用的是自签证书,配上CertName: “sha256-raw:<证书指纹>”
tailnet 里所有 client 都是按 指纹 pin,不会走系统 CA,也不在乎证书是不是可信 CA 签出来的。

若你的 DERP 是 完全私用,只有你自己接入,就不需要让普通浏览器访问它,也不需要给外部第三方看这个证书。
更别说免费IP证书有效期往往只有一个月甚至几天,配这种东西就是徒增成本。
从功能 / 稳定性角度来说,换成「免费 IP 证书」几乎没有额外收益,反而增加复杂度和潜在故障点。

接入 Tailnet:控制台配置 derpMap

此时 DERP 服务器已经成功运行,但 Tailnet 还不知道它的存在,需要在控制台 ACL 规则中声明。

打开管理后台:Access controls - Tailscale

在你原有的配置中,新增一个 derpMap 块。

1. 使用域名 + 证书的配置示例

如果在 DERP 中使用了域名(如 relay.inm.com),并且证书链正常,可以参考如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"derpMap": {
"OmitDefaultRegions": false,
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "inm",
"RegionName": "Yajyuu Senpai DERP Service",
"Nodes": [
{
"Name": "inm",
"RegionID": 900,
"HostName": "relay.inm.com",
"IPv4": "114.51.41.91",
"DERPPort": 443,
"STUNPort": 3478
}
]
}
}
},

// 其他配置
"acls": [
...
]
}

2. 使用 IP + 自签证书的配置示例

如果使用 IP 地址并且采用自签证书,可以参考以下写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"derpMap": {
"OmitDefaultRegions": false,
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "inm",
"RegionName": "Yajyuu Senpai DERP Service",
"Nodes": [
{
"Name": "inm-ip",
"RegionID": 900,
"HostName": "114.51.41.91",
"IPv4": "114.51.41.91",
"DERPPort": 12345,
"STUNPort": 3478,
"CertName": "sha256-raw:39c6db53804bc0992ea35a1d64dc3ec381a904222a6360cc40c3e6677896f278"
}
]
}
}
},

// 其他配置
"acls": [
...
]
}

注意根据你实际的:

  • 公网 IP;
  • derper 监听端口(DERPPort);
  • STUN 端口;
  • 证书指纹;

进行对应替换。


刷新客户端配置并测试

1. 强制刷新客户端 DERP 配置

在客户端机器上执行:

1
2
sudo tailscale down
sudo tailscale up

2. 检查 DERP 节点状态

使用以下命令检查 DERP 节点是否已更新,并且连接正常(假设 RegionID 为 900):

1
tailscale debug derp 900

如果输出中没有错误,那么表示配置已经生效。

IP 搭建的 DERP 有时会出现failed to verify certificate或者Error making request to the captive portal check的错误,这并不影响使用。

3. 实际连通性测试

使用 tailscale ping 命令检查与其它设备的连接:

1
tailscale ping foxstation

若无问题,可再进行 SSH 测试:

1
ssh root@foxstation

如果能够正常连接、且在晚高峰也没有明显卡死或大面积超时,便可以认为自建 DERP 已经正确接入 Tailnet,并且在当前网络环境下比官方节点更稳定。


结语

在中国大陆自建 Tailscale DERP 节点,本质上是在和运营商 QoS、间歇性封锁打架,官方节点再优秀(其实也并不优秀),也很难针对你所在的小区/机房做定制优化,自建 DERP 则给了你一个可以完全掌控的「就近中继」方案。

需要注意的是,自建 DERP 并不能解决所有问题(例如对端网络极差、路由异常等),但在多数「运营商盯着P2P QOS」的场景中,效果还是相当可观的。

如果你也和我一样是 Tailscale 重度用户,有一堆机器需要在晚高峰互相打洞连线,那么花亿点时间搭一个自己的 DERP,大概率是值回票价的。

评论