Info

本文首发自我的博客:阿瑞纳与阿巴拉契亚的博客,后续文章相关更新也将在博客第一时间发布。

最近在家里搭建了一个Minecraft服务器和朋友联机,朋友在学校校园网的网络质量很差,特别是直连家用宽带时有严重的QoS或丢包问题。早期的解决方法是我用natter给Minecraft服务器开放端口(我家里是NAT1环境),朋友先连加速器(如网易UU加速器或类似的国内联机加速器),然后再连我用natter暴露的端口。这种方案没有问题,只是我一直以来都对将自己的服务暴露到公网这件事情比较抵触,这很大程度上是因为我没有精力检查和维护防火墙等安全设置。因此,我过去绝大多数时间使用的是Tailscale方案。但是Tailscale方案搭建国内的DERP转发服务器略显麻烦(这是因为默认的DERP服务器需要域名和HTTPS以及Web访问,而国内服务器在这类功能上需要备案;此外,P2P方面如前文所提,在我朋友的环境中会导致严重的问题)。后来我冲浪时发现了EasyTier方案,其去中心化的设置使得无论是协调服务器还是中转服务器的设置都更加简单。因此,本文尝试利用EasyTier、natter以及SRV记录,实现去中心化的组网。

一些预备知识

在开始阐述我的实践之前,希望读者对以下概念有一些基本的了解:EasyTierNatterSRV记录NAT。如果读者已经对这些工具或概念有基本的了解,就可以选择性观看这个章节。

EasyTier

EasyTier根据其在官网的介绍,是一个由Rust和Tokio驱动的一个简单、安全、去中心化的异地组网方案。如果说Tailscale类似于传统tracker下的BT、EasyTier更像DHT技术下的BT。通过在配置文件中设置好网络名与密码和节点地址,也即是将配置分散地存储在每一个节点上。从而实现中心服务器的单一故障而带来的整个网络的崩溃。(笔者认为EasyTier和DHT技术在实际使用中都要面临在初次启动时如何发现节点的问题,能多大程度上解决这个问题决定了这个方案的去中心化程度,限于文章篇幅,具体观点先按下不表)。

不同的NAT类型

NAT是一种地址转换技术,根据外部主机发送数据到内部主机时受到的限制,可以分为NAT1、NAT2、NAT3、NAT4(外部主机受到的限制逐步增加)

  • NAT1:任意IP的外部主机可以使用任意端口向通过相对固定的公网IP与端口将数据发送到内部主机
  • NAT2:特定IP的外部主机可以使用任意端口向通过相对固定的公网IP与端口将数据发送到内部主机
  • NAT3:特定IP的外部主机可以使用特定端口向通过相对固定的的公网IP与端口将数据发送到内部主机
  • NAT4:内部主机无法获得相对固定的公网IP与端口供外部主机传入。

一般认为NAT1的可穿透性最好、NAT4的可穿透性最差,具体NAT组合的穿透性请读者自行学习。但笔者需要提醒的是,如今即使在NAT4-NAT4环境中,也由于端口分配的某种规律性而能被打洞成功,但打洞软件摸索规律的过程本身也可能导致运营商的QoS限制。

Natter

Natter以及Lucky之类的软件,都是通过STUN内网穿透技术,能够在NAT1网络下将内网主机端口映射到公网端口上,实现内网穿透。(关于STUN技术的原理请读者自行上网学习)。一般而言,Natter仅能在NAT1类型的内部主机使用。Natter在实际应用中每次穿透都会向上游、也就是宽带运营商方向申请一个新的端口,这就使得与家用宽带公网ip通过端口转发实现公网访问相比,Natter方案不仅仅公网ip可能是动态的、连公网端口都是动态的。

SRV记录

为了更方便用户访问Natter映射出来的端口,我们需要将这个动态的ip和端口固定下来。对于动态ip的固定方案在互联网上已经相当成熟了,即ddns。而对于端口的固定方案则会由于服务的类型而有所不同,目前主流的方案是Cloudflare的重定向(适用于https服务)以及SRV记录(适用于Minecraft、EasyTier以及其它适配SRV记录的软件)。

根据维基百科的介绍,SRV记录是域名系统中用于指定服务器提供服务的位置(如主机名和端口)数据,他还有实现负载均衡的作用,一条SRV记录由以下部分组成:

  • 服务:服务的符号名称。
  • 协议:服务的传输协议,通常为TCPUDP
  • 名称:此记录生效的所在域名,以半角逗号结尾。
  • TTL:标准DNS存活时间值。
  • 类别:标准DNS类别值(此值总为IN)。
  • 优先级:目标主机的优先级,值越小越优先。
  • 权重:相同优先度记录的相对权重,值越大越优先。
  • 端口:服务所在的TCP或UDP端口。
  • 主机:提供服务的规范主机名,以半角句号结尾。

方法:EasyTier、Natter、SRV

警告

