Sleepstars 的记录室

Sleepstars 的记录室

Tailscale 替代 DERP:Peer Relays 更加简单的中继方法(支持分流)

2025-10-30

1. 前言

之前我写了一个免证书部署 Tailscale Derp 的教程,只需要一个单 IP 的机器即可完成 Derp 的部署。如果你不知道什么是 Derp ,可以回去查看 免备案部署Derp教程

而在 2025 年 10 月 29 日,Tailscale 发了一篇全新的 Blog ,向我们介绍了新功能: Peer RelaysTailscale Peer Relays 允许你在网络条件不佳(如严格的 NAT 环境 )导致无法建立 P2P 连接时,使用你在 Tailscale 网络中的设备(称为 tailnet)作为高吞吐量的中继服务器。

通常情况下,Tailscale 依赖其全球分布的 DERP 服务器在无法建立设备之间的直接连接时中继流量。虽然 DERP 服务器在中继流量方面效果良好,但可能会引入额外的延迟,尤其是在高吞吐量的应用场景中。当你将某个设备配置为端点中继时,同一 tailnet 中的其他设备可以在无法建立直接连接时,使用它来中继客户端到客户端的流量。Tailscale 会优先尝试使用任何可用的端点中继,然后才会回退到 DERP 服务器。

除此之外,Derp 服务器的配置难度比较高,相较之下 Peer Relays 就要简单多了,只需要在中继流量的机器上开放一个 UDP 端口,在 Tailscale 中配置相关 ACL Rules 就可以完成配置,而且不需要担心修改版 Derp 带来的安全问题(例如被扫爆、需要暴露一个 http 服务)。

2. 简单配置流程

2.1 前提条件

准备好一个 Tailnet:第三方的 Headscale 控制平面和 官方的 Tailscale 控制平面均可。

确保所有需要使用到 Relay Peers 的设备均为 Tailscale 版本 1.86 或更高版本。可以使用除 iOS 或 Apple TV 之外的任何操作系统。

作为中级服务器,至少有一个可配置的 UDP 端口,用于对等中继流量。该端口必须对 tailnet 中的其他设备可访问。同时具有公网IP,足够的网络带宽和低延迟,以有效转发其他设备的流量。

2.2 中继服务器配置

在所有需要用以中继的服务器上使用命令配置 Relay peers

tailscale set --relay-server-port=40000

该指令不会有反馈。40000 的端口号可以修改为任意开放 UDP 端口。在国内建议使用 20000 以上高位端口,避免封锁。确保 UDP 不会被 QoS。

2.3 ACL tag 分配

在这里我使用图形化 Access controls 进行机器的 Tag 分配。首先进入 https://login.tailscale.com/admin/acls/visual/tags 页面,添加如下的 Tag:

Tag 配置页面

图 Tag 配置页面

此处选择 “Create Tag”

配置所有需要的设备组

图 配置所有需要的设备组

在 JSON 中直接配置则为

	"tagOwners": {
		// 用于中继的设备组
		"tag:srv": ["autogroup:member"],
		// 中继 Device
		"tag:relay": ["autogroup:member"],
	},

你可以不用分配这么复杂的规则,对于简单的需求来说,新建 "srv" 和 "relay" 两个组别即可。

接着使用命令行或者图形化界面给所有需要的设备加入中继

在设备上用 CLI 直接打标签:

# 被中继机
sudo tailscale login --advertise-tags=tag:srv
# 或者
sudo tailscale up --advertise-tags=tag:srv

# 中继服务器
sudo tailscale login --advertise-tags=tag:relay
# 或者
sudo tailscale up --advertise-tags=tag:relay

或者在图形化界面中配置 ACL:

配置 ACL tags

图 配置 ACL tags

2.4 ACL grant 规则分配

进入 https://login.tailscale.com/admin/acls/file 选择 JSON Editor:

图 Grant 分流配置

在 grants 中添加或者新增 grants,注意 JSON 层级是否正确:

	"grants": [
		/* ① srv 允许用 celay 作为中继 */
		{
			"src": ["tag:srv"],
			"dst": ["tag:relay"],
			"app": {"tailscale.com/cap/relay": []},
		},
		/* ② 访问中继节点本身(否则用不上中继) */
		{
			"src": ["tag:srv"],
			"dst": ["tag:relay"],
			"ip":  ["*"],
		}
	],

说明:grants 里的 app: {"tailscale.com/cap/relay": []} 是“允许把 dst 当中继”,ip:["*"] 是“允许去连中继节点本身(含其 UDP 端口)”。两者都需要。

2.5 功能检查

使用 tailscale ping 检查即可

tailscale ping <替换为你的设备 Tailnet IP 或者 Hostname>

peer relay 配置检查

图 peer relay 配置检查

你也可以使用 tailscale status 进行检查,有看到 peer-relay 字样即意味着已经正确连接到了中继设备上了。

图 tailscale status 配置检查

3. 进阶流程(路由分流)

3.1 Tag 分配

	"tagOwners": {
		// 中国地区所有 Device
		"tag:cn-srv": ["autogroup:member"],

		// 国际 Device
		"tag:global-srv": ["autogroup:member"],

		// 中国地区稳定中继 Device
		"tag:cn-relay": ["autogroup:member"],

		// 国际优化中继
		"tag:pre-global-relay": ["autogroup:member"],
	},

3.1 ACL grant 规则分配

配置了四个分流 tag 后,那么可以直接使用我的配置方案:

	"grants": [
		/* ① cn-srv 允许用 cn-relay 作为中继(cn→cn 的第二优先) */
		{
			"src": ["tag:cn-srv"],
			"dst": ["tag:cn-relay"],
			"app": {"tailscale.com/cap/relay": []},
		},
		/* ② 访问中继节点本身(否则用不上中继) */
		{
			"src": ["tag:cn-srv"],
			"dst": ["tag:cn-relay"],
			"ip":  ["*"],
		},

		/* ③ cn-srv 与 global-srv 互访时,仅允许用 pre-global-relay */
		{
			"src": ["tag:cn-srv", "tag:global-srv"],
			"dst": ["tag:pre-global-relay"],
			"app": {"tailscale.com/cap/relay": []},
		},
		/* ④ 允许双方都能连到 pre-global-relay 节点本身 */
		{
			"src": ["tag:cn-srv", "tag:global-srv"],
			"dst": ["tag:pre-global-relay"],
			"ip":  ["*"],
		},

		/* ⑤ 不为 global-srv→global-srv 授予任何 relay(自然是 P2P→DERP) */
	],

图 Grant 分流配置

  • cn→cn:允许使用 cn-relay(直连失败时才会走它;否则 P2P)。

  • cn↔global:允许使用 pre-global-relay,并且不授予其它 relay,避免误选。

  • global→global不授予任何 relay,这样就是 P2P;直连失败才会走 DERP。