CentOS服务器跑久了,防火墙规则往往越堆越多。临时放行的IP、测试用的端口、已经下线的业务白名单,全都留在iptables或firewalld的配置里。规则一多,不仅拖慢匹配效率,更危险的是那些早已失效的放行条目,等于给服务器留了一堆没人管的暗门。清理防火墙规则不是删几条了事,而是要建立一套可审计、可回滚、能定期自动执行的维护机制。

先搞清楚你用的是iptables还是firewalld

CentOS 6默认用iptables,CentOS 7和8虽然底层也走iptables或nftables,但管理工具默认是firewalld。两者清理思路完全不同,动手前必须确认。执行以下命令判断:

systemctl status firewalld
systemctl status iptables

如果firewalld是active状态,就按firewalld的体系来清理。如果只有iptables在运行,则直接操作iptables规则文件。混用两套工具是运维大忌,firewalld的规则会转换成iptables链,手动改iptables可能被firewalld覆盖。

iptables规则清理:从导出备份开始

清理iptables规则前,第一件事是把当前生效的规则完整导出。不要相信自己的记忆,也不要觉得某些规则明显没用就直接删。执行:

iptables-save > /root/iptables-backup-$(date +%Y%m%d-%H%M%S).rules

这个备份文件就是你的后悔药。接下来查看当前规则,带上行号:

iptables -L -n -v --line-numbers

输出中每一行前面的数字就是规则序号。重点看INPUT链,因为绝大多数放行和拦截都发生在这里。对于已经确认无用的规则,用行号删除。比如要删除INPUT链第7条规则:

iptables -D INPUT 7

注意一个关键点:删除操作会让后续行号前移。如果一次要删多条,必须从后往前删,也就是先删行号大的,再删行号小的。否则删完第一条,后面的行号全变了,再按原行号删就会删错对象。

iptables规则审计:识别哪些该删

判断一条规则是否该清理,不能凭感觉。可以从几个维度核查。第一,看流量计数。iptables -L -n -v输出中的pkts和bytes列显示该规则匹配了多少数据包。如果一条放行规则长时间零匹配,说明对应的业务可能已经停用。第二,检查源IP或目标端口是否还存在于当前业务清单中。第三,看注释。规范的运维会在添加规则时用-m comment打标记,没有注释的规则要格外谨慎,先确认来源再决定去留。

对于零匹配的规则,建议先改成日志记录模式观察一周,而不是直接删除。例如把某条放行规则临时改为记录日志:

iptables -I INPUT 1 -s 192.168.10.50 -j LOG --log-prefix "audit-rule: "

观察/var/log/messages里是否有对应日志输出。一周后确认无流量,再正式删除。

firewalld规则清理:用zone和service管理

firewalld的规则组织方式和iptables不同,它按zone(区域)和service(服务)来管理。查看当前默认zone和已配置的规则:

firewall-cmd --list-all

输出中services、ports、rich rules、forward-ports几个部分分别列出放行的服务、端口、富规则和端口转发。清理时先看rich rules,因为这里最容易堆积临时规则。查看所有富规则:

firewall-cmd --list-rich-rules

删除富规则需要完整匹配规则内容。比如删除一条放行特定IP访问22端口的富规则:

firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="203.0.113.50" port port="22" protocol="tcp" accept'

对于开放的端口,用remove-port删除:

firewall-cmd --permanent --remove-port=8080/tcp

对于开放的服务,用remove-service删除:

firewall-cmd --permanent --remove-service=ftp

所有带--permanent的修改都只写入配置文件,不会立即生效。确认修改无误后,执行reload让配置生效:

firewall-cmd --reload

reload会保留当前连接不断开,比complete-reload更安全。但要注意,reload不会中断已建立的连接,如果某条规则被删除,已建立的连接仍然保持,直到连接断开。

清理临时规则和运行时配置

firewalld有一个容易被忽略的问题:不带--permanent参数添加的规则只存在于运行时,reload或重启后就消失。很多运维在排查问题时临时加了规则,事后忘了处理。检查运行时和永久配置的差异:

firewall-cmd --runtime-to-permanent

