在Linux中用firewall-cmd动态添加黑名单必须加--permanent并执行--reload才持久生效;drop静默丢包适合公网防护,reject返回拒绝响应便于内网排障;批量封禁推荐--direct直写iptables或合并规则后批量加载;删除rich rule需严格匹配原字符串。

在 Linux 系统中用 firewall-cmd 动态添加黑名单,核心是使用 rich rule 语法配合 --permanent 和 --reload,否则规则重启或重载后就失效。
必须加 --permanent 并 reload 才真正生效
很多人误以为 --add-rich-rule 不加 --permanent 就能长期封禁,其实这只是临时规则:一旦执行 firewall-cmd --reload 或重启 firewalld,规则就清空。生产环境务必按以下流程操作:
- 用
--permanent添加规则,例如封单个 IP:sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.44" reject' - 立即执行重载使规则写入内核:
sudo firewall-cmd --reload - 验证是否生效:
sudo firewall-cmd --list-rich-rules或sudo firewall-cmd --zone=public --list-rich-rules
区分 drop 和 reject 场景
封禁行为有两种响应方式,选错会影响安全性和排障效率:
- drop:静默丢弃所有包,客户端无响应,直到超时。适合面向公网的服务器,可延缓扫描和暴力攻击。
-
reject:立即返回拒绝响应(如
Connection refused)。适合内网调试,便于快速定位连通性问题。 - 示例(封某 IP 的 80 端口):
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.0.200" port port="80" protocol="tcp" drop'
批量封禁要避免逐条调用
一次性封几十上百个 IP 时,循环执行 firewall-cmd --add-rich-rule 效率极低,容易触发 D-Bus 超时或规则编译卡顿。推荐两种方式:
-
方案一(推荐):用 --direct 直写 iptables 链
绕过 firewalld 抽象层,性能高、无延迟:sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -s 203.0.113.44 -j DROP
注意:该方式默认不持久,需后续执行firewall-cmd --runtime-to-permanent或手动保存到/etc/firewalld/direct.xml。 -
方案二:合并 rich rule 后批量加载
先生成完整规则列表,再用脚本统一添加并 reload,减少 reload 次数。
删除规则必须完全匹配原字符串
firewalld 对 rich rule 删除要求严格,引号位置、空格、关键词顺序都不能错。例如添加时用了:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.44" reject'
那么删除时必须写成:
sudo firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="203.0.113.44" reject'
若顺序写成 reject source address=... 或漏掉引号,命令会静默失败或报错。











