firewalld不支持zone嵌套,一个接口只能绑定一个zone;跨zone流量控制需通过source绑定、rich rule、masquerade和forward-port组合实现,并遵循source→interface→default zone匹配顺序。

firewalld 本身不支持“zone 嵌套”——区域之间不能层层包含或继承,也没有 parent-child zone 的概念。所谓“多 zone 区域的嵌套转发”,实际是误用术语;真正可行且常用的是基于源地址(source)+ 接口(interface)+ rich rule + masquerade/forward-port 的组合策略,实现跨子网、跨信任级别的流量路由与控制。
明确 zone 绑定的基本限制
一个物理接口(如 eth0)只能属于一个活跃 zone,这是 firewalld 的硬性约束。执行 firewall-cmd --zone=internal --add-interface=eth0 后,eth0 会自动脱离原 zone(比如 public)。试图重复绑定会报错:ERROR: ZONE_ALREADY_SET。所以“嵌套”不是靠接口叠加,而是靠流量来源识别来分流。
- 接口绑定决定默认策略:eth0 属于 public → 所有未匹配 source 的入向流量走 public 规则
- source 绑定优先级更高:添加
--add-source=192.168.10.0/24到 internal zone 后,该网段所有流量按 internal 策略处理 - 匹配顺序固定为:source → interface → default zone
实现跨 zone 流量转发的三步关键操作
例如:内网 192.168.10.0/24(internal)需访问 DMZ 区 192.168.20.100:80(dmz),但不允许反向访问;同时主机需做 NAT 转发。
-
启用 IP 转发:编辑
/etc/sysctl.conf,设net.ipv4.ip_forward = 1,运行sysctl -p -
在 source 所属 zone 开启 masquerade:比如 internal zone 需出向 NAT,执行
firewall-cmd --permanent --zone=internal --add-masquerade -
在目标 zone 配置端口转发:对 dmz zone 添加规则,将进来的 80 端口转给后端服务器:
firewall-cmd --permanent --zone=dmz --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.20.100
用 rich rule 控制跨 zone 访问权限
当需要精细控制“谁能在哪个 zone 下访问什么”,rich rule 是唯一可靠方式。它只在指定 zone 内生效,且优先级高于 zone 级服务配置。
- 只允许 internal zone 中的 192.168.10.50 访问本机 3306:
firewall-cmd --permanent --zone=internal --add-rich-rule='rule family="ipv4" source address="192.168.10.50" port port="3306" protocol="tcp" accept' - 拒绝 public zone 中某 IP 访问所有服务:
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.99" reject' - 注意:该规则是否触发,取决于流量是否被判定归属到对应 zone(靠 source 或 interface 绑定决定)
验证与调试要点
多 zone 转发失败,90% 出在底层链路而非 firewalld 配置本身。
- 确认
firewall-cmd --get-active-zones显示 source 和 interface 绑定正确 - 检查
firewall-cmd --zone=xxx --list-all是否已启用masquerade和forward-ports - 用
tcpdump -i eth0 host 192.168.10.50查看原始包是否到达,再用journalctl -u firewalld | grep mysql-access查日志 - 临时关闭 SELinux 或调整其策略(
setsebool -P firewall_enable_icmp true)可排除干扰











