跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

Firewalld 区域详解:从概念到实践

Firewalld 是 Linux 系统中一款动态防火墙管理工具,它替代了传统的 iptables 静态配置方式,广泛应用于 CentOS、RHEL、Fedora 以及 Ubuntu 等发行版。Firewalld 最核心的设计理念就是区域(Zone)。理解区域的概念,是掌握 Firewalld 配置的关键。

什么是区域

区域定义了网络连接的信任级别。这是一个抽象的管理层,让你不必为每张网卡手动编写繁琐的规则,而是通过将网络接口或来源地址分配到不同区域,来快速应用对应的安全策略。

在 firewalld 的语境里,“连接”(connection)指的是一个网络接口或一个来源地址与某个区域的绑定关系。它的来源有两种:

  1. 网络接口(interface):比如 enp1s0、eth0、docker0
  2. 来源地址(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)> 默认区域

具体来说:

  1. 首先检查来源地址:如果数据包的源 IP 匹配某个区域配置的 source,则该数据包归入该区域处理。源地址的匹配优先于接口匹配——也就是说,如果某个源地址被显式绑定到了某个区域,来自它的流量会优先按该区域的规则处理,无论它从哪张网卡进入。
  2. 其次检查接口:如果没有匹配的 source,则检查数据包从哪张网卡进入。该网卡绑定的区域即为该数据包所属的区域。接口区域是未匹配任何 source 的流量的“兜底”。
  3. 最后是默认区域:如果接口也没有绑定区域(或该接口不属于任何活跃区域),则使用系统默认区域(通常是 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 重启后就会丢失,这正是很多“端口明明加了却连不上”现象的根源。

容易被忽略的细节

  1. 转发与 NAT 的前提:如果你配置了多区域和 source 绑定,但需要流量跨子网转发或做 NAT,必须确保 net.ipv4.ip_forward=1。Firewalld 默认关闭 IP 转发,包会在内核层被丢弃,firewalld 根本收不到。
  2. 重叠的 source 范围:如果你添加了多个带有重叠网络范围的区域,firewalld 会按区域名称的字母顺序排序,只考虑第一个区域。
  3. 所有区域配置都是持久的:即使某个区域当前不活跃,它的配置也会被保留,可以随时被激活使用。
  4. 删除 source 后的行为:当你从某个区域删除一个 source 时,来自该源的流量不再走该区域的规则,而是回退到接口关联的区域或默认区域。

总结

Firewalld 的区域机制,本质上是对网络信任级别的分层管理。它把复杂的 iptables 规则抽象成了一套可复用的策略模板,让你通过“把接口或来源放进哪个区域”这一简单操作,就能实现差异化的安全控制。

核心要点:

  • 一个连接(接口或来源)只能属于一个区域,但一个区域可以服务多个连接
  • 流量归属遵循“source > interface > default”的三级优先链
  • source 绑定与网口无关,来自该网段的流量从任意接口进入都走同一区域
  • 同一接口无法绑定多个区域,多策略需求通过 source 绑定实现
  • 区域间的默认行为是拒绝,跨区域转发需要显式配置 policy
  • 富规则不跨区域生效,必须在目标区域上下文中配置

理解每个区域的信任定位、流量归属机制以及 source 与 interface 的区别,是正确配置 firewalld 的前提。

作者

老丹

关注我
其他文章
上一个

在 Ubuntu 上用 Docker Compose 手动搭建 Nextcloud:从基础到扩展的完整指南

下一个

Performance Co-Pilot (PCP) 深度详解

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • 在 Windows 里养一只 Linux:WSL 完整指南 2026年10月24日
  • Paho MQTT C 与 C++ 客户端库完全指南:从概念到 Ubuntu 26.04 下的编译、安装与使用 2026年10月23日
  • Mosquitto $SYS 主题详解:Broker 自监控指南 2026年10月23日
  • 应用级 MQTT 服务搭建完全指南:Mosquitto + 宿主机 Nginx 2026年10月22日
  • OpenWrt 固件签名三剑客:usign、ucert 与 fwtool 深度解析 2026年10月21日

文章分类

  • C/C++开发 (22)
  • Docker容器 (5)
  • Linux工具包 (21)
  • Linux服务配置 (53)
  • Linux系统 (16)
  • MQTT技术 (6)
  • OpenWrt路由 (5)
  • Shell脚本 (3)
  • 代码管理 (1)
  • 安防技术 (4)
  • 数据安全 (36)
  • 网络协议 (25)
  • 计算机理论 (23)
  • 问题解决 (3)
  • 防火墙 (6)
  • 音视频技术 (6)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号