firewalld规则未生效主因是未永久保存或未重载、zone不匹配、rich rule语法错误、服务名未定义;须用--permanent加规则并执行--reload,确认活跃zone一致,rich rule严格校验语法,自定义service需放/etc/firewalld/services/并重载。

firewalld 规则添加后看似执行成功,但外部始终连不上,大概率不是服务没起、也不是网络不通,而是规则根本没真正加载进运行时——常见于“只加了临时规则却忘了重载”,或“加到了错误 zone”,又或者“语法有硬伤导致 reload 时被静默跳过”。
确认规则是否已永久保存并重载
firewalld 的规则分“运行时”和“永久配置”两套。只用 firewall-cmd --add-port=8080/tcp 这类命令,规则只存在内存中,firewall-cmd --reload 或重启后立刻消失。
- 添加规则时必须带上 --permanent 参数,例如:
firewall-cmd --permanent --add-port=8080/tcp - 执行 firewall-cmd --reload 才会把永久配置刷入当前运行环境
- 验证是否生效:运行 firewall-cmd --list-ports(看端口)或 firewall-cmd --list-all(看完整配置),确认输出里包含你刚加的项
检查活跃 zone 是否与规则所在 zone 一致
firewalld 按 zone 管理规则,默认 zone 是 public,但你的网卡可能绑定在 internal、docker 或 custom zone 上。规则加在 public,而流量走的是 docker zone,自然不生效。
- 查当前活跃 zone:firewall-cmd --get-active-zones
- 查默认 zone:firewall-cmd --get-default-zone
- 加规则时显式指定 zone,例如:
firewall-cmd --permanent --zone=docker --add-port=3306/tcp - 确保网卡已正确绑定到目标 zone:firewall-cmd --zone=docker --add-interface=docker0
排查富规则(rich rule)语法错误
富规则对格式极其敏感,漏引号、错顺序、少关键字都会导致 --reload 时解析失败,整条规则被跳过,且无报错提示。
- 正确写法示例:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="22" protocol="tcp" accept' - 常见错误:
• 把 source 和 port 位置颠倒
• 写成 protocol="tcp" 却漏掉 port 子项
• 引号不匹配或用了中文引号
• 忘记写 accept 动作 - 调试建议:先用 --query-rich-rule=... 检查是否存在;再用 --remove-rich-rule=... 清除后重试
验证服务名是否真实可用
用 --add-service=http 可以,但 --add-service=myapp 若未提前定义 service 文件,则命令虽返回 success,实际不生效。
- 列出所有已知服务:firewall-cmd --get-services
- 查看某服务具体内容:cat /usr/lib/firewalld/services/http.xml
- 自定义服务需放入 /etc/firewalld/services/ 目录,文件名须为 xxx.xml,且格式合法
- 添加后必须 firewall-cmd --reload 才能识别新 service










