EasyTier 组网小记
将异地组网从 WireGuard 迁移到 EasyTier。
前言
在很长一段时间里,我一直使用WireGuard来进行异地组网,架构如下:
从上图中可以看出,几处节点是以驻地作为核心进行组网的,而除了阿里云之外,其他几处节点都没有公网 IPv4 地址,只有公网 IPv6 地址。
虽然驻地为 IPv6 地址配置了DDNS,但由于 DNS 缓存和 Mikrotik 路由器的缺陷,导致驻地 IPv6 地址更新后,其他节点并不能第一时间建立连接,甚至有时候需要手动启停wg接口才能重新连接到核心节点。
再加上wg作为点对点协议,不能实现P2P通信,没有直连的节点都需要通过核心节点进行中转,我确定换掉目前的这一套方案,调研一番之后,EasyTier走入了我的视线,它完美地符合了我的需求:
- 完全开源,可以自建私有公网节点
- 通过公网节点发现其他节点后,直接进行 P2P 通信
- 自动发布路由到虚拟网络中
- 不支持
EasyTier的设备可以通过WireGuard作为客户端接入 - IP 变化后可以迅速通过公网节点再次和其他节点建立连接
规划
开始迁移之前,先梳理一下思路,各个节点的设备情况如下:
| 节点 | 网关设备 | EasyTier 支持情况 |
|---|---|---|
| 驻地 | Mikrotik RB4011 | 不支持,需要通过局域网其他设备作为节点 |
| 朋友 | Mikrotik CHR | 同上 |
| 老家 | OpenWRT | 支持 |
| 阿里云 | Debian | 支持 |
| 移动设备 | - | 支持,但我希望将 EasyTier 集成到 Mihomo 中 |
阿里云作为唯一拥有公网 IPv4 且 SLA 极高的节点,理所当然的成为了公网节点。
对于不支持EasyTier的Mikrotik设备,可以在局域网中其他 Linux 设备上运行EasyTier;但局域网中其他设备并不能通过该节点访问其他节点,虽然可以通过在网关上增加指向该节点的静态路由,但每次EasyTier网络路由信息变化时,都需要手动更新静态路由。
对于这种情况,可以在EasyTier节点上运行bird,通过BGP协议将接收到的EasyTier路由信息传递给Mikrotik网关,由此就可以实现路由信息动态更新。
我希望通过Mihomo通过WireGuard出站功能接入EasyTier虚拟网络,虽然失去了P2P能力,但方便管理。因此,让移动设备作为WireGuard客户端接入即可。
配置
我部署EasyTier时,最新版本是2.6.4,这个版本存在一个问题:节点开启 Secure Mode、指定远端公钥、且使用 toml 配置文件的情况下,无法连接到远端节点,会一直出现如下错误,关闭 Secure Mode 后可以正常连接:
easytier | 2026-10-14T18:01:52.646830192+08:00 INFO CORE::INSTANCE::CONNECTION: [61f29995-da62-471d-9255-d430c66269eb] connection error local="tcp://0.0.0.0:52900" remote="tcp://x.x.x.x:29454" err="wait resp error: conn closed during wait handshake response"Github Issues 有人反馈了类似的问题:https://github.com/EasyTier/EasyTier/issues/2267
还好项目当时已经预发布了2.7.0,我切换到该版本后上述问题就不复存在了。
阿里云/公网节点
公网节点我是用 Docker 部署的,Docker Compose 配置文件如下:
services:
easytier:
image: m.daocloud.io/docker.io/easytier/easytier:v2.7.0
hostname: easytier
container_name: easytier
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
- NET_RAW
environment:
- TZ=Asia/Shanghai
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- /etc/machine-id:/etc/machine-id:ro
- ./conf:/config
command: >
-c /config/easytier.tomlEasyTier 配置文件如下:
hostname = "aliyun"
ipv4 = "192.168.252.1/24" # 公网节点在虚拟网络中的 IP
dhcp = false
listeners = [
"udp://0.0.0.0:52900",
"tcp://0.0.0.0:52901",
"wg://0.0.0.0:52902",
] # 支持的协议和端口
[network_identity]
network_name = "homecloud" # 虚拟网络名称,随便起
network_secret = "<PRIVATE>" # 网络密钥,可以手写也可以用 OpenSSL 之类的工具生成
credential_file = "/config/easytier_credential.json"
[secure_mode]
enabled = true
local_private_key = "<PRIVATE>" # 用 easytier-core 生成,注意保存对应的公钥,其他客户端要用到
[vpn_portal_config] # 供 WireGuard 客户端接入
enabled = true
wireguard_listen = "0.0.0.0:52913"
wireguard_private_key = "<PRIVATE>" # WireGuard 私钥,使用 wg cli 生成
[[vpn_portal_config.clients]] # 对应的 WireGuard 客户端,可以写多个
name = "iPhone"
virtual_ip = "192.168.252.100/24"
[flags] # 相关 flag,可以去文档中查看更相信的介绍
latency_first = true
proxy_forward_by_system = true
private_mode = true
need_p2p = true配置完成后,使用 docker compose up -d 启动项目,然后可以使用 docker compose logs -f 查看日志,其他节点接入时会有相关日志输出。
老家/OpenWRT
首先,在路由器终端中输入 uname -r 确定架构,然后 Release 去下载对应的发布包,然后将包内的 easytier-cli 和 easytier-core 上传到路由器的 /usr/bin 目录下,并赋予执行权限。
接下来需要生成 EasyTier 配置文件和 procd 服务,以便由 OpenWrt 管理相关进程。
EasyTier 配置文件路径为 /etc/easytier/config.toml,配置内容如下:
hostname = "laojia"
ipv4 = "192.168.252.3/24"
ipv6_public_addr_auto = true # 启用 IPv6
dhcp = false
listeners = [
"udp://0.0.0.0:52900",
"tcp://0.0.0.0:52901",
"wg://0.0.0.0:52902",
]
[network_identity]
network_name = "homecloud"
network_secret = "<PRIVATE>"
[secure_mode]
enabled = true
[[proxy_network]]
cidr = "10.3.0.0/24" # 需要被发布到虚拟网络中的 OpenWrt LAN 地址段
[[peer]]
uri = "udp://ali.example.com:52900" # 公网节点地址和协议
peer_public_key = "<PRIVATE>" # 公网节点公钥
[flags]
latency_first = true
proxy_forward_by_system = true
private_mode = true
need_p2p = true然后需要创建服务脚本 /etc/init.d/easytier:
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=95
STOP=10
PROG=/usr/bin/easytier-core
CONF=/etc/easytier/config.toml
start_service() {
[ -f "$CONF" ] || return 1
[ -f "$PROG" ] || return 1
procd_open_instance
procd_set_param command "$PROG" -c "$CONF"
procd_set_param respawn 3600 5 0 # 异常退出时自动拉起
procd_set_param stdout 1 # 日志输出至 logread
procd_set_param stderr 1
procd_close_instance
}赋予权限并启用开机启动:
chmod +x /etc/init.d/easytier
/etc/init.d/easytier enable
/etc/init.d/easytier start检查运行状态:
/etc/init.d/easytier status
ip addr show dev tun0
easytier-cli peer到了这里,EasyTier 已经可以正常运行,但是还需要配置防火墙相关:
- 进入 Luci 页面,网络/接口/添加新接口
- 名称填写 easytier,协议选择不配置协议(Unmanaged),设备选择 tun0 或者对应的 easytier 设备
- 在接口的防火墙设置中,选择已有的 lan 区域
现在,可以在公网节点上 Ping OpenWrt 的虚拟节点 IP 和 LAN IP 了。
驻地/Mikrotik
驻地网络网关路由器是 Mikrotik,不支持 EasyTier ,因此只能在局域网的其他 Linux 设备上安装 EasyTier ,然后通过 BGP 将相关路由宣告给 Mikrotik。
我的另一台 Linux 设备是 debian,因此可以用官网的一键安装脚本来安装,详见:https://easytier.cn/guide/installation.html
安装完成后,相关程序会安装到 /opt/easytier 目录下,配置文件位于 /opt/easytier/config/default.conf ,直接修改该配置文件即可:
hostname = "home"
ipv4 = "192.168.252.2/24"
ipv6_public_addr_auto = true
dhcp = false
listeners = [
"udp://0.0.0.0:52900",
"tcp://0.0.0.0:52901",
"wg://0.0.0.0:52902"
]
[network_identity]
network_name = "homecloud"
network_secret = "<PRIVATE>"
[secure_mode]
enabled = true
[[proxy_network]] # 需要被发布到虚拟网络中的 LAN 地址段,可以发布多个
cidr = "192.168.233.0/24"
[[peer]]
uri = "udp://ali.example.com:52900" # 公网节点地址和协议
peer_public_key = "<PRIVATE>" # 公网节点公钥
[flags]
latency_first = true
proxy_forward_by_system = true
private_mode = true
need_p2p = true配置完成后,可以通过 systemd 进行管理:
systemctl enable easytier@default # 开机自启
systemctl start easytier@default # 立即启动此时,在该 Debian 设备上已经能正常访问到其他 EasyTier 节点,也成功建立起了 P2P 连接。
但现在,局域网其他设备还无法通过该节点访问虚拟网络,因此需要用 BGP 将路由发布到网关设备上。
这个需求可以使用 bird2 来实现,直接 apt install bird2 即可。安装完成后,修改 /etc/bird/bird.conf 配置文件即可。
需要注意的是,我的这个设备安装的是 Debian 12 ,因此安装的 bird2 不是最新版本,语法和 Debian 13 上的 bird2 存在些许差异,可以让 AI 协助修改。
router id 192.168.233.4; # 使用 Debian 设备局域网 IP 作为 Router ID
protocol device {
}
protocol direct {
ipv4 {
import filter {
if net = 192.168.252.0/24 then accept; # 直连路由中,仅发布 EasyTier 路由
reject;
};
};
interface "tun0";
}
# 从 Linux 内核读取 EasyTier 路由
protocol kernel easytier_kernel {
learn yes;
scan time 10;
ipv4 {
import filter {
if defined(krt_metric) then {
if krt_metric = 65535 then accept;
# 匹配当前 EasyTier 其他节点宣告的路由,这里要根据你的设备 ip r 的输出来修改
}
reject;
};
export none;
};
}
# BGP 配置
protocol bgp routeros {
local 192.168.233.4 as 65002; # Debian 的 RouterID 和 AS 号
neighbor 192.168.233.233 as 65001; # Mikrotik 的 RouterID 和 AS 号
direct;
ipv4 {
import none;
export all;
next hop self;
};
}接下来,执行以下操作:
# 语法检查
bird -p -c /etc/bird/bird.conf
# 启动 bird
systemctl enable --now bird
systemctl restart bird
# 查看路由,预期中在这里能看到 easytier 其他节点发布的路由
birdc show route all接下来需要配置 Mikrotik,先创建过滤规则,只接受常见的内网地址,并拒绝本地 LAN 段,以免接收到错误路由时造成路由冲突:
/routing filter rule
add chain=et-bgp-in rule="if (dst == 192.168.233.0/24) {reject}"
add chain=et-bgp-in rule="if (dst in 10.0.0.0/8) {accept}"
add chain=et-bgp-in rule="if (dst in 172.16.0.0/12) {accept}"
add chain=et-bgp-in rule="if (dst in 192.168.0.0/16) {accept}"创建一条禁止 Mikrotik 向 Debian 发布路由的规则:
/routing filter rule
add chain=et-bgp-out rule="reject"创建 BGP 实例,RouterID 使用网关地址即可,AS 和之前 bird 中的配置一致:
/routing bgp instance
add name=easytier as=65001 router-id=192.168.233.233添加 BGP 邻居,remote.address 使用 Debian 的 LAN 地址,AS 号 和之前 bird 中的配置一致:
/routing bgp connection
add name=easytier-debian \
instance=easytier \
local.role=ebgp \
local.address=192.168.233.233 \
remote.address=192.168.233.4 \
remote.as=65002 \
input.filter=et-bgp-in \
output.filter-chain=et-bgp-out接下来,在 RouterOS 路由表中就能看到 Debian 宣告的 EasyTier 路由表了:
/ip/route/print其他
朋友家的网络结构和驻地网结构是一样的,因此照猫画老虎即可;而移动设备这边,按照常规的 WireGuard 配置编写配置文件即可,需要在 AllowedIPs 中补齐 EasyTier 虚拟网络其他节点发布的网段,否则无法访问对应的路由。
最终的网络结构如下: