标准 Linux 启用 ZeroTier 局域网转发
参考文章
需要解决的问题
在使用非OpenWRT
这种路由器类型的Linux
发行版的时候,如果想要使用ZeroTier
自带的路由转发的功能,需要进行一系列的操作来启用内部的路由转发机制。
解决这个问题原本应该十分简单,只需要在sysctl
启用对应的forward
设置然后设置防火墙即可。但是在CentOS 8
上实践的过程中,遇到了iptables-save
无法保存防火墙规则的问题。因为对iptables
的使用也不是很频繁,这里就写了一个小脚本,通过systemd
的方式曲线救国,并记录一下脚本的内容
启用路由转发的流程
初期准备
首先将需要作为内部跳板的局域网机器加入ZeroTier网络中,这一步网上的教程比较多,不多做赘述
根据下面这个简单的脚本查询当前机器对应的默认网络
CIDR
信息1
2
3
4
5
6
7
8
9
10
11# 提取默认路由的接口名称
iface=$(route | grep default | awk '{print $8}')
# 使用接口名称获取默认网关
gateway=$(ip route show default | grep -oP "default via \K\S+")
# 使用相同接口获取子网掩码
netmask=$(ip -o -f inet addr show $iface | awk '{print $4}' | sed 's/.*\///')
# 输出默认网关和子网掩码
echo "${gateway}/${netmask}"这里为了做示范,假设输出的内容为
192.168.1.1/24
,机器在ZeroTier
子网对应的IP为10.242.231.123
将输出的默认网关填入
ZeroTier
控制台的Manage Routes
处。其中Destination
填入我们上面查询到的192.168.1.1/24
,Via
填入机器对应的网关IP:10.242.231.123
在这里设置之后,ZeroTier子网下其他设备就会将
192.168.1.x
网段的请求都转发给10.242.231.123
。因此如果有多个物理局域网需要转发,最好确定彼此之间的网段不会冲突
设置转发
在初期准备完成之后,会发现此时如果想从虚拟局域网的其他设备直接通过192.168.1.x
的网段访问内网其他设备,是无法成功通信的。这是因为默认的Linux
发行版一般都会禁用路由转发的功能来确保安全。因此还需要我们给当前系统启用路由转发
开启
sysctl
的路由转发1
sudo sysctl -w net.ipv4.ip_forward=1
但是在完成了上面的步骤以后,也会发现只有跳板机本身的192.168.1.x
可以访问,局域网内其他设备不一定能直接访问。这个时候就还需要我们对防火墙的规则进行修改,放行ZeroTier
的网络请求
对于这一步,根据官方的文档,理论上直接执行下面的步骤就能成功
Configure iptables
Assign some shell variables (personalize these)
1PHY_IFACE=eth0; ZT_IFACE=zt7nnig26
Add rules to iptables
1
sudo iptables -t nat -A POSTROUTING -o $PHY_IFACE -j MASQUERADE sudo iptables -A FORWARD -i $PHY_IFACE -o $ZT_IFACE -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables -A FORWARD -i $ZT_IFACE -o $PHY_IFACE -j ACCEPT
Save iptables rules for next boot
1sudo apt install iptables-persistent sudo bash -c iptables-save > /etc/iptables/rules.v4
但是在实践的过程中,发现在物理机刚启动的时候,ZeroTier
的网卡并不会立马被添加到系统当中。因此写了一个开机自启动的轮训脚本,在监测到网卡正确加载之后,再对接口进行修改放行
在
/etc/systemd/system
下创建服务zerotier-nat.service
1
2
3
4
5
6
7
8
9
10
11
12[Unit]
Description=Setup IP forwarding and iptables rules for ZeroTier
Wants=zerotier-one.service
After=zerotier-one.service network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/enable-zerotier-nat.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target创建文件
/usr/local/bin/enable-zerotier-nat.sh
,写入下列内容1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#!/bin/bash
# Enable IP forwarding
sysctl -w net.ipv4.ip_forward=1
# Get the interface with the default route (assumed to be PHY_IFACE)
PHY_IFACE=$(ip route | grep default | awk '{print $5}')
echo "Physical interface detected: $PHY_IFACE"
# Initialize attempt counter
attempt=0
# Try to find the ZeroTier interface, retry up to 10 times every 5 seconds
while [ $attempt -lt 10 ]; do
ZT_IFACE=$(ip link show | grep -o 'zt[a-zA-Z0-9]*')
if [ ! -z "$ZT_IFACE" ]; then
echo "ZeroTier interface detected: $ZT_IFACE"
break
else
echo "ZeroTier interface not found, retrying in 5 seconds..."
sleep 5
((attempt++))
fi
done
# Check if ZT_IFACE was found
if [ -z "$ZT_IFACE" ]; then
echo "Failed to find ZeroTier interface after 10 attempts."
exit 1
fi
# Set up NAT
iptables -t nat -A POSTROUTING -o $PHY_IFACE -j MASQUERADE
# Set up IP forwarding rules
iptables -A FORWARD -i $PHY_IFACE -o $ZT_IFACE -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $ZT_IFACE -o $PHY_IFACE -j ACCEPT为刚刚编辑的脚本添加可执行权限,并设置脚本的开机自启动
1
2chmod +x /usr/local/bin/enable-zerotier-nat.sh
systemctl enable --now zerotier-nat
经过上面的操作之后,理论上就完成了,可以在ZeroTier
其他设备上直接访问192.168.1.x
的家庭内网设备啦