firewalld rich rule 添加后不生效的 zone 优先级调试

9次阅读

firewalld rich rule 不生效的首要原因是 zone 绑定错误,需先用 firewall-cmd –get-active-zones 确认网卡所属 zone,再检查该 zone 的 rich rule 并确保 –reload 生效。

firewalld rich rule 添加后不生效的 zone 优先级调试

firewalld rich rule 不生效,先确认 zone 绑定是否正确

rich rule 生效的前提是它所属的 zone 确实被应用在对应网卡或源地址上。很多人直接用 firewall-cmd --add-rich-rule 添加规则,却没检查该规则加到了哪个 zone——默认是 public,但如果你的接口实际属于 trusted 或自定义 zone,规则就完全不会触发。

查当前接口绑定的 zone:
firewall-cmd --get-active-zones
再查该 zone 的所有 rich rule:
firewall-cmd --zone=your-zone-name --list-rich-rules

  • 如果 --get-active-zones 没输出你的接口,说明它走的是 default zone(通常是 public),但得确认 firewall-cmd --get-default-zone
  • 如果接口出现在多个 zone 下(比如用了 --permanent 但没重载),以运行时 zone 为准,--runtime-to-permanent 不会自动同步 rich rule
  • 临时添加的 rich rule 不带 --permanent,重启 firewalld 后消失;永久添加后必须 firewall-cmd --reload 才生效

rich rule 中的 source address 写法影响匹配优先级

firewalld 的 rich rule 是按“从上到下”顺序匹配的,但真正决定是否命中的是 sourcedestination 的 CIDR 精确度,而非添加顺序。比如你写了两条规则:

rule family="ipv4" source address="192.168.1.0/24" accept rule family="ipv4" source address="192.168.1.100" accept

实际生效的是更具体的那条(即后者),因为 firewalld 底层用的是 nftables,其链匹配逻辑优先选最长前缀匹配(LPM),不是简单顺序执行。

  • source address 写成单 IP(如 192.168.1.100)比写成 /32 更稳妥,某些版本对 /32 解析有 bug
  • 不要混用 sourcedestination 在同一条 rule 里限制双向流量,firewalld rich rule 默认只管入向;出向需额外加 rule ... destination ... 并确保 zone 的 target 不是 DEFAULT_DROP
  • 若使用 ipset,务必确认 ipset 已存在且加载进内核:ipset list your-set-name,否则 rich rule 会静默失败

检查 runtime 规则是否真落到 nftables 链里

firewalld 是 nftables 前端,rich rule 最终要编译成 nft 表项。如果没生效,最直接的办法是绕过 firewalld 查底层:

看当前生效的 nft ruleset:
nft list ruleset | grep -A5 -B5 "firewalld"

  • rich rule 一般落在 inet firewalld filter_IN_XXX 链(XXX 是 zone 名),若找不到对应 rule,说明 firewalld 没成功下发
  • 常见原因:rule 语法错误(比如漏写 family="ipv4")、zone 名拼错、或 firewall-cmd --reload 时因语法问题回滚了整个 zone 配置(此时 journalctl -u firewalld 里会有 “Failed to apply rules”)
  • 临时调试可手动加一条 nft rule 测试通路:nft add rule inet firewalld filter_INPUT ip saddr 192.168.1.100 accept,若通了,说明是 firewalld 解析或 zone 绑定问题

zone target 设置为 DROP 时 rich rule 可能被跳过

每个 zone 的 target 决定了默认策略。如果 zone 的 target 是 REJECTDROP(可通过 firewall-cmd --zone=xxx --get-target 查),那么 rich rule 必须显式 accept,且不能依赖“默认放行”。但更隐蔽的问题是:当 target = DROP 时,firewalld 会把所有非 rich rule 的流量直接丢弃,而 rich rule 若因语法/顺序/匹配失败没触发,结果就是全拒。

  • 建议调试期先设为 firewall-cmd --zone=xxx --set-target=ACCEPT,确认 rich rule 能触发后再调回严格模式
  • target=DEFAULT_DROP 是最严格的,它会让所有未显式 accept 的包走到最后一条 drop 规则;此时 rich rule 的位置无关紧要,但必须 100% 匹配条件
  • 注意:修改 target 后必须 --reload,仅 --runtime-to-permanent 不生效

真正卡住的地方往往不在 rule 本身,而在 zone 是否接管了流量、nftables 是否收到指令、以及 target 如何兜底。别急着改 rule 内容,先用 firewall-cmd --get-active-zonesnft list ruleset 对齐预期和现实。

text=ZqhQzanResources