iptables-restore不支持ipset命令,需先用ipset restore加载集合,再用iptables-restore加载引用规则,否则报错或静默失败;nftables原生支持原子性加载。

iptables-restore 本身不支持 ipset,必须分开处理
直接把 ipset 命令写进 iptables-save 输出的规则文件里,iptables-restore 会报错并跳过整条规则,甚至导致后续规则加载失败。因为 iptables-restore 只认 Netfilter 规则语法,不认识 ipset 的创建、添加、引用等操作。常见错误现象是:iptables-restore: line N failed,或规则看似加载成功但实际没生效——ipset list 为空,iptables -L 里却有 match-set 规则,运行时直接报 set not found。
原子性加载的关键:先建好 ipset,再用 iptables-restore 加载引用规则
所谓“原子性”,是指整个防火墙状态切换要么全成功、要么全失败,中间不能出现部分生效的混乱态。而 ipset 和 iptables 是两个独立子系统,内核中也没有跨模块事务机制。所以真正的原子性只能靠顺序控制+预检实现:
- 用
ipset restore(不是iptables-restore)一次性加载所有集合定义和成员,它本身是原子的; - 再用
iptables-restore -t先测试规则文件是否能正确解析(尤其检查-m set --match-set引用的集合名是否拼写一致); - 最后才执行
iptables-restore加载规则——此时所有依赖的ipset已就绪,不会因集合不存在而静默失败; - 如果任一环节出错,整个流程中断,旧规则仍保持有效,无中间态风险。
ipset restore + iptables-restore 的标准执行链
假设你有一套规则存于 /etc/iptables/rules.v4,其中包含 -m set --match-set blacklist src -j DROP 这类规则,对应 ipset 集合需提前定义好。你需要两个配套文件:
-
/etc/ipset/blacklist.ipset:内容为create blacklist hash:ip+ 若干add blacklist 192.168.1.100行; -
/etc/iptables/rules.v4:不含任何ipset命令,只含引用规则,且确保blacklist名字大小写、空格完全一致;
执行顺序如下:
sudo ipset restore <p>注意:不要用 <code>ipset -F</code> 或 <code>ipset -X</code> 清空前先确认新集合已加载完成,否则可能短暂放行恶意流量。</p><h3>为什么不用 nftables?它才是真原子</h3><p>如果你的系统内核 ≥ 5.10 且能接受迁移,<code>nft</code> 原生支持 <code>map</code> 和 <code>dynamic sets</code>,一条 <code>nft -f rules.nft</code> 就能同时定义映射、填充数据、设置规则,整个加载过程由内核保证原子性。而 <code>iptables + ipset</code> 组合本质是两阶段提交,靠脚本协调,容易在异常中断(如 Ctrl+C、OOM kill)时留下残留集合或未更新规则。这也是为什么 2026 年起新部署服务器普遍推荐直接上 <code>nftables</code>——不是因为它更难,而是它把“原子性”从运维脚本逻辑下沉到了工具本身。</p>











