通过Zerotier实现异地设备访问局域网自动配置防火墙脚本
📝 ZeroTier 转发脚本优化笔记
1. 脚本目标
- 自动检测物理网卡和 ZeroTier 虚拟网卡
- 开启 IP 转发
- 添加 NAT 和 FORWARD 规则,实现 ZeroTier 与物理网络互通
- 保证规则持久化,不影响现有防火墙规则
2. 优化思路
-
安全性
-
使用
set -euo pipefail-e:命令出错立即退出-u:引用未定义变量时报错-o pipefail:管道中任一命令失败即退出
-
检查
$EUID确保以 root 运行 -
网卡检测
-
物理网卡:排除
lo、docker、br-、zt - ZeroTier 网卡:匹配
^zt -
检测不到直接退出,避免空变量执行 iptables
-
交互选择
-
多个网卡时使用
select让用户选择 -
验证输入是否为空
-
IP 转发
-
sysctl -w net.ipv4.ip_forward=1 -
/etc/sysctl.conf中追加配置(避免重复) -
iptables 规则
-
添加前先用
iptables -C检查是否已存在 - NAT:
POSTROUTING -o $PHY_IFACE -j MASQUERADE -
FORWARD:
- ZeroTier → 物理网卡:
ACCEPT - 物理网卡 → ZeroTier:
RELATED,ESTABLISHED
- ZeroTier → 物理网卡:
-
规则持久化
-
优先
netfilter-persistent save(Debian/Ubuntu) - 其次
service iptables save(CentOS) - 最后
iptables-save > /etc/iptables.rules手动加载
3. 优化后脚本结构
#!/bin/bash
set -euo pipefail
# 1. 检查 root 权限
# 2. 检测物理网卡 & ZeroTier 网卡
# 3. 用户选择(多网卡情况)
# 4. 开启 IP 转发
# 5. 添加 iptables 规则(仅在不存在时添加)
# 6. 保存规则(多种方式兼容)
4. 脚本
#!/bin/bash
set -euo pipefail
# 必须以 root 运行
if [[ $EUID -ne 0 ]]; then
echo "❌ 请使用 root 权限运行此脚本"
exit 1
fi
# 自动检测物理网卡(排除 lo、docker、br-、zt 开头)
PHY_CANDIDATES=($(ip -o link show | awk -F': ' '{print $2}' | grep -Ev '^(lo|docker|br-|zt)'))
ZT_CANDIDATES=($(ip -o link show | awk -F': ' '{print $2}' | grep -E '^zt'))
# 检查是否找到网卡
if [[ ${#PHY_CANDIDATES[@]} -eq 0 ]]; then
echo "❌ 未检测到物理网卡"
exit 1
fi
if [[ ${#ZT_CANDIDATES[@]} -eq 0 ]]; then
echo "❌ 未检测到 ZeroTier 网卡"
exit 1
fi
# 选择物理网卡
if [[ ${#PHY_CANDIDATES[@]} -eq 1 ]]; then
PHY_IFACE=${PHY_CANDIDATES[0]}
else
echo "检测到多个物理网卡,请选择:"
select opt in "${PHY_CANDIDATES[@]}"; do
[[ -n "$opt" ]] && PHY_IFACE=$opt && break
done
fi
# 选择 ZeroTier 网卡
if [[ ${#ZT_CANDIDATES[@]} -eq 1 ]]; then
ZT_IFACE=${ZT_CANDIDATES[0]}
else
echo "检测到多个 ZeroTier 网卡,请选择:"
select opt in "${ZT_CANDIDATES[@]}"; do
[[ -n "$opt" ]] && ZT_IFACE=$opt && break
done
fi
echo "✅ 使用物理网卡: $PHY_IFACE"
echo "✅ 使用 ZeroTier 网卡: $ZT_IFACE"
# 开启 IP 转发
if sysctl -w net.ipv4.ip_forward=1 >/dev/null; then
grep -q "net.ipv4.ip_forward=1" /etc/sysctl.conf || echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
else
echo "❌ 无法开启 IP 转发"
exit 1
fi
# 添加 iptables 规则(仅在不存在时添加)
iptables -t nat -C POSTROUTING -o "$PHY_IFACE" -j MASQUERADE 2>/dev/null || \
iptables -t nat -A POSTROUTING -o "$PHY_IFACE" -j MASQUERADE
iptables -C FORWARD -i "$ZT_IFACE" -o "$PHY_IFACE" -j ACCEPT 2>/dev/null || \
iptables -A FORWARD -i "$ZT_IFACE" -o "$PHY_IFACE" -j ACCEPT
iptables -C FORWARD -i "$PHY_IFACE" -o "$ZT_IFACE" -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \
iptables -A FORWARD -i "$PHY_IFACE" -o "$ZT_IFACE" -m state --state RELATED,ESTABLISHED -j ACCEPT
# 保存规则
if command -v netfilter-persistent >/dev/null 2>&1; then
netfilter-persistent save
elif command -v service >/dev/null 2>&1 && service iptables save >/dev/null 2>&1; then
service iptables save
elif command -v iptables-save >/dev/null 2>&1; then
iptables-save > /etc/iptables.rules
echo "⚠️ 已保存到 /etc/iptables.rules,请在启动时加载"
else
echo "⚠️ 未检测到 iptables 持久化工具,请手动保存规则"
fi
echo "🎯 ZeroTier 转发规则已添加且不会影响现有防火墙规则"
5. 使用建议
- 首次运行:建议手动确认网卡选择
- 系统重启后:确保持久化规则已加载
- 调试:可在脚本开头加
set -x查看执行过程 - 备份规则:
iptables-save > backup.rules