在没有域名的 NAT 主机上,部署 Tailscale 中继节点(DERPER)

在没有域名的 NAT 主机上,部署 Tailscale 中继节点(DERPER)

GT610 Lv3

📌 背景

我一直使用 Tailscale 组网,Tailscale 在校园网环境下表现几乎等于局域网,但是一离开校园网环境就很难连接了。这是因为在无法直连打通时,Tailscale 会自动选择 DERPER 节点进行中继。

什么是 DERPER?

DERP(Distributed End Reversal Proxy)是 Tailscale 实现的一种中继协议,用于在无法直接建立 P2P 连接时通过中继服务器进行通信。

Tailscale 官方提供的中继节点均位于大陆以外,加上国内网络环境错综复杂,这就导致国内访问官方中继延迟非常高,速度慢,甚至无法连接。

官方中继节点惨不忍睹的延迟
官方中继节点惨不忍睹的延迟

DERPER 也可以自建。自建 DERPER 按理来说需要公网 IP、域名和 TLS 证书。

正当我考虑自建的时候,有个朋友问我要不要服务器,4 核 4 GB 的宿迁 NAT 主机只要 20 元/月,上行 50 Mbps,下行 30 Mbps,不限流量,简直是先天中继圣体,价格也远低于市面上绝大多数厂商。于是二话不说买了两个月。实际用下来确实效果很好,感觉还是非常值的,但是我没拿到广告费,所以这里就不打广告了

但现在的问题是:

  • VPS 没有公网 IP,仅支持 NAT 映射端口到公网 IP 的特定端口上。
  • 服务商提供的公网域名没有备案,无法通过域名访问 HTTP 内容,但是可以通过公网 IP 地址访问。
  • 由于 NAT 映射,我也无法绑定自己的域名到 DERPER 上。

这个时候,我们就可以使用 IP Derper 来实现基于 IP 地址的中继服务。该方案不需要域名,也不需要主机拥有公网 IP,只需要确保 DERPER 的两个端口能够通过公网访问即可。

🌐 环境要求

组件 要求 我的方案
系统 Linux Debian 12
硬件 最低 1 核 512 MB 4 核 4 GB
软件 Docker / Podman 容器 Podman
网络 公网或支持 TCP 和 UDP 端口映射,上下行速率不能太低 端口映射,上行 50Mbps,下行 30Mbps

🛠️ 准备工作

在 NAT 环境下部署时,需要先确保以下几点:

  • 服务器提供商允许你映射主机内的任意 TCP 和 UDP 端口
  • 需要映射 2 个端口,一个 TCP + UDP,一个 UDP。
  • 服务器提供商对映射的端口没有限制

安装容器运行时

如果你尚未安装容器运行时,请先安装。Docker 或 Podman 均可。

Docker

输入以下命令安装 Docker 和 Docker Compose:

1
2
3
4
5
6
# 安装 Docker
sudo apt update && sudo apt install docker.io -y

# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Podman

输入以下命令安装 Podman:

1
sudo apt update && sudo apt install podman podman-compose -y

📦 使用 Docker Compose 部署 DERPER

创建容器

这里推荐使用 Docker Compose / Podman Compose 来进行部署。这里我使用的是一个社区维护的镜像:ghcr.nju.edu.cn/yangchuansheng/ip_derper:latest

以下为我的 YAML 配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
services:
derper:
image: ghcr.nju.edu.cn/yangchuansheng/ip_derper:latest
container_name: derper
restart: unless-stopped
ports:
- "50443:443"
- "53478:3478/udp"
environment:
- DERP_ADDR=:443
- DERP_CERTS=/app/certs
- DERP_VERIFY_CLIENTS=true

解释

  1. 容器端口映射 ports
主机端口 容器端口 类型 协议 说明
50443 443 DERPER 工作端口 TCP + UDP 你可以把主机端口 50443 改成其他的。
53478 3478 STUN 工作端口 UDP 你可以把主机端口 53478 改成其他的,但是协议必须是 UDP
  1. 环境变量 environment
环境变量 解释
DERP_ADDR :443 DERPER 工作端口,无特殊情况不要修改。若修改为其他端口,则在容器的 DERPER 工作端口映射处,修改容器端口 443 为对应端口。
DERP_CERTS /app/certs 证书目录,不要修改
DERP_VERIFY_CLIENTS 根据自身需求,建议为 true 是否验证客户端,true 为“是”。如果开启验证,则该节点只有你自己可用,否则任何知道节点的人都可以使用。客户端验证需要将服务器加入自己的 Tailnet。

若不开启验证,则任何知道你的节点 IP 地址和端口的人都可以使用你的节点,从而导致额外的流量

除非你的中继节点需要给他人使用,请将 DERP_VERIFY_CLIENTS 设置为 true。如果你的节点是共用的,请确保你信任和你共用节点的人之后,再将其改成 false

如果你开启了客户端验证,也就是将 DERP_VERIFY_CLIENTS 设置为 true,请在创建容器之前,将服务器添加到你的 Tailnet 网络中。

将上述配置文件代码复制下来,修改好后保存到服务器上,并运行以下命令:

Docker

1
docker-compose -f 配置文件名 up -d

Podman

1
podman-compose -f 配置文件名 up -d

验证服务是否正常运行

1
docker logs -f derper

如果看到如下输出,则表示服务已经正常运行:

1
2
2025/07/13 15:22:16 STUN server listening on [::]:3478
2025/07/13 15:22:16 derper: serving on :443 with TLS

