一、背景
为了保护我的网站(一个在线工具箱),我早早地配置了 iptables + ipset,只允许国内 IP 段访问 80/443 端口,其他来源一律拒绝。同时写了一个 update_china_ipset.sh 脚本,每天自动从 ipdeny.com 下载最新的国内 IP 段,更新到 china 集合中。

这套组合拳运行了很久,日志里几乎没有境外 IP 访问。直到有一天,服务器因系统更新重启,第二天我查看 Nginx 日志时,发现了大量来自 瑞士、美国、新加坡 的 IP 请求,而且很多在尝试 /wp-admin、/phpmyadmin、/.env 等敏感路径。

白名单失效了。

二、排查过程
我立刻登录服务器(幸好还能通过阿里云 Workbench 进去),检查 iptables 规则:

iptables -L INPUT -n

输出结果竟然是空的。再检查 ipset 集合:

ipset list china

提示 china 集合不存在。显然,重启后 iptables 规则和 ipset 集合都丢失了。

我这才想起来,之前添加 iptables 规则时是手动执行的 iptables -A INPUT …,并没有保存。而 ipset 集合也是脚本运行时动态创建的,重启后自然不会保留。

三、原因分析
iptables 规则默认是临时的:重启后所有规则都会清零,除非显式保存到配置文件并设置开机加载。

ipset 集合也是内存中的结构:重启后同样消失,需要在开机时重新创建并填充。

我虽然每天凌晨用 update_china_ipset.sh 更新集合,但脚本中只执行了 ipset flush china 和 ipset add,没有 ipset create china hash:net -exist 这样的创建逻辑。所以集合一旦丢失,脚本再次运行时就会报错“set does not exist”。

四、解决方案

  1. 立即恢复规则(临时)
    我重新执行了之前用于添加 iptables 规则的命令:
ipset create china hash:net
# 然后从 /root/china_ip_list.txt 导入(如果有备份)
# 或者手动运行 update_china_ipset.sh 重建集合

iptables -I INPUT -p tcp --dport 80 -m set --match-set china src -j ACCEPT
iptables -I INPUT -p tcp --dport 443 -m set --match-set china src -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j DROP
iptables -A INPUT -p tcp --dport 443 -j DROP

网站立刻恢复了境外拦截。

  1. 持久化 iptables 规则
    安装 iptables-services,并将当前规则保存到文件:
sudo yum install -y iptables-services
sudo service iptables save
sudo systemctl enable iptables

这样,以后每次重启,iptables 规则都会自动加载。

  1. 修复 ipset 自动恢复
    修改 update_china_ipset.sh,在脚本开头加入创建集合的逻辑(-exist 选项确保集合已存在时不报错):
# 确保 china 集合存在
ipset create china hash:net -exist 2>/dev/null

同时,为了让 ipset 集合在重启后能尽快被填充,我将该脚本添加到了 /etc/rc.local 中,确保每次开机时自动运行(前提是脚本放在 root 目录下且有执行权限)。

  1. 双重保险:增加定时任务
    我已经有 crontab 每天凌晨 3 点执行 update_china_ipset.sh,这能保证即使某天开机脚本没跑,第二天也会自动更新。

五、教训与总结
防火墙规则必须持久化:任何时候修改 iptables 规则后,立即执行 service iptables save。

ipset 集合需要开机创建:脚本中要包含 ipset create … -exist,而不是假设集合永远存在。

备份是底线:最好将规则和集合导出为文件(iptables-save、ipset save),放在安全的地方。

应急通道不能依赖 SSH:如果你像我一样把自己 IP 加白名单,一定要确保还有 Workbench 或 VNC 可以登录,防止 IP 变更后自己被锁在外面。

现在,我的服务器即使再重启,iptables 规则和 ipset 集合都会自动恢复。日志里再也看不到那些讨厌的境外扫描器了。

一句话总结:Linux 防火墙默认不持久,记得 save 和 enable,并让 ipset 脚本具备“自创”能力。

it-tools,一个适合开发者的在线工具箱

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