firewalld用rich rule做动态IP黑名单必须加--permanent并执行--reload,否则临时规则在重载后消失;reject用于调试,drop用于静默丢弃;批量封禁推荐--direct直写iptables以提升性能。
临时规则(不带 --permanent)在 firewall-cmd --reload 后就消失,根本起不到“黑名单”作用。很多人测试时用 --add-rich-rule 看似生效,一重载或重启就清空,误以为脚本没跑通。
正确写法必须带 --permanent,且后续一定要 firewall-cmd --reload 才能让规则真正落地:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.44" reject'<br>sudo firewall-cmd --reload
reject 会让客户端收到明确拒绝响应(如 Connection refused),适合调试;生产环境若需静默丢弃,换成 drop
ERROR: timeout 或静默忽略--remove-rich-rule 时,source address 和 reject 顺序不能颠倒直接在 shell 循环里反复调用 firewall-cmd,每条规则都触发 D-Bus 通信和规则链重编译,100 个 IP 就可能卡住或超时。实际线上环境建议合并操作。
推荐做法是:先收集所有待封 IP,生成一个临时 rich rule 文件,再用 --direct 批量注入内核链:
sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -s 203.0.113.44 -j REJECT<br>sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -s 192.168.5.101 -j REJECT
--direct 绕过 firewalld 抽象层,直写 iptables 规则,性能高、无延迟,适合高频封禁场景0)控制优先级,数字越小越靠前,确保黑名单早于白名单生效firewall-cmd --runtime-to-permanent 或手动保存到 /etc/firewalld/direct.xml
很多自动化脚本只关注“命令返回 0”,却没验证规则是否真进链表。常见失效原因包括:zone 绑定错网卡、rich rule 被其他规则覆盖、firewalld 服务未运行。
校验不能只看 firewall-cmd --list-all,得查底层链:
firewall-cmd --get-active-zones,确保目标 IP 是落在你操作的 zone(比如 public)里firewall-cmd --zone=public --list-rich-rules
sudo iptables -L INPUT -n -v | grep 203.0.113.44
curl -v http://your-server:80,应看到 Connection refused 或超时CentOS Linux 7.9 已于 2024 年 6 月停止维护,但仍在不少旧系统中运行。它的 firewalld 默认启用,但部分镜像预装了 iptables-services 并设为开机启动,导致 firewalld 实际被屏蔽——此时你往 firewalld 加的任何规则都不生效。
检查并修复步骤:
systemctl is-active firewalld 和 systemctl is-active iptables 只能有一个是 active (running)
iptables 在跑,停用它:sudo systemctl stop iptables && sudo systemctl disable iptables
sudo systemctl enable --now firewalld
firewall-cmd --state 必须输出 running,且 iptables -L 输出中不应出现你手动加的 DROP 规则规则持久化本身没问题,但旧系统里 service 冲突比想象中更常见,不检查就写脚本,等于往空配置里填数据。