firewalld规则需先--permanent再--reload才生效:--permanent仅写入配置文件,--reload才加载到运行时;Docker默认绕过firewalld,需禁用其iptables管理并手动配置masquerade。

firewall-cmd --permanent 之后没 reload,规则就只是“写进硬盘”
这是最常见、也最容易被忽略的失效原因:你执行了 firewall-cmd --permanent --add-port=8080/tcp,终端返回 success,但立刻 telnet 测试失败,reboot 后依然不通。不是命令没跑完,而是规则只落盘到 /etc/firewalld/zones/public.xml,根本没加载进当前运行的 firewalld 实例。
firewalld 的 runtime 和 permanent 是两套状态,--permanent 不会自动同步过去;--reload 才是那个“把磁盘配置全量覆盖 runtime”的关键动作。
- ✅ 正确流程必须是两步:先
firewall-cmd --permanent --add-port=8080/tcp,再firewall-cmd --reload - ⚠️
--reload不中断已有连接,比systemctl restart firewalld更安全 - ? 建议在
~/.bashrc里加个函数:fwadd() { firewall-cmd --permanent "$@" && firewall-cmd --reload; },以后直接fwadd --add-port=8080/tcp
Docker 启动时自动绕过 firewalld
如果你在宿主机上跑 docker run -p 8080:80,firewalld 规则大概率无效——因为 Docker 默认会直接往 iptables 的 DOCKER-USER 链里插一条 ACCEPT 规则,优先级高于 firewalld 管理的链,相当于在防火墙上凿了个洞。
- ✅ 解法是禁止 Docker 操作 iptables:编辑
/usr/lib/systemd/system/docker.service,在ExecStart行末尾加--iptables=false - ? 执行
systemctl daemon-reload && systemctl restart docker - ⚠️ 注意副作用:容器默认无法访问外网,需手动开启 masquerade:
firewall-cmd --permanent --zone=public --add-masquerade && firewall-cmd --reload - ? 验证是否生效:
iptables -t nat -L DOCKER-USER -n应为空(或只有你手动加的规则)
firewalld 服务本身没活过来
规则再对,服务没起来也是白搭。很多 reboot 失效,其实压根不是规则问题,而是 firewalld 根本没自启,或者启动失败后静默退出。
- ? 先查状态:
systemctl is-active firewalld(应为active),systemctl is-enabled firewalld(应为enabled) - ? 若 disabled:运行
systemctl enable firewalld;若 inactive:运行systemctl start firewalld - ❗ 别只信
systemctl status firewalld的 “running”,要看日志:journalctl -u firewalld --since "1 hour ago" | grep -i error - ? 注意冲突:如果
iptables-services(传统 iptables)也在运行,它会覆盖 firewalld 规则,务必systemctl disable iptables
规则看似加了,实际没进 permanent 配置文件
有时候你反复 --permanent + --reload,但 reboot 后还是丢,可能是因为规则压根没写进 XML 文件——比如 zone 被改错、XML 格式损坏、或被 Ansible/Salt 等工具覆盖重置。
- ? 对比验证:
firewall-cmd --list-all --permanent输出是否含你加的端口/服务? - ? 直接检查文件:
grep -A2 8080 /etc/firewalld/zones/public.xml,确认内容存在且闭合标签正确 - ⚡ 模拟 reboot 效果:
systemctl restart firewalld && firewall-cmd --list-all,这个输出应和--permanent版本一致 - ⚠️ IPv6 容易漏:firewalld 默认不管理 IPv6,若业务走 IPv6,得显式加
--ipv6参数,例如:firewall-cmd --permanent --add-port=8080/tcp --ipv6
真正麻烦的从来不是加一条规则,而是搞清哪一层断了:是 service 没跑、是 reload 没做、是 Docker 插队、还是 XML 被悄悄抹掉。每次怀疑规则失效,先分层验证——从服务状态、到 permanent 配置、再到 runtime 状态,一层一层往下扒,比重试十遍更省时间。