这条命令会把运行时配置同步到永久配置,但前提是你确认运行时规则都是需要的。反过来,如果只想看差异,可以分别执行:

firewall-cmd --list-all
firewall-cmd --permanent --list-all

对比两者输出,找出只在运行时存在的规则。这些临时规则要么补上--permanent正式固化,要么直接清理掉,避免重启后配置漂移。

建立定期清理机制:脚本化与审计日志

手动清理只能解决一时的问题,真正有效的是把清理流程固化下来。建议写一个防火墙审计脚本,每周执行一次,输出规则清单、匹配计数、最后修改时间等信息。iptables环境下的审计脚本示例:

#!/bin/bash
# firewall-audit.sh
BACKUP_DIR="/root/firewall-audit"
mkdir -p $BACKUP_DIR
DATE=$(date +%Y%m%d-%H%M%S)
iptables-save > $BACKUP_DIR/iptables-$DATE.rules
echo "=== Firewall Audit Report: $DATE ===" > $BACKUP_DIR/report-$DATE.txt
echo "" >> $BACKUP_DIR/report-$DATE.txt
echo "--- Rules with zero packet match ---" >> $BACKUP_DIR/report-$DATE.txt
iptables -L -n -v --line-numbers | awk '$1=="0" && $2=="0" {print}' >> $BACKUP_DIR/report-$DATE.txt
echo "" >> $BACKUP_DIR/report-$DATE.txt
echo "--- All INPUT chain rules ---" >> $BACKUP_DIR/report-$DATE.txt
iptables -L INPUT -n -v --line-numbers >> $BACKUP_DIR/report-$DATE.txt

把这个脚本加入crontab,每周一凌晨执行:

0 2 * * 1 /root/firewall-audit.sh

审计报告会列出所有零匹配的规则,运维人员每周花几分钟过一遍,确认哪些可以清理。这样防火墙规则就不会失控。

清理时的安全注意事项

清理防火墙规则最大的风险是把自己锁在服务器外面。如果服务器是远程访问,清理前务必确认当前SSH连接的源IP在放行列表中,或者确保有控制台访问权限作为后备。一个稳妥的做法是:清理前先添加一条针对当前管理IP的临时放行规则,并设置自动过期。iptables下可以用at命令定时删除:

iptables -I INPUT 1 -s 你的管理IP -p tcp --dport 22 -j ACCEPT
echo "iptables -D INPUT 1" | at now + 30 minutes

firewalld下可以添加带timeout的富规则,不过firewalld本身不支持规则自动过期,需要配合at或cron实现。另外,清理完规则后不要立即断开SSH连接,先新开一个连接测试能否正常登录,确认无误后再关闭旧连接。

规则清理后的验证与压测

清理完规则后,不能只看命令执行成功就完事。要验证几件事。第一,确认防火墙服务状态正常:

systemctl status firewalld
# 或
systemctl status iptables

第二,确认关键服务端口仍然可达。从外部机器用nc或telnet测试:

nc -zv 服务器IP 22
nc -zv 服务器IP 80
nc -zv 服务器IP 443

第三,检查规则数量是否合理。iptables -L | wc -l看一下总行数,如果清理后规则数量没有明显减少,说明清理不够彻底,或者存在重复规则。第四,对于生产环境,建议在清理后观察一段时间,确认业务日志没有出现连接异常。

防止规则再次膨胀的管理规范

清理只是治标,防止规则再次堆积才是治本。建议在团队内建立几条硬性规范。第一,所有临时放行规则必须加注释,注明用途、添加人、有效期。iptables用-m comment,firewalld富规则里可以写description。第二,临时规则必须设置过期时间,用at命令或cron任务自动删除。第三,每次添加规则前先检查是否已存在相同或相似的规则,避免重复添加。第四,每月做一次全量规则审计,输出报告存档。第五,防火墙配置变更纳入变更管理流程,重大变更前备份、变更后验证。

把这些规范落实到日常操作中,防火墙规则就能保持在一个可控的规模。定期清理不再是突击任务,而是日常运维的一部分。服务器安全不是靠堆规则堆出来的,精简且准确的规则集才是真正有效的防线。