从自建DERP到Peer Relay:用阿里云ECS稳定访问内网服务

我认为 Peer Relay 解决的不是“能不能连上”,是“已经能连上,但中继链路还不够稳定”。

2024 年我在阿里云 ECS 上搭过一套自建 Tailscale DERP,当时是为了在外网访问 NAS。现在的需求变了:我需要在另一台电脑上访问家里 WSL 中的 GAG(Game Assets Generator)服务,传输图片、音频和模型资产。原来的 DERP 可以用,但延迟会从 45–53 ms 突然跳到 260 ms、287 ms,甚至 773 ms。

带宽不是完全不够。是抖。

先说结果

我没有删除原来的自建 DERP,而是在同一台阿里云 ECS 上增加了 Tailscale Peer Relay:

1
2
3
4
5
直连
↓ 失败
Peer Relay(UDP 40000)
↓ 不可用
自建 DERP(TCP 33445)

切换后,连续 10 次 tailscale ping 全部走 Peer Relay,延迟稳定在 38–48 ms;ECS 服务端能看到 2 个活跃 session。实际下载一个 4.81 MB 的 GAG 资产,三次用时 1.42–1.74 秒,大约 22–27 Mbps。

Peer Relay 不是新的 DERP 配置项,它是另一条 UDP 数据路径。

Peer Relay 和 DERP 到底是什么关系

Tailscale 官方现在把连接分成三类:直连、Peer Relay 中继和 DERP 中继。三种路径的业务数据都使用 WireGuard 端到端加密,差别主要是性能,不是“用了自建中继就变成明文”。

DERP 通过 HTTPS/TCP 提供连接协商和最终兜底,穿透性很强,但大文件传输和交互性服务可能受 TCP 队头阻塞、线路抖动等问题影响。Peer Relay 是同一个 tailnet 内的一台设备用 UDP 替其他节点转发已加密流量,通常更适合高吞吐、低抖动的场景。

但这里有一个容易说错的细节:Tailscale 建立连接时仍会用 DERP 交换连接信息,然后尝试升级为直连或 Peer Relay。 Peer Relay 的数据面不经过 DERP,但 DERP 仍有协商和兜底价值。

所以我的选择不是“用 Peer Relay 替换 DERP”,是两条路径并存。

我的部署结构

1
2
3
4
5
6
7
8
9
10
11
外部笔记本

│ Tailscale / WireGuard

阿里云 ECS
├─ Peer Relay: UDP 40000
└─ Custom DERP: TCP 33445 + STUN UDP 3478


家中 WSL
└─ GAG HTTPS / MCP 服务

ECS 入站只保留三个与 Tailscale 中继相关的端口:

  1. 40000/UDP:Peer Relay。
  2. 33445/TCP:自建 DERP。
  3. 3478/UDP:自建 DERP 的 STUN。

SSH 通过 Tailscale SSH 进入,不需要向公网开放 22/TCP。80、443 也不是这套结构的必需入站端口。

在 ECS 上启动 Peer Relay

Peer Relay 内置在 tailscaled 里,不需要安装另一个 relay daemon。服务端和使用 Peer Relay 的节点都需要 Tailscale 1.86 或更高版本。

先安装 Tailscale,加入自己的 tailnet:

1
2
3
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
sudo systemctl enable --now tailscaled

再把 ECS 设为 Peer Relay:

1
2
3
sudo tailscale set \
--relay-server-port=40000 \
--relay-server-static-endpoints="<ECS_PUBLIC_IP>:40000"

我的 ECS 有固定公网 IPv4,所以显式声明 static endpoint。阿里云安全组同时需要允许:

1
2
3
4
Protocol: UDP
Port: 40000/40000
Source: 0.0.0.0/0
Direction: Inbound

0.0.0.0/0 看上去很宽,但 Peer Relay 不是一个任意公网用户都能调用的通用 UDP 代理。它只为同一 tailnet 且获得 grant 授权的节点分配中继绑定,转发的也是端到端加密数据。

Access Controls 里的 grant 才是真正的开关

我一开始已经在 ECS 上看到 UDP 40000 监听,从外部发 UDP 数据包,ECS 也确实抓到了。但客户端仍然走 DERP(MyDerps)

这是因为安全组只解决“包能不能到 ECS”,grant 才决定“这个节点有没有资格使用 Peer Relay”。

在 Tailscale Admin Console 的 Access Controls 中,可以在旧的 ACLs 之外新增一个顶层 grants 字段:

1
2
3
4
5
6
7
8
9
"grants": [
{
"src": ["<GAG_WSL_TAILSCALE_IP>"],
"dst": ["<ECS_TAILSCALE_IP>"],
"app": {
"tailscale.com/cap/relay": []
}
}
]

