Firewalld 区域详解:从概念到实践
Firewalld 是 Linux 系统中一款动态防火墙管理工具,它替代了传统的 iptables 静态配置方式,广泛应用于 CentOS、RHEL、Fedora 以及 Ubuntu 等发行版。Firewalld 最核心的设计理念就是区域(Zone)。理解区域的概念,是掌握 Firewalld 配置的关键。
什么是区域
区域定义了网络连接的信任级别。这是一个抽象的管理层,让你不必为每张网卡手动编写繁琐的规则,而是通过将网络接口或来源地址分配到不同区域,来快速应用对应的安全策略。
在 firewalld 的语境里,“连接”(connection)指的是一个网络接口或一个来源地址与某个区域的绑定关系。它的来源有两种:
- 网络接口(interface):比如
enp1s0、eth0、docker0 - 来源地址(source):比如
192.168.1.0/24、10.0.0.5
所以“一个连接只能属于一个区域”准确的表述是:一个网络接口,或一个来源地址,只能被绑定到一个区域。但一个区域可以被多个连接共用。当你把某张网卡绑定到某个区域后,这个区域内配置的所有规则——预定义服务、端口、ICMP 阻断、伪装、富规则等——就会自动应用到该网卡上的流量。
每个区域内部可以包含以下配置项:
- 预定义服务:如
ssh、http、https,本质是端口和协议的组合 - 端口与协议:直接允许特定的 TCP/UDP 端口
- ICMP 阻断:选择性地屏蔽某些类型的 ICMP 报文
- 伪装(Masquerading):即源地址转换(NAT),用于将私有网络隐藏在公共 IP 后
- 富规则(Rich Rules):提供更精细的控制,可基于源/目的地址、日志、动作等进行复杂配置
区域的目标(Target)
每个区域还有一个“目标”设置,用来决定当流量不匹配区域内任何具体规则时,该怎么处理。这相当于区域的默认策略:
| 目标 | 行为 | 使用区域 |
|---|---|---|
| ACCEPT | 接受所有未明确禁止的传入包 | trusted |
| REJECT | 拒绝所有未明确允许的传入包,并通知来源 | block |
| DROP | 丢弃所有未明确允许的传入包,不通知来源 | drop |
| default | 与 REJECT 类似,但具有特殊含义 | 大多数预定义区域(如 public) |
如果目标未指定,所有不匹配任何规则的包都会被拒绝。
预定义区域的详细特性
Firewalld 预置了多个区域,官方文档按信任程度从低到高进行了排序。下面逐一详细说明每个区域的特性。
drop
信任级别最低。任何传入的网络数据包都会被静默丢弃,不返回任何响应,发送方无法得知数据包被拦截,只会一直等待直至超时。
唯一允许的是出站连接:只有系统主动发起的网络连接才可能正常工作。这个区域适合用在完全不可信的网络环境,或者你想对外部探测保持“隐身”状态的场景。
block
信任级别同样很低,但与 drop 有一个关键区别:传入连接会被拒绝并返回 ICMP 错误消息——IPv4 返回 icmp-host-prohibited,IPv6 返回 icmp6-adm-prohibited。外部主机能明确知道“连接被禁止了”。
和 drop 一样,只有系统主动发起的出站连接才被允许。适合用在你希望明确拒绝连接、但不介意暴露主机存在的场景。
public
默认区域,用于公共场所(如咖啡馆、机场 WiFi)。设计前提是:你不信任网络上的其他计算机,认为它们可能对你的系统构成威胁。
行为上:只接受明确选择的传入连接。在干净安装的情况下,它通常只预置了 ssh、dhcpv6-client 等少数服务。如果你需要开放其他端口或服务,必须手动添加。
external
用于外部网络,特别是启用了 IPv4 伪装(masquerading)的路由器场景。信任级别与 public 类似——不信任网络上的其他计算机,只接受选中的连接。
它的独特之处在于默认启用 masquerade(NAT),将内部私有地址隐藏在公共 IP 之后。如果你把这台机器当作网关或 NAT 设备使用,external 比 public 更合适。
dmz
用于隔离区(Demilitarized Zone) 中的计算机。这些机器对外可以公开访问(例如运行公开的 Web 服务),但对内部网络的访问受到严格限制。
信任级别介于 public 和 work 之间。设计思路是:即使 DMZ 中的机器被攻破,攻击者也无法轻易横向移动到内网。适合同一网段中既有对外服务、又需要与内网保持隔离的服务器。
work
用于工作区域。设计前提是:你基本信任网络上的其他计算机。与 home 和 internal 的定位相似,区别仅在于使用场景的语义。
通常预置了 ssh、dhcpv6-client 等服务。适合公司办公室等你愿意给予一定信任、但仍需基本防护的网络。
home
用于家庭区域。同样基于基本信任其他计算机的前提。预置服务通常包括 ssh、mdns、samba-client 等家庭网络常用的协作服务。
适合有线家庭网络等环境:你相对信任网络中的设备,愿意让它们访问一些共享服务,但不需要像 trusted 那样完全敞开。
internal
用于内部网络。信任级别与 work/home 相同:基本信任网络上的其他计算机。语义上用于组织内部的可信网络,例如企业内网。
功能上与 home、work 高度重叠,选择哪个主要取决于命名习惯和使用场景。
trusted
信任级别最高。接受所有网络连接,不做任何过滤。等同于关闭了防火墙对流入流量的拦截。
只应用在完全可信、物理隔离或专用测试网络中。日常生产环境应避免将面向外部的接口绑定到此区域。
流量归属区域的三级匹配机制
当数据包到达时,firewalld 需要判断它属于哪个区域。这个判断过程遵循一个明确的三级优先链:
来源地址(source)> 接口(interface)> 默认区域
具体来说:
- 首先检查来源地址:如果数据包的源 IP 匹配某个区域配置的 source,则该数据包归入该区域处理。源地址的匹配优先于接口匹配——也就是说,如果某个源地址被显式绑定到了某个区域,来自它的流量会优先按该区域的规则处理,无论它从哪张网卡进入。
- 其次检查接口:如果没有匹配的 source,则检查数据包从哪张网卡进入。该网卡绑定的区域即为该数据包所属的区域。接口区域是未匹配任何 source 的流量的“兜底”。
- 最后是默认区域:如果接口也没有绑定区域(或该接口不属于任何活跃区域),则使用系统默认区域(通常是
public)。
这意味着:一个数据包最终只会属于一个区域,该区域的规则决定它的命运。
接口绑定与来源绑定:两种分区方式
将流量划入区域有两种手段,用途不同。
按接口绑定
firewall-cmd --zone=public --add-interface=enp1s0
这表示来自该网卡的所有流量都按 public 区域的规则处理。适合按物理或虚拟网卡来划分安全边界:公网口用严格策略,内网口用宽松策略。
一个接口只能属于一个区域。如果你尝试把同一个接口加到两个区域,firewalld 会报错,并自动把它从原区域移出。
按来源绑定
firewall-cmd --zone=trusted --add-source=192.168.1.0/24
这条命令的意思是:凡是源 IP 属于 192.168.1.0/24 这个网段的流量,无论从哪张网卡进来,都按 trusted 区域的规则处理。
来源地址的匹配与从哪个网口进入无关。这是一个全局性的绑定——只要源地址匹配,firewalld 就不关心它是从 enp1s0、eth1 还是 docker0 进来的。
这带来一个需要警惕的后果:信任范围可能被意外放大。如果这台机器有多个网口且网络拓扑复杂,理论上存在路径让外部流量伪装成受信任的源网段从“错误”的接口进入。务必确认路由和网络环境没有意外的入口。
两者共存时的行为
假设 enp1s0 绑定在 public,同时你添加了 192.168.1.0/24 → trusted:
- 来自
192.168.1.0/24的流量,即使从enp1s0进来 → 走 trusted 规则(source 优先) - 来自其他网段的流量,从
enp1s0进来 → 走 public 规则(接口兜底)
来源地址匹配的优先级高于接口匹配。这也是 firewalld 实现“同一物理接口接入不同子网、走不同策略”的方式——你无法把同一接口绑定到两个区域,但可以通过 source 绑定实现逻辑上的多区域隔离。
同一接口的多区域需求
一个常见场景:服务器只有一张网卡,但希望来自 192.168.10.0/24 的流量走 internal 策略,来自 192.168.20.0/24 的流量走 public 策略。
这不能通过接口绑定实现——一张网卡只能属于一个活跃区域。正确的做法是使用 source 绑定:
firewall-cmd --permanent --zone=internal --add-source=192.168.10.0/24
firewall-cmd --permanent --zone=public --add-source=192.168.20.0/24
然后确保该接口本身绑定到一个合理的默认区域(比如 public),作为不匹配任何 source 的流量的兜底。
区域与策略(Policy)
Firewalld 0.9.0 及以上版本引入了策略(Policy) 概念,用于精细控制区域之间的流量。这是区域机制的重要补充。
区域内的默认行为
在同一个区域内部,流量转发默认是允许的(--remove-forward 可配置)。而区域之间的流量默认是拒绝的。
策略的作用
策略与入口区域(ingress zone) 和出口区域(egress zone) 关联,用于定义跨区域的转发规则。例如,你可以创建一条策略,允许从 internal 区域进入、转发到 external 区域出去的流量。
策略的优先级
多条策略可以作用于同一组流量,因此需要优先级来排序。数值越小,优先级越高,越先执行。例如 -500 会比 -100 先执行。
富规则与区域的关系
富规则(rich rule)不跨区域生效。你在 --zone=internal 下添加的富规则,只在该区域上下文中生效。如果某个 IP 实际走的是 public 区域(因为没有配置 source 绑定),internal 中的富规则对它无效。
富规则内部有自己的优先级机制:负优先级的富规则在标准服务之前执行,正优先级的在标准服务之后执行。
你环境中的特殊区域
在你之前的 --list-all-zones 输出中,有两个区域比较特殊,值得单独说明。
docker (active)
这不是 firewalld 预置的区域。当你运行 Docker(版本 20.10.0 或更高,且系统由 firewalld 管理)时,Docker 会通过 D-Bus 与 firewalld 通信,自动创建 docker 区域并将其管理的网桥(如 docker0、br-xxxx)动态加入其中。
你看到它的 target: ACCEPT 正是为了配合 Docker 的转发逻辑——容器需要能够自由地与外部通信,实现 Docker 的端口映射等网络功能。如果你希望由 firewalld 严格管控容器流量(而不是依赖 Docker 自行放行),需要先禁用 Docker 的 iptables 管理,然后通过 firewalld 的 policy 机制来配置容器的入站和出站规则。
nm-shared
这是 NetworkManager 为了“连接共享”功能自动创建的辅助区域。当你使用 NetworkManager 的共享连接(例如把笔记本变成热点让其他设备上网)时,NetworkManager 会将相关接口放入这个区域。
它的策略是:严格阻断外部对你这台本机的直接访问(仅放行 DHCP、DNS、ICMP 等基础协议),但放行所有转发流量,以便其他设备能通过你的电脑上网。你看到的那条 rule priority="32767" reject 就是它用来实现“阻断本机访问”的兜底规则,不建议删除,删了可能影响共享热点功能。
如何选择合适的区域
选择区域的原则是:区域越开放,越应该只用在可信网络接口上。
一个典型的场景是:一台机器同时有公网网卡和内网网卡。你应该把它们分别划到 public 和 trusted 两个区域,而不是共用一个宽松策略。这样,来自公网的流量受严格约束,而来自内网的流量则享有更高的信任。
对于公共 WiFi 连接,选择 public;对于有线的家庭网络,home 或 internal 更合适;对于完全可信的测试网络,才使用 trusted。
对于只有一张网卡但需要区分不同来源流量的场景,使用 source 绑定在逻辑上实现多区域隔离。
区域配置的核心命令
# 查看当前默认区域
firewall-cmd --get-default-zone
# 查看所有活跃区域及绑定的接口和来源
firewall-cmd --get-active-zones
# 查看指定区域的详细配置
firewall-cmd --info-zone=public
# 将接口绑定到指定区域
firewall-cmd --zone=trusted --add-interface=eth1
# 将来源网段绑定到指定区域
firewall-cmd --zone=internal --add-source=192.168.10.0/24
# 永久生效需加 --permanent 后 reload
firewall-cmd --permanent --zone=trusted --add-interface=eth1
firewall-cmd --reload
需要特别注意 --permanent 选项。如果不加,配置只在当前会话有效,机器重启或 firewalld 重启后就会丢失,这正是很多“端口明明加了却连不上”现象的根源。
容易被忽略的细节
- 转发与 NAT 的前提:如果你配置了多区域和 source 绑定,但需要流量跨子网转发或做 NAT,必须确保
net.ipv4.ip_forward=1。Firewalld 默认关闭 IP 转发,包会在内核层被丢弃,firewalld 根本收不到。 - 重叠的 source 范围:如果你添加了多个带有重叠网络范围的区域,firewalld 会按区域名称的字母顺序排序,只考虑第一个区域。
- 所有区域配置都是持久的:即使某个区域当前不活跃,它的配置也会被保留,可以随时被激活使用。
- 删除 source 后的行为:当你从某个区域删除一个 source 时,来自该源的流量不再走该区域的规则,而是回退到接口关联的区域或默认区域。
总结
Firewalld 的区域机制,本质上是对网络信任级别的分层管理。它把复杂的 iptables 规则抽象成了一套可复用的策略模板,让你通过“把接口或来源放进哪个区域”这一简单操作,就能实现差异化的安全控制。
核心要点:
- 一个连接(接口或来源)只能属于一个区域,但一个区域可以服务多个连接
- 流量归属遵循“source > interface > default”的三级优先链
- source 绑定与网口无关,来自该网段的流量从任意接口进入都走同一区域
- 同一接口无法绑定多个区域,多策略需求通过 source 绑定实现
- 区域间的默认行为是拒绝,跨区域转发需要显式配置 policy
- 富规则不跨区域生效,必须在目标区域上下文中配置
理解每个区域的信任定位、流量归属机制以及 source 与 interface 的区别,是正确配置 firewalld 的前提。