从自建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 | 直连 |
切换后,连续 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 | 外部笔记本 |
ECS 入站只保留三个与 Tailscale 中继相关的端口:
40000/UDP:Peer Relay。33445/TCP:自建 DERP。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 | curl -fsSL https://tailscale.com/install.sh | sh |
再把 ECS 设为 Peer Relay:
1 | sudo tailscale set \ |
我的 ECS 有固定公网 IPv4,所以显式声明 static endpoint。阿里云安全组同时需要允许:
1 | Protocol: UDP |
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 | "grants": [ |
这里最反直觉的是 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 | Server port: 40000 |
这三层分别回答三个问题:控制面是否授权,客户端是否选中,服务端是否转发。三个都对,才算真的部署完成。
这次遇到的两个假象
端口通了,不等于 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 | sudo modprobe tcp_bbr |
但要说清楚: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 上有两个职责:
tailscaled提供 UDP Peer Relay,承担日常高性能中继。derper提供 TCP DERP,承担最终兜底。
这不是重复建设,是两种不同失败条件的保险。
如果之后换 ECS
我把部署动作收进了一个独立的网络配置目录,里面包含:
- Peer Relay 部署脚本。
- 验收脚本。
- Access Controls grant 模板。
- BBR + fq 持久化配置。
- 迁移和回滚说明。
新 ECS 的迁移顺序应该是:新旧节点并行,先验证新 Peer Relay,再迁移 DERP,最后释放旧机。不要把“换服务器”变成一次不可回滚的网络切换。