这里最反直觉的是 src

src 不是“谁发起了访问”,是“哪些稳定资源允许别人通过这个 Peer Relay 访问”。

在我的场景里,src 是家中运行 GAG 的 WSL,dst 是运行 Peer Relay 的 ECS。外部笔记本不需要填进 src,除非我还需要从其他设备反向访问这台笔记本。

我最后使用了 Tailscale IP,因为当时的策略编辑器没有接受我直接填入的 MagicDNS 短名。如果要增强可读性,可以用 policy 中的 Hosts 为 IP 定义显式别名。

不建议为了省事写:

1
"src": ["*"]

官方文档也明确警告过宽的 src 可能让不必要的设备尝试使用 Peer Relay,反而增加绕路和流量。我只把 NAS、WSL、家庭服务器这类“稳定位置且需要被访问”的设备放进去。

怎么确认真的走了 Peer Relay

不能只看端口有没有监听。我现在用三层验收。

1. 客户端是否收到 Relay 候选

1
tailscale debug peer-relay-servers

未授权时我看到的是:

1
[]

grant 保存生效后,列表中出现 ECS 的 Tailscale IP。

2. 实际路径是否从 DERP 切换

1
tailscale ping --c 10 <PROTECTED_DEVICE>

成功时的关键输出是:

1
pong from <device> via peer-relay(<ECS_PUBLIC_IP>:40000:vni:1) in 41ms

如果显示:

1
via DERP(<region>)

说明还在走 DERP。direct connection not established 不代表 Peer Relay 失败,它只表示没能升级成直连;只要前面显示 peer-relay(...),Peer Relay 就已经承载这条连接。

3. ECS 是否真的在转发

1
sudo tailscale debug peer-relay-sessions

我的验收结果是:

1
2
Server port: 40000
Sessions count: 2

这三层分别回答三个问题:控制面是否授权,客户端是否选中,服务端是否转发。三个都对,才算真的部署完成。

这次遇到的两个假象

端口通了,不等于 Peer Relay 生效

我曾经在 ECS 上用 tcpdump 抓到外部主机发到 UDP 40000 的数据包,但 peer-relay-servers 仍然是空数组,服务端 session 也是 0。原因不在阿里云安全组,在 Access Controls 还没有 grant。

健康检查很快,不等于真实资产传输很稳

GAG 的 /health 只有很小的响应,它可以证明服务存活,不能代表几 MB 的图片或模型传输不抖。所以我另外用带签名的真实资产 URL 做了三次下载测试。

可观测性不是一个 ping。是控制面、路径、服务端 session 和业务流量四层证据。

BBR + fq 要不要开

我最后在 ECS 上启用了 BBR + fq:

1
2
3
4
5
6
7
8
sudo modprobe tcp_bbr

sudo tee /etc/sysctl.d/99-bbr.conf >/dev/null <<'EOF'
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
EOF

sudo sysctl -p /etc/sysctl.d/99-bbr.conf

但要说清楚:BBR 是 TCP 拥塞控制,它主要影响原来的 TCP DERP,不是 Peer Relay 生效的必要条件。Peer Relay 走 UDP 40000,真正决定它能否工作的是 Tailscale 版本、UDP 可达性和 grant。

要不要删掉自建 DERP

我的结论是:暂时不删。

Peer Relay 的数据传输不依赖自建 DERP,但酒店、校园网、公司网可能阻断陌生 UDP 端口,而 HTTPS/TCP 形式的 DERP 穿透性更强。我的 tailnet policy 还设置了 OmitDefaultRegions: true,如果再关闭自建 DERP,Peer Relay 不可用时就失去了最后兜底。

所以现在这台 ECS 上有两个职责:

  1. tailscaled 提供 UDP Peer Relay,承担日常高性能中继。
  2. derper 提供 TCP DERP,承担最终兜底。

这不是重复建设,是两种不同失败条件的保险。

如果之后换 ECS

我把部署动作收进了一个独立的网络配置目录,里面包含:

  1. Peer Relay 部署脚本。
  2. 验收脚本。
  3. Access Controls grant 模板。
  4. BBR + fq 持久化配置。
  5. 迁移和回滚说明。

新 ECS 的迁移顺序应该是:新旧节点并行,先验证新 Peer Relay,再迁移 DERP,最后释放旧机。不要把“换服务器”变成一次不可回滚的网络切换。

参考

  1. Tailscale Peer Relays
  2. Tailscale connection types
  3. DERP servers
  4. 2024 年我搭建自建 DERP 的记录