Firewalld rich rule 是否生效取决于流量是否进入对应 zone 及规则在 zone 内的匹配顺序;需确认接口/源绑定、zone 优先级、规则添加顺序及 reload 状态。

Firewalld 的 rich rule 生效问题,核心在于规则的匹配顺序和 zone 的优先级逻辑。rich rule 本身不决定优先级,而是依赖它所在的 zone 以及该 zone 的接口/源绑定关系;如果规则没生效,大概率是流量根本没走到这个 zone,或者被更高优先级的 zone 拦截了。
确认流量实际进入的是你配置 rich rule 的 zone
firewalld 按照“接口 > 源地址 > 默认 zone”的顺序匹配 zone,不是按规则内容排序。例如:你给 public zone 加了 rich rule,但网卡 eth0 实际绑定在 trusted zone,那所有从 eth0 进来的包都走 trusted,public 的规则完全不参与处理。
- 运行 firewall-cmd --get-active-zones 查看当前各 zone 绑定的接口和源
- 用 firewall-cmd --zone=xxx --list-all 确认目标 zone 确实包含你添加的 rich rule(注意:--permanent 添加后需 reload 才生效)
- 检查接口归属:firewall-cmd --get-zone-of-interface=eth0
rich rule 的匹配顺序取决于所在 zone 的规则列表顺序
同一 zone 内,rich rule 按添加顺序从上到下匹配,**先匹配上的规则立即执行动作(accept/drop),不再继续匹配后续规则**。但要注意:rich rule 是插在该 zone 的“自定义规则”区,排在默认服务/端口规则之后、masquerade/forward-port 等高级规则之前。
- 查看完整规则链:firewall-cmd --zone=xxx --list-rich-rules(注意顺序)
- 若想让某条 rich rule 优先,可先 --remove-rich-rule 清空,再按期望顺序重新添加
- 避免写冲突规则,比如前面 accept 了 8080,后面又 drop 8080 —— 后者永远不会触发
检查是否被 default zone 或 system-configured zone 覆盖
未显式绑定接口或源的流量,会落入 default zone(通常是 public)。如果你在 custom zone(如 myzone)里加了 rich rule,但忘了把接口或源分配过去,流量就进了 default zone,你的规则自然不生效。
- 查 default zone:firewall-cmd --get-default-zone
- 临时将接口切到目标 zone 测试:firewall-cmd --zone=xxx --add-interface=eth0
- 永久设置(需 --permanent + reload):firewall-cmd --permanent --zone=xxx --add-interface=eth0
调试技巧:用 --query-rich-rule 快速验证 + 日志辅助
光看 list 不够,要确认规则是否真正加载进内核链。firewalld 基于 nftables,可用底层命令交叉验证。
- 查某条规则是否存在(返回 0 表示存在):firewall-cmd --query-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="22" protocol="tcp" accept'
- 开启 debug 日志:firewall-cmd --set-log-denied=all,然后查 /var/log/firewalld 看拒绝记录对应哪个 zone
- 直查 nft 链:nft list chain inet firewalld filter_IN_public(替换为你的 zone 名),确认 rich rule 对应的 handle 是否出现