在本文撰写时,最新版本(2.2.4)的EasyTier部分平台(已知有Windows)在处理SRV记录时会异常性的反复尝试向DNS请求,为了缓解这个问题,请使用最新的开发版本(已知在#910版本中该问题已经修复)

简要流程

  1. 设置EasyTier的监听器
  2. 将EasyTier的监听端口通过Natter映射到公网
  3. 利用脚本将Natter映射出来的公网地址绑定到SRV记录
  4. 设置将SRV记录加入EasyTier的对等节点

设置EasyTier的监听器

EasyTier的下载与安装教程请自行在官网学习,本文不提供教程。

在默认情况下,EasyTier会使用11010端口用作监听。你也可以自行设置一个监听端口,根据使用的软件不同,有不同的设置方式,以下介绍几种常用的方式。

命令行

命令行模式中配置后缀为-l, --listeners,在命令行将监听端口设为udp和tcp协议的11015端口的例子是:

sudo easytier-core -i 10.144.144.1 -l ["tcp://0.0.0.0:11015",  "udp://0.0.0.0:11015"]

图形界面GUI

在图形界面将监听端口设为udp和tcp协议的11015端口的例子是:

在监听地址中直接输入11015,能够自动联想

配置文件

一份将监听端口设为udp和tcp协议的11015端口的配置文件可以是(留意listeners,读者可以在EasyTier Dashboard方便地生成一份配置文件):

instance_name = "easytier"
instance_id = "4438348b-0db1-4692-aa83-ddbd6dfc411f"
dhcp = true
listeners = [
    "tcp://0.0.0.0:11015",
    "udp://0.0.0.0:11015",
]
rpc_portal = "0.0.0.0:0"

[network_identity]
network_name = "easytier"
network_secret = ""

[flags]

Natter映射以及绑定SRV记录

MikeWang000000/Natter仓库的natter-docker目录中,提供了各种Natter的实用脚本,其中同EasyTier一样可以利用SRV记录的软件是Minecraft,因而我们可以参考minecraft目录下的脚本cf-srv.py。并按照其介绍文件填写相关信息,但是务必注意的是,由于我们是给EasyTier使用的,因而在cf_srv_service一项,读者应当设为 “_easytier”。

设置好cf-srv.py文件后,读者可以使用docker-compose(minecraft目录下有提供,只要将minecraft-server部分删掉就好)

或者将仓库下下来,通过类似于以下代码的方式运行:

python3 natter.py -e /opt/cf-srv.py -p 11010 -r

NOTE

如果不能理解直接下载运行的方案或者出现了不能解决的错误,那就用docker-compose方案,那个方案上手难度低很多,本文不介绍docker-compose的使用方法

运行成功日志如下所示:

2025-05-11 07:51:08 [I] Natter v2.1.1

2025-05-11 07:51:17 [I] 

2025-05-11 07:51:17 [I] tcp://192.168.1.xxx:11010 <--socket--> tcp://192.168.1.xxx:39443 <--Natter--> tcp://www.xxx.yyy.zzz:23717

2025-05-11 07:51:17 [I] 

2025-05-11 07:51:17 [I] Calling script: /opt/cf-srv.py

Setting easytier.arenadruid.top SRV record to tcp port 23717...

2025-05-11 07:51:20 [I] LAN > 192.168.1.xxx:11010   [ OPEN ]

2025-05-11 07:51:20 [I] LAN > 192.168.1.xxx:39443   [ OPEN ]

2025-05-11 07:51:20 [I] LAN > www.xxx.yyy.zzz:23717    [ OPEN ]

2025-05-11 07:51:20 [I] WAN > www.xxx.yyy.zzz:23717    [ OPEN ]

2025-05-11 07:51:20 [I]

将SRV记录加入EasyTier的对等节点

对等节点的设置是为了让其它主机连上上文所用的主机,因此以下的配置应当在其它主机的EasyTier中配置的。其配置也可以通过图形界面GUI、命令行、配置文件配置。其中要注意的是:srv记录的uri应当写为srv://域名

命令行

命令行模式中配置后缀为-p, --peers [<PEERS>...],在命令行中将对等节点设为srv://easytier.test.top的例子是:

sudo easytier-core -d -p srv://easytier.test.top

图形界面GUI

在GUI中将对等节点设为srv://easytier.test.top

配置文件

一份将对等节点设为srv://easytier.test.top的配置文件可以是(留意[[peer]]一栏)

instance_name = "easytier"
instance_id = "4438348b-0db1-4692-aa83-ddbd6dfc411f"
dhcp = true
listeners = [
    "tcp://0.0.0.0:11015",
    "udp://0.0.0.0:11015",
]
rpc_portal = "0.0.0.0:0"

[network_identity]
network_name = "easytier"
network_secret = ""

[[peer]]
uri = "srv://easytier.test.top"

[flags]

结语

本文使用EasyTier、Natter和SRV记录,使得NAT1状态下节点也可以视同公网节点被发现,前文提到,EasyTier在实际使用中要面临在初次启动时如何发现节点的问题,能多大程度上解决这个问题决定了这个方案的去中心化程度。在仅使用一个官方服务器作为对等节点的情况下,如果官方服务器无法联通,那么EasyTier会由于无法发现第一个节点而导致无法发现所有的节点并最终导致整个网络完全失能,因此增加对等节点是提升网络稳健性的充分手段,而本文提到的方案将NAT1环境下的节点利用起来,能够有效增加EasyTier对等节点的库存,从而提高了EasyTier的去中心化程度和网络的稳健性。

本文的撰写中十分感谢,EasyTier支持Q群中网友的协助,正是网友帮我实现了这个方案中在对等节点配置SRV记录的“最后一步路”,此外网友们的热心帮助也让我能够更好地上手EasyTier这款软件。EasyTier是一款相当有前景的软件方案,其不区分服务器和客户端的设计,事实上使得中转服务器的搭建比TailScale、Zerotier等更加的简单,但是目前情况,这个软件也是一个缺乏安全性的例子。一个例子是非预想的公共服务器的会由于任一客户端的误设置纳入进网络当中:我的初始网络设置中并没有连上任一官方的公共服务器,但是我的朋友在加入我的网络时,没有删掉默认的官方公共服务器,从而导致最后公共服务器被意外地加入到我的网络之中,这个问题在Q群中也经常被讨论,目前的讨论的结果是:在要对外分享的情况下,最好通过Web统一管理。而目前EasyTier的作者也将ACL功能纳入未来更新的方向,最后,笔者希望这个软件能够越来越完善。

版权许可

本作品采用知识共享 署名 4.0 国际许可协议进行许可

CC BY 4.0