firewalld规则不生效的四大根源:服务假运行(进程在但规则未加载)、运行时与永久配置不一致、网卡未正确绑定zone、外部干扰(如docker直写iptables或selinux拦截)。

Firewalld规则不生效,往往不是命令没输对,而是配置、状态、依赖或外部干扰在“悄悄作祟”。真正的问题常藏在看似正常的表象之下——服务显示运行中、命令执行无报错、端口也加进去了,但就是不通。下面这四类排查方向,覆盖了生产环境中最常见、最易被忽略的失效根源。
确认 firewalld 是否真正在工作
别只信 systemctl status firewalld 的 “active (running)” —— 它可能只是进程在,规则根本没加载。
- 执行
firewall-cmd --state,返回running才算基础通过;若返回not running,说明服务已退场 - 再跑
firewall-cmd --list-all:如果只显示空 zone(如ports:、services:全为空),大概率是规则未加载或被清空 - 检查 journal 日志末尾是否有
Failed to initialize nftables backend或Connection refused类错误,这类报错常被滚动日志淹没,需加-n 20查看最新行
验证规则是否落到运行时且持久化正确
加了规则 ≠ 规则生效。firewalld 分“运行时”和“永久配置”两层,漏掉任一环节都会导致重启丢失或当前不生效。
- 查运行时开放的端口:
firewall-cmd --list-ports - 查永久配置里的端口:
firewall-cmd --permanent --list-ports - 两者不一致?说明你忘了加
--permanent,或者加了但没执行--reload - rich rule 或 service 类规则也要分别用
--list-rich-rules和--list-services对比运行时与永久配置
检查区域(zone)绑定与网络接口归属
firewalld 是按 zone 管理流量的,而 zone 要靠 interface 或 source 绑定才起作用。很多故障源于“规则加对了 zone,但流量根本没走那个 zone”。
- 运行
firewall-cmd --get-active-zones,确认你的网卡(如 eth0)确实在你配置的 zone(如 public)里 - 若输出为空,说明没有 interface 被自动归入任何 zone,需手动绑定:
firewall-cmd --zone=public --add-interface=eth0 --permanent,再 reload - 默认 zone 不代表所有流量都走它——只有未显式绑定的 interface 才 fallback 到默认 zone,这点极易误判
排查外部冲突与底层干扰
firewalld 不是孤立存在的。Docker、iptables 直接操作、SELinux、甚至 NetworkManager 都可能绕过或破坏它的规则。
- Docker 默认会直接写 iptables FORWARD 链,firewalld 重启时可能删掉这些规则,反过来也会让 firewalld 的策略对容器端口“视而不见”;可查
iptables -t filter -L FORWARD是否存在 docker 插入的 ACCEPT 规则 - 执行
iptables -L INPUT和nft list chain inet firewalld filter_INPUT(视后端而定),确认底层链是否真有对应规则 - SELinux 若启用且策略收紧,可能拦截连接本身,与防火墙无关;临时设为 permissive 模式测试:
setenforce 0 - 宝塔等面板会周期性扫描端口监听状态,若
ss -tlnp | grep :端口号无输出,它可能自动撤回放行规则