你可能会看到其他错误,比如 No mesh key configured忽略它们,只要有上述两行输出就是正常的。

验证容器端口映射是否正常

在服务器上输入以下命令(请自行替换为对应的主机端口):

1
2
curl --insecure https://127.0.0.1:[DERPER 工作端口号]
nc -uvz 127.0.0.1 [STUN 工作端口号] # 需要安装 ncat 软件包

若返回结果分别为:

1
2
3
4
5
<html><body>
<h1>DERP</h1>
<p>
This is a <a href="https://tailscale.com/">Tailscale</a> DERP server.
...(以下省略)
1
2
3
4
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:53478.
Ncat: UDP packet sent successfully
Ncat: 1 bytes sent, 0 bytes received in 2.08 seconds.

则说明 DERPER 及主机端口映射正常,可以继续下面的配置。

🔗 映射主机端口到公网

主机的两个端口映射到公网:

类型 协议
DERPER 工作端口 TCP + UDP
STUN 工作端口 UDP

具体的端口号取决于你的配置文件,注意这里选择将上一步开放的主机端口映射出去,而不是容器端口

比如你上一步将 DERPER 工作端口映射到主机的 50443 端口,也就是 50443:443,那么你应该50443 映射到公网,而不是 443

STUN 端口也是一样的,比如你上一步映射到主机的端口为 53478 端口,也就是 53478:3478/udp,那么你应该53478 映射到公网,而不是 3478

验证是否可以通过公网访问 DERPER

任选一个能访问互联网的设备,输入以下命令(请自行替换为对应的公网端口):

1
2
curl --insecure https://[公网 IP 地址]:[DERPER 工作端口号]
nc -uvz [公网 IP 地址] [STUN 工作端口号] # 需要安装 ncat 软件包

然后通过浏览器访问 https://[公网 IP 地址]:[DERPER 工作端口号]

若返回结果分别为:

1
2
3
4
5
<html><body>
<h1>DERP</h1>
<p>
This is a <a href="https://tailscale.com/">Tailscale</a> DERP server.
...(以下省略)
1
2
3
4
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Connected to [公网 IP 地址]:[公网端口号].
Ncat: UDP packet sent successfully
Ncat: 1 bytes sent, 0 bytes received in 2.08 seconds.

且浏览器能够显示网页:

DERPER 网页界面
DERPER 网页界面

恭喜你,DERPER 搭建成功,可以配置客户端连接了。

浏览器显示“HTTPS 不安全”为正常现象,这是因为我们使用的是自签名证书,浏览器无法验证。

🧑‍💻 配置 Tailscale 客户端使用该 DERPER

接下来你需要告诉 Tailscale 客户端使用你自建的 DERP 节点。

  1. 登录 Admin Console,选择 Access Controls - Edit File。

Access Control JSON 配置界面
Access Control JSON 配置界面

在最下面一行添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"derpMap": {
"OmitDefaultRegions": false,
"Regions": {
"901": {
"RegionID": 901,
"RegionCode": "", // 地区代码,自行填写,仅限小写字母
"RegionName": "", // 地区名称,自行填写
"Nodes": [
{
"Name": "", // DERPER 名称,自行填写
"RegionID": 901,
"DERPPort": 50443, // 填写公网映射出来的 DERPER 工作端口号
"STUNPort": 53478, // 填写公网映射出来的 STUN 服务端口号
"ipv4": "", // 填写公网 IPv4 地址
"InsecureForTests": true, // 必须为 true
},
],
},
},
},

然后自行补充空缺的部分,然后点击 Save。

大概应该这样子
大概应该这样子

🧐 验证中继节点是否工作

任意客户端的终端上执行以下命令:

1
tailscale netcheck

若能在 DERP Latency 中看到你的节点 RegionCode,则说明中继节点工作正常。

1
2
* DERP latency:
- suq: 19.8ms (Suqian)

一般来说,国内中继节点的延迟是远小于官方的海外中继节点的延迟的。所以,下次连接网内其他设备的时候,Tailscale 一般都会自动选择自建节点作为中转。这一点也可以从 Nearest DERP 看出来:

1
* Nearest DERP: Suqian

你也可以通过执行 tailscale ping 任意设备 命令,或者在 Android 客户端上 Ping 其他设备,来查看自建节点的效果。

中继连接 300 公里外的 NAT4 设备,延迟还是可以接受的
中继连接 300 公里外的 NAT4 设备,延迟还是可以接受的

📝 写在最后

Tailscale 也是为数不多的在国内成功率较高的组网软件了,相比其他组网软件,我很喜欢 Tailscale 的 full mesh 特性,以及非常高的安全性。然而,我们的网络环境日益复杂,即使是 Tailscale,也不能保证任何环境下都可以穿透成功。中继节点虽然能有效解决穿透失败问题,但是也并不是 Tailscale 的最优先策略,毕竟什么流量都要走中继的话,整个组网网络的带宽就会被中继的带宽给“卡脖子”。

希望国内的互联网发展越来越好,也希望这篇文章能对你有所帮助。如果你有任何问题或者更好的建议,欢迎留言讨论!

  • 标题: 在没有域名的 NAT 主机上,部署 Tailscale 中继节点(DERPER)
  • 作者: GT610
  • 创建于 : 2025-07-13 17:26:26
  • 更新于 : 2025-09-23 15:09:18
  • 链接: https://gt-610.dpdns.org/2025/07/13/docker-ip-derper/
  • 版权声明: 本文章采用 CC BY 4.0 进行许可。
评论