Linux 服务器重启后 iptables 规则全丢了,原来是没做持久化
前阵子一台公网服务器重启做完内核升级,重启完没多久就收到告警:对外开放的数据库端口居然能在外网直接连上。登录一查,iptables 规则空空如也,之前辛辛苦苦配的防火墙全没了。踩了一次才明白,iptables 规则默认只活在内存里,不做持久化,重启必然丢。
问题现象
重启前后对比特别明显。重启前我明明配了类似这样的规则:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP
iptables -P INPUT DROP
重启后再看:
$ iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
不仅规则没了,连默认策略都回到了 ACCEPT。等于这台机器在重启后裸奔了一段时间,直到有人从外网扫到 3306 才被发现。
排查过程
第一反应是「谁把规则清了」?先排除人为操作:
$ last reboot
$ history | grep iptables
没查到有人执行过 iptables -F。接着怀疑是不是有别的服务在启动阶段重置了 netfilter,比如 firewalld 或 nftables 在开机时抢占了规则表:
$ systemctl status firewalld
$ nft list ruleset
这台机器没开 firewalld,nftables 也是空的。最后才反应过来:iptables 的规则从来就只存在内核内存里,没有落盘,重启即清零。我之前一直是「配完就走」,从没保存过。这是认知盲区,不是被谁动了。
补充一个排查时容易忽略的点:确认 iptables 的后端实现。现代发行版很多把 iptables 偷偷接到了 nft 后端,命令看着一样,实际写进了另一张表:
$ iptables --version
iptables v1.8.7 (nf_tables)
看到 nf_tables 就说明是「新」后端。这时如果你用老办法把规则存到 /etc/sysconfig/iptables 再用 legacy 的 iptables-restore 灌回去,表里不会有任何东西。正确做法是同一套 save/restore 工具配对使用——nf_tables 后端就用 iptables-save / iptables-restore,不要混用。搞清楚后端,能省掉一半「怎么存都不生效」的返工。
根因
iptables 本质是用户态工具,通过 netlink 把规则下发到内核的 netfilter 框架。规则存储在内核内存,断电/重启后自然消失。所谓「保存」,其实是把当前规则导出成文本文件,开机时再重新灌回去。
另一个坑是后端不一致:现代发行版 iptables 可能映射到 nft 后端(iptables-nft),而你用 iptables-save 导出、用 iptables-restore 导入时若后端不匹配,也会看起来「没生效」。可以用 iptables --version 看它指向的是 legacy 还是 nf_tables。
解决办法
第一,配完立刻保存。 用发行版自带工具最省心:
# Debian/Ubuntu
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
# 开机自动恢复
apt install iptables-persistent netfilter-persistent
netfilter-persistent save
netfilter-persistent 会在开机和关机时自动 save / restore,以后改完规则只要再跑一次 netfilter-persistent save 即可。
第二,CentOS/RHEL 用 service 版本:
service iptables save # 写入 /etc/sysconfig/iptables
systemctl enable iptables
第三,嫌手工管理麻烦,直接上 firewalld 或 nftables。 firewalld 的配置是落盘的,重启不丢,而且支持 zone 和 rich-rule,长期维护比裸 iptables 省心:
firewall-cmd --permanent --add-port=22/tcp
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 port port=3306 reject'
firewall-cmd --reload
注意一定要带 --permanent,否则只改运行时、重启照样没。
第四,上线前验证。 改完别只看 iptables -L,用一台跳板机实打实扫一下端口(nmap -Pn 主机),确认该开的开了、该堵的堵了,再交付。
小结
iptables 的规则是「内存态」的,任何改动都必须显式持久化,否则一次重启就回到解放前,甚至把安全策略搞丢。我的习惯现在是:配完规则 → 立即 save → 重启验证 → 用 nmap 实测端口。用 firewalld/nftables 这类配置落盘的方案能少踩一半坑。记住一句话:没持久化的防火墙,等于没配。
- 点赞
- 收藏
- 关注作者
评论(0)