Firewalld 不允许多区域同时绑定同一接口,因每个接口只能属一个活跃zone;需通过source绑定实现逻辑隔离,并开启IP转发与正确配置rich rule、masquerade等才能生效。

Firewalld 的多区域策略不是“同时生效多个区域”,而是靠接口绑定 + 源地址匹配实现逻辑隔离;直接给同一接口分配多个区域会报错,必须用 rich rule 或 zone targeting 配合 source-based 规则。
为什么不能直接把一个网卡同时加到 public 和 internal 区域
Firewalld 要求每个网络接口(eth0、ens33 等)只能属于一个活跃 zone。执行 firewall-cmd --zone=internal --add-interface=eth0 后,eth0 会自动从原 zone(如 public)移出。强行重复添加会返回错误:ERROR: ZONE_ALREADY_SET: 'eth0' already bound to a zone。
真正需要的是:同一物理接口接入不同子网(如 192.168.10.0/24 和 192.168.20.0/24),让它们走不同策略 —— 这得靠 source 绑定而非接口绑定。
- 用
firewall-cmd --permanent --zone=internal --add-source=192.168.10.0/24把源网段绑定到internal区域 - 用
firewall-cmd --permanent --zone=public --add-source=192.168.20.0/24把另一网段绑定到public区域 - 确保这些
source规则优先级高于接口默认 zone(Firewalld 按 “source → interface → default” 顺序匹配)
如何用 rich rule 实现跨区域的精细控制(比如只允许 internal 用户访问数据库端口)
当 zone 级别策略不够细(例如 internal zone 默认放行所有服务,但你只想开放 3306 给特定 IP),就得在目标 zone 里加 rich rule。它比 zone-level 设置更优先,且支持源地址、端口、协议、日志等组合条件。
示例:只允许来自 192.168.10.100 的 TCP 请求访问本机 3306,并记录匹配日志:
firewall-cmd --permanent --zone=internal --add-rich-rule='rule family="ipv4" source address="192.168.10.100" port port="3306" protocol="tcp" accept log prefix="mysql-access" level="info'
- 注意
--zone=internal表示这条规则生效于internalzone 的上下文中,不是全局规则 - 如果该 IP 实际走的是
publiczone(比如没配source绑定),这条规则不会触发 —— rich rule 不跨 zone 生效 - 日志前缀
prefix="mysql-access"会出现在/var/log/messages或journalctl -u firewalld中,方便排查
多区域策略下最容易被忽略的路由与转发问题
Firewalld 默认关闭 IP 转发(net.ipv4.ip_forward=0),而跨子网流量隔离往往依赖主机做路由或 NAT。如果你绑定了两个 source 到不同 zone,但没打开转发,包会在内核层被丢弃,firewalld 根本收不到 —— 此时 firewall-cmd --list-all-zones 看起来一切正常,但实际不通。
- 先确认转发开启:
sysctl net.ipv4.ip_forward应返回1;否则运行echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p - 若涉及 SNAT/DNAT(如让 internal 用户通过本机访问外网),需在对应 zone 启用伪装:
firewall-cmd --permanent --zone=internal --add-masquerade - 检查
iptables -t nat -L POSTROUTING是否出现 masquerade 规则,避免只配 firewalld 却忘了底层 netfilter 生效条件
多区域本质是 source + interface + default 的三级匹配链,不是并行策略容器;真正复杂的地方在于,一旦引入 rich rule、masquerade、forward-port,就必须同步检查内核参数、路由表、以及 firewall-cmd --get-active-zones 输出中是否真有 source 条目 —— 很多人卡在“规则写了却没生效”,其实是 source 绑定失败或转发未开。


















