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

firewalld 防火墙全面详解:从核心概念到高级实战

firewalld 是 RHEL、CentOS、Fedora 等发行版的默认防火墙管理工具,采用“区域(Zone)”模型替代传统的规则链堆叠,支持运行时与永久配置分离、富规则、策略对象等高级能力。它的核心价值在于:用“信任级别”抽象组织安全策略,让多网卡、多场景的防火墙管理更清晰、更不易出错。本文从核心概念、基础操作、高级功能到实战场景,系统梳理 firewalld 的完整用法。

一、firewalld 是什么

firewalld 是一个动态防火墙管理器,提供支持网络/防火墙区域的防火墙,用于定义网络连接或接口的信任级别。它支持 IPv4、IPv6、以太网桥和 IP sets,并且将运行时配置与永久配置分离。

与 iptables 最本质的区别在于:firewalld 引入了“区域(Zone)”这一层抽象。你不再直接面对裸的规则链,而是先把网卡或来源地址归属到某个信任级别的区域,区域内置的规则集合自动作用于该区域上的所有流量。

二、核心概念

2.1 区域(Zone)

区域是对网络“信任级别”的抽象。firewalld 自带多个预定义区域,从最保守到最开放依次为:

区域信任级别典型用途
drop最低(最安全)静默丢弃所有入站流量,不返回任何响应
block极低拒绝入站,但返回 ICMP 不可达响应
public默认公共网络,仅放行明确指定的服务
external较低路由器外部网络,启用地址伪装
dmz中等DMZ 区域服务器
work较高工作网络,信任同网段主机
home高家庭网络
internal高内部网络
trusted最高(最宽松)允许所有流量

Ubuntu 上 firewalld 的默认区域通常也是 public。未显式绑定到其他区域的网络接口,自动归入默认区域。

关键原则:区域越开放,越应该只用在可信网络接口上。一台机器同时有公网网卡和内网网卡时,应分别划到 public 和 trusted 两个区域。

2.2 运行时 vs 永久配置

firewalld 将配置分为两层:

  • 运行时配置:立即生效,但重启服务或系统后丢失。适合测试和临时调整。
  • 永久配置:写入磁盘,重启后依然存在。使用 --permanent 标志添加。

优先级上,运行时配置高于永久配置。执行 firewall-cmd --reload 后,永久配置会覆盖运行时中未保存为永久的修改。

实用技巧:如果在运行时测试了一条规则且运行正常,可以将其保存为永久配置:

sudo firewall-cmd --runtime-to-permanent

2.3 策略对象(Policy,firewalld 0.9+)

较新版本的 firewalld 引入了策略对象,用于描述区域之间、区域与出站流量之间的策略,比传统的 zone 更灵活。

策略对象允许你将 firewalld 的原语(如服务、端口和富规则)附加到策略,并以有状态和单向的方式应用到区域间传输的流量上。

符号区域 HOST 和 ANY 可用于 ingress/egress:

  • HOST:来自运行 firewalld 主机的流量,或到该主机的流量。
  • ANY:所有当前和将来的区域,充当通配符。

三、基础操作命令

3.1 启停与状态查看

# 启动并设为开机自启
sudo systemctl enable --now firewalld

# 查看运行状态
sudo systemctl status firewalld
sudo firewall-cmd --state

# 停止并禁用
sudo systemctl stop firewalld
sudo systemctl disable firewalld

3.2 区域管理

# 查看默认区域
sudo firewall-cmd --get-default-zone

# 设置默认区域(该更改总是永久的)
sudo firewall-cmd --set-default-zone=work

# 查看所有活跃区域及绑定的接口
sudo firewall-cmd --get-active-zones

# 查看指定区域的完整配置
sudo firewall-cmd --zone=public --list-all

# 列出所有区域的配置
sudo firewall-cmd --list-all-zones

# 将接口绑定到指定区域
sudo firewall-cmd --zone=trusted --change-interface=eth1
sudo firewall-cmd --reload

3.3 放行服务与端口

# 永久放行 HTTP 和 HTTPS(按服务名)
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload

# 查看预定义服务列表
sudo firewall-cmd --get-services

# 放行自定义端口(必须带协议类型)
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
sudo firewall-cmd --permanent --zone=public --add-port=51820/udp

# 放行端口范围
sudo firewall-cmd --permanent --zone=public --add-port=8080-8090/tcp
sudo firewall-cmd --reload

# 查看已放行的端口
sudo firewall-cmd --zone=public --list-ports

高频陷阱:--permanent 是必须的。不带 --permanent 的规则只在当前会话开放,机器重启或 firewalld 重启后就会丢失,这正是很多“端口明明加了却连不上”现象的根源。

3.4 移除规则

sudo firewall-cmd --permanent --zone=public --remove-service=http
sudo firewall-cmd --permanent --zone=public --remove-port=8080/tcp
sudo firewall-cmd --reload

3.5 重新加载

每次修改 --permanent 规则后,都必须执行 reload 才能生效:

sudo firewall-cmd --reload

reload 不会中断现有连接;--complete-reload 会完全重置(断开连接)。

四、高级功能

4.1 富规则(Rich Rules)

富规则是 firewalld 最强大的功能,用于表达服务/端口不足以描述的复杂防火墙规则。

基本语法:

rule [family="ipv4|ipv6"] [priority="priority"] [conditions] [actions]

限制来源访问特定端口:

sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  source address="10.0.0.0/8"
  port protocol="tcp" port="22" accept'

限制连接频率(防暴力破解):

sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  service name="ssh"
  limit value="3/m"
  accept'

记录并拒绝特定来源:

sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  source address="192.168.1.100"
  reject'

富规则的优先级:priority 参数范围是 -32768 到 32767,数值越低优先级越高。低于 0 的规则被重定向到带 _pre 后缀的链中,高于 0 的进入 _post 链,等于 0 的按操作进入 _log、_deny 或 _allow 链。

4.2 端口转发与 NAT

DNAT(目标地址转换)——将公网流量转发到内部服务器:

# 将公网 IP 192.0.2.1 的 443 端口转发到内网 192.51.100.20 的 443
sudo firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4"
  destination address="192.0.2.1"
  forward-port port="443" protocol="tcp" to-port="443" to-addr="192.51.100.20"'
sudo firewall-cmd --reload

启用 IP 伪装(SNAT 的必要条件):

sudo firewall-cmd --permanent --zone=public --add-masquerade
sudo firewall-cmd --reload

# 验证
sudo firewall-cmd --query-masquerade

端口转发依赖源地址转换,必须开启 masquerade,否则内网服务器响应包无法正确回传,造成单向通信失败。

4.3 策略对象(Policy)实战

使用策略对象过滤区域间流量,例如限制 Podman 容器到其他区域的访问:

# 创建新策略
sudo firewall-cmd --permanent --new-policy podmanToAny

# 默认拒绝,只放行必要服务
sudo firewall-cmd --permanent --policy podmanToAny --set-target REJECT
sudo firewall-cmd --permanent --policy podmanToAny --add-service dhcp
sudo firewall-cmd --permanent --policy podmanToAny --add-service dns
sudo firewall-cmd --permanent --policy podmanToAny --add-service https

# 定义 ingress 和 egress 区域
sudo firewall-cmd --permanent --policy podmanToAny --add-ingress-zone podman
sudo firewall-cmd --permanent --policy podmanToAny --add-egress-zone ANY

sudo firewall-cmd --reload

# 验证
sudo firewall-cmd --info-policy podmanToAny

策略的 target 可选值:ACCEPT、DROP、REJECT、CONTINUE(默认)。

4.4 IP sets(大量 IP 集合管理)

当需要封禁/放行成百上千个 IP 时,逐条富规则效率极低。firewalld 支持 ipset:

# 创建 IP 集合
sudo firewall-cmd --permanent --new-ipset=blocklist --type=hash:ip

# 添加条目
sudo firewall-cmd --permanent --ipset=blocklist --add-entry=1.2.3.4
sudo firewall-cmd --permanent --ipset=blocklist --add-entry=5.6.7.8

# 在富规则中引用
sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule source ipset="blocklist" drop'
sudo firewall-cmd --reload

五、与 Docker 的冲突处理

这是 Ubuntu 用户从 UFW 迁移到 firewalld 时最容易踩坑的地方。Docker 默认会自行写入 iptables 规则,可能绕过 firewalld 的区域规则。即使你没有在 firewalld 中放行某个端口,Docker 映射的端口仍然可能对外可达。

排查步骤:

# 检查 firewalld 状态
sudo systemctl status firewalld
sudo firewall-cmd --list-all

# 检查底层 iptables 规则
sudo iptables -L -n -v

处理方案:

  1. 调整启停顺序:systemctl restart firewalld → systemctl restart docker,让 Docker 重建规则链。
  2. 使用 host 网络模式:容器直接使用宿主网络,避免 bridge 与 iptables 交互。
  3. 修改 Docker 配置:在 /etc/docker/daemon.json 中设置 "iptables": false(需自行管理网络规则)。
  4. 为 Docker 创建专用 zone:绑定 docker0 接口,按需放行。

六、配置持久化与文件管理

firewalld 的所有永久配置存储在 /etc/firewalld/ 下:

  • zones/ — 区域配置(如 public.xml)
  • services/ — 自定义服务定义
  • ipsets/ — IP 集合
  • policies/ — 策略对象
  • direct.xml — direct 规则
  • firewalld.conf — 全局配置

在自动化运维(Ansible、SaltStack)中,直接管理这些 XML 文件往往比执行命令更可靠。

七、安全操作要点

  1. 不要同时运行多个防火墙管理工具。UFW、firewalld、iptables 同时运行会竞争对内核 Netfilter 的写权限,导致规则互相覆盖、端口状态不可预期。
  2. 远程操作前确保 SSH 可达。变更防火墙前,先确认新规则会放行 SSH,否则一旦网络断开将无法连接。
  3. 变更前备份规则: sudo firewall-cmd --runtime-to-permanent sudo cp /etc/firewalld/zones/public.xml ~/backup-public.xml
  4. 日志排查: sudo journalctl -u firewalld -f

八、总结

firewalld 的学习曲线比 UFW 陡,但它的核心价值在于区域模型提供的策略组织能力。理解以下三点,就能掌握 firewalld 的精髓:

  • 区域是信任级别的抽象:把网卡/来源归入合适的区域,比逐条写规则更清晰。
  • --permanent + --reload 是标准流程:养成习惯,避免规则丢失。
  • 富规则和策略对象是进阶关键:它们决定了你能否处理限速、区域间过滤、容器网络等复杂场景。

对于运行在 Ubuntu 上的服务,如果只做简单的端口放行,UFW 可能更直接。但如果你管理混合 Linux 环境、需要多网卡隔离、或者追求更精细的流量控制,firewalld 是更值得投入学习的选择。

作者

老丹

关注我
其他文章
上一个

firewalld 防火墙详解:以firewall-cmd –zone=public –list-all的输出为例

下一个

Ubuntu 服务器 UFW 防火墙排查实录:从一条备份命令到看清全部规则

关于博主

    老丹是一名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号