如何在Linux中配置具体的系统级防火墙动态黑名单同步与更新任务

作者:袖梨 2026-07-19
firewalld用rich rule做动态IP黑名单必须加--permanent并执行--reload,否则临时规则在重载后消失;reject用于调试,drop用于静默丢弃;批量封禁推荐--direct直写iptables以提升性能。

firewalld 用 rich rule 做动态 IP 黑名单,必须加 --permanent

临时规则(不带 --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
  • 同一个 IP 重复添加不会报错,但也不会叠加——firewalld 不允许重复规则,第二次执行会提示 ERROR: timeout 或静默忽略
  • 删除时必须用完全一致的字符串,包括引号位置和空格:用 --remove-rich-rule 时,source addressreject 顺序不能颠倒

黑名单批量更新要避免逐条调用 firewall-cmd

直接在 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)控制优先级,数字越小越靠前,确保黑名单早于白名单生效
  • 这种规则默认不持久,重启 firewalld 或系统后丢失,必须配合 firewall-cmd --runtime-to-permanent 或手动保存到 /etc/firewalld/direct.xml

同步任务必须校验规则是否真实生效

很多自动化脚本只关注“命令返回 0”,却没验证规则是否真进链表。常见失效原因包括:zone 绑定错网卡、rich rule 被其他规则覆盖、firewalld 服务未运行。

校验不能只看 firewall-cmd --list-all,得查底层链:

  • 确认当前活跃 zone:firewall-cmd --get-active-zones,确保目标 IP 是落在你操作的 zone(比如 public)里
  • 查 rich rule 是否写入:firewall-cmd --zone=public --list-rich-rules
  • 查底层 iptables 是否命中:sudo iptables -L INPUT -n -v | grep 203.0.113.44
  • 模拟测试:从被封 IP 机器上 curl -v http://your-server:80,应看到 Connection refused 或超时

CentOS 7 上持久化黑名单要特别注意 service 状态

CentOS Linux 7.9 已于 2024 年 6 月停止维护,但仍在不少旧系统中运行。它的 firewalld 默认启用,但部分镜像预装了 iptables-services 并设为开机启动,导致 firewalld 实际被屏蔽——此时你往 firewalld 加的任何规则都不生效。

检查并修复步骤:

  • 确认真正运行的是哪个服务:systemctl is-active firewalldsystemctl is-active iptables 只能有一个是 active (running)
  • iptables 在跑,停用它:sudo systemctl stop iptables && sudo systemctl disable iptables
  • 启用 firewalld:sudo systemctl enable --now firewalld
  • 验证:firewall-cmd --state 必须输出 running,且 iptables -L 输出中不应出现你手动加的 DROP 规则

规则持久化本身没问题,但旧系统里 service 冲突比想象中更常见,不检查就写脚本,等于往空配置里填数据。

相关文章

精彩推荐