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

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

本文以一台 Ubuntu 服务器上 firewall-cmd --zone=public --list-all 的实际输出为线索,逐行拆解 firewalld 的每一项配置,并穿插介绍其背后的概念、机制和常用操作。这样既能理解命令输出,也能掌握 firewalld 的整体工作方式。

先看我们的原始输出:

richard@ubuphy001:~$ sudo firewall-cmd --zone=public --list-all
public (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp1s0
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

下面我们逐行分析,并在每一部分展开相关背景知识。

一、命令与输出结构

1.1 命令的含义

sudo firewall-cmd --zone=public --list-all
  • firewall-cmd:firewalld 的命令行客户端,用来查询和修改防火墙配置
  • --zone=public:指定要操作/查看的区域为 public
  • --list-all:列出该区域当前运行时的全部配置
  • sudo:修改防火墙需要 root 权限,虽然查询有时普通用户也能执行,但加上 sudo 更稳妥

如果加上 --permanent,则会显示永久配置而非运行时配置:

sudo firewall-cmd --zone=public --list-all --permanent

1.2 输出的整体结构

第一行 public (default, active) 是区域的“状态头”,包含三个信息:

  • public:区域名称
  • default:这是系统默认区域(--get-default-zone 会返回 public)
  • active:该区域当前处于激活状态,即有网络接口绑定在它上面

我们这台机器的默认区域是 public,而且 enp1s0 网卡正绑定在它上面,所以它是 active。

二、逐项拆解所输出的配置

2.1 target: default

target: default

含义:该区域对未匹配任何允许规则的入站数据包的最终处理方式。

本例解读:default 意味着——所有没有被 services、ports、rich rules 等明确放行的入站流量,都会被拒绝(REJECT) 。注意,名字叫“default”,但它的行为并不是“允许”,而是“默认拒绝”。

背景知识:target 的可选值有:

值行为
default拒绝未匹配的包(发送拒绝响应)
ACCEPT接受所有未匹配的包(trusted 区域用)
%%REJECT%%以 firewalld 默认方式拒绝(block 区域用)
DROP静默丢弃,不发送任何响应(drop 区域用)

可以用以下命令修改区域的 target:

sudo firewall-cmd --permanent --zone=public --set-target=DROP
sudo firewall-cmd --reload

关键点:真正决定“放行什么”的,是 services、ports、rich rules 里明确列出的内容;target 只决定“其余怎么办”。

2.2 ingress-priority: 0 / egress-priority: 0

ingress-priority: 0
egress-priority: 0

含义:入站和出站数据包在本区域的处理优先级。

本例解读:都是 0,即普通优先级。数字越小越优先处理。

背景知识:优先级主要用于多个区域可能同时匹配一个包时(比如同时绑定了接口和源地址),决定哪个区域先被应用。一般默认 0 即可。

2.3 icmp-block-inversion: no

icmp-block-inversion: no

含义:ICMP 拦截的“反转开关”。

本例解读:no 表示正常模式——icmp-blocks 里列出的 ICMP 类型会被禁止。由于我们的 icmp-blocks 是空的,所以没有禁止任何 ICMP,包括 ping。

背景知识:如果设为 yes,则规则反转——icmp-blocks 列表里的类型反而被允许,其余全部拦截。这提供了一种 ICMP 白名单机制。

验证方法:从另一台机器 ping 这台服务器,应该是通的:

ping ubuphy001

如果想禁用 ping:

sudo firewall-cmd --zone=public --add-icmp-block=echo-request --permanent
sudo firewall-cmd --reload

2.4 interfaces: enp1s0

interfaces: enp1s0

含义:绑定到 public 区域的网络接口。

本例解读:enp1s0 是这台机器的主要网卡,它上面的入站流量全部套用 public 区域的规则。所以“默认拒绝、只放行 ssh 和 dhcpv6-client”这些规则,正是作用于这块网卡的。

背景知识:可以用命令查看接口和区域的绑定关系:

sudo firewall-cmd --get-active-zones

输出类似:

public
  interfaces: enp1s0

也可以手动把接口移到别的区域:

sudo firewall-cmd --zone=trusted --change-interface=enp1s0 --permanent
sudo firewall-cmd --reload

2.5 sources: (空)

sources:

含义:按源 IP 地址/网段匹配该区域。

本例解读:为空,表示这个区域的匹配只靠网卡(enp1s0),不依赖源地址。任何从 enp1s0 进来的流量都会套用 public 区域规则,无论来源 IP 是什么。

背景知识:source 常用于“对特定来源的机器给予不同信任级别”。例如把某台内网机器划到 trusted:

sudo firewall-cmd --permanent --zone=trusted --add-source=192.168.1.100
sudo firewall-cmd --reload

这样来自 192.168.1.100 的流量就直接享受 trusted 区域的宽松规则,而不用改网卡。

2.6 services: dhcpv6-client ssh

services: dhcpv6-client ssh

含义:允许入站的预定义服务。这是本配置中真正放行流量的核心项。

本例解读:只放行两个服务:

  • ssh → TCP 22 端口,允许远程登录管理
  • dhcpv6-client → 允许本机作为 IPv6 DHCP 客户端收发 DHCPv6 报文

除这两个服务(以及后续会看到的 ports/rich rules,都是空的)之外的入站流量,都会被 target=default 拒绝。

背景知识:服务是“端口 + 协议”的预定义组合,比直接写端口更清晰。可以查看某个服务的定义:

sudo firewall-cmd --info-service=ssh

输出会显示 ports: 22/tcp 等细节。也可以列出所有预定义服务:

sudo firewall-cmd --get-services

注意:dhcpv6-client 和 ssh 是 firewalld 默认区域里通常会预置的服务,所以这个配置基本是“开箱默认”状态。

SSH 的重要性:因为我们只放行了 ssh,所以远程登录不受影响;如果哪天误删了 ssh 服务又 reload,可能立刻失去远程连接(除非有带外管理)。修改 SSH 相关规则时要格外小心。

2.7 ports: (空)

ports:

含义:直接放行的端口(如 8080/tcp)。

本例解读:为空,表示没有额外开放任何端口。也就是说,除了 ssh(22) 和 dhcpv6 涉及的端口外,本机不对外提供其他服务。

背景知识:当服务预定义不满足需求时(比如跑了一个 Web 服务在 8080),就用 ports:

sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload

支持单个端口和端口范围:

sudo firewall-cmd --add-port=5060-5062/udp --permanent

查看已放行端口:

sudo firewall-cmd --zone=public --list-ports

2.8 protocols: (空)

protocols:

含义:单独放行的协议(不是端口,而是 IP 层协议,如 gre、esp)。

本例解读:为空,没有单独放行任何协议。

背景知识:协议值可以是协议名(参考 /etc/protocols)或协议号。常用于 VPN、IPsec 等场景:

sudo firewall-cmd --add-protocol=gre --permanent
sudo firewall-cmd --add-protocol=esp --permanent
sudo firewall-cmd --reload

大多数普通服务器不需要动这一项。

2.9 forward: yes

forward: yes

含义:是否允许同一区域内网络接口之间的流量转发。

本例解读:yes。但注意——这台机器只绑定了一个接口 enp1s0 在 public 区域,所以“同区域内接口间转发”实际上没有对象可转。这一项对当前拓扑没有实际影响。

容易混淆的点:

  • forward: yes 不等于“本机能当路由器转发跨区域流量”
  • 也不等于“能上外网”(那是 masquerade 的事)
  • 跨区域转发由 policy 或全局 --get-forward 设置控制

背景知识:如果这台机器有多个网卡同属一个区域,转发才真正起作用。默认情况下 firewalld 的转发策略是比较保守的。

2.10 masquerade: no

masquerade: no

含义:IP 地址伪装(NAT)是否开启。

本例解读:no,关闭。这台机器不会把内网流量的源地址替换成自己的公网地址,即它不做 NAT 出口,内网其他机器不能通过它共享上网。

背景知识:masquerade 仅支持 IPv4,开启后会隐式启用 IP 转发。典型场景是把一台双网卡机器当路由器/网关:

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

配合 external 区域使用是常见做法。注意富规则里也能写 masquerade,并可用 source/destination 限定伪装范围。

2.11 forward-ports: (空)

forward-ports:

含义:端口转发(目的地址转换,DNAT)。

本例解读:为空,没有配置任何端口转发。

背景知识:用于把到达本机某端口的流量转发到本机其他端口或另一台主机,常用来把内网服务发布到公网。例如把公网 80 端口转到内网 192.168.1.10:8080:

sudo firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.1.10 --permanent
sudo firewall-cmd --reload

和 masquerade 配合可实现完整的入站发布 + 出站 NAT。

2.12 source-ports: (空)

source-ports:

含义:按来源端口匹配的规则。

本例解读:为空,没有按源端口做限制。

背景知识:这一项用得较少,通常用于对“来自特定源端口的流量”做特殊处理,实际运维中较少见。

2.13 icmp-blocks: (空)

icmp-blocks:

含义:要拦截的 ICMP 消息类型列表。

本例解读:为空。配合前面的 icmp-block-inversion: no,表示不拦截任何 ICMP 类型,ping 是通的。

背景知识:常用的是拦截 echo-request 来禁用 ping:

sudo firewall-cmd --zone=public --add-icmp-block=echo-request --permanent
sudo firewall-cmd --reload

查看系统支持的 ICMP 类型:

sudo firewall-cmd --get-icmptypes

注意:完全禁用 ICMP 并不总是好主意——PMTU 发现等机制依赖 ICMP,可能导致网络异常。通常只禁 echo-request 即可。

2.14 rich rules: (空)

rich rules:

含义:自定义的复杂规则。

本例解读:为空,没有任何富规则。所以目前所有放行都来自 services 里的 ssh 和 dhcpv6-client,其余一律拒绝。

背景知识:富规则是 firewalld 最灵活的表达方式,支持源/目标地址、端口、协议、日志、审计、动作等组合。完整结构大致如下:

rule [family="ipv4|ipv6"] [priority="priority"]
    [ source [NOT] [address="address"] [mac="mac-address"] [ipset="ipset"] ]
    [ destination [NOT] address="address" ]
    [ element ]
    [ log [prefix="prefix text"] [level="log level"] [limit value="rate/duration"] ]
    [ audit ]
    [ action ]

一个实用例子——只允许来自 192.168.1.0/24 网段 SSH 登录:

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'
sudo firewall-cmd --reload

优先级:富规则的 priority 范围是 -32768 到 32767,值越低越优先。负优先级在其它 firewalld 原语之前执行,正优先级在之后执行,0 则按动作放入相应链。

超时机制:添加富规则时可用 --timeout=timeval(如 --timeout=1h),规则到期自动删除,适合临时放行。

三、运行时配置 vs 永久配置

我们的输出是运行时配置(没加 --permanent)。理解这两者的区别非常关键。

3.1 运行时配置(Runtime)

  • 当前实际生效的规则,直接作用于内核
  • 不指定 --permanent 的修改只影响运行时
  • 服务停止、重载(reload)后丢失
  • firewalld 启动时,永久配置会加载为运行时配置

3.2 永久配置(Permanent)

  • 存储在 /etc/firewalld/zones/ 下的 XML 文件里
  • 系统启动或 --reload 时被加载为新的运行时配置
  • 单独用 --permanent 修改不会立刻生效

3.3 两者关系与操作

# 查看永久配置,和运行时对比
sudo firewall-cmd --zone=public --list-all --permanent

# 把当前运行时配置保存为永久配置
sudo firewall-cmd --runtime-to-permanent

# 用永久配置覆盖运行时配置(未保存的临时修改会丢失)
sudo firewall-cmd --reload

典型工作流:先在运行时测试规则,确认无误后用 --runtime-to-permanent 保存。这样即使测试出错,reload 或重启就能恢复。

容易踩的坑:只加了 --permanent 却忘了 --reload,规则不会生效;反过来,只改运行时没保存,重启后就没了。

四、从我的配置得出的结论

综合以上逐项分析,这台 ubuphy001 的防火墙状态可以总结为:

  1. 网卡 enp1s0 绑定在 public 区域,套用 public 规则
  2. 默认拒绝所有未明确允许的入站流量(target: default)
  3. 只放行 SSH(22/tcp)和 DHCPv6 客户端两个服务
  4. 没有开放任何额外端口、协议、源端口
  5. 没有配置任何端口转发、NAT、富规则
  6. 没有拦截任何 ICMP,ping 是通的
  7. 本机不做 NAT 出口(masquerade: no),也不是路由器

这是一个非常干净、保守、接近默认的配置。作为一台通过 SSH 管理的物理服务器,这个状态是合理且安全的:能远程登录、能获取 IPv6 地址、其余一概拒绝。

五、常用操作命令速查

5.1 服务管理

systemctl start firewalld          # 启动
systemctl enable firewalld         # 开机自启
systemctl status firewalld         # 查看状态
firewall-cmd --state               # 守护进程是否活跃
firewall-cmd --reload              # 重载(保留连接,推荐)
firewall-cmd --complete-reload     # 完全重载(丢失连接,慎用)

5.2 区域管理

firewall-cmd --get-zones                  # 所有可用区域
firewall-cmd --get-default-zone           # 默认区域
firewall-cmd --set-default-zone=work      # 设置默认区域
firewall-cmd --get-active-zones           # 查看激活区域及接口
firewall-cmd --zone=public --list-all     # 查看区域运行时配置
firewall-cmd --zone=public --list-all --permanent   # 查看永久配置

5.3 服务与端口

firewall-cmd --add-service=http                     # 运行时加服务
firewall-cmd --permanent --add-service=http         # 永久加服务
firewall-cmd --add-port=8080/tcp                    # 运行时加端口
firewall-cmd --permanent --add-port=8080/tcp        # 永久加端口
firewall-cmd --permanent --remove-service=http      # 删除服务
firewall-cmd --permanent --remove-port=8080/tcp     # 删除端口
firewall-cmd --list-services                        # 已放行服务
firewall-cmd --list-ports                           # 已放行端口

5.4 高级操作

# 禁用 ping
firewall-cmd --zone=public --add-icmp-block=echo-request --permanent

# 启用 IP 伪装(NAT)
firewall-cmd --zone=external --add-masquerade --permanent

# 保存运行时配置为永久
firewall-cmd --runtime-to-permanent

# 查看接口绑定
firewall-cmd --get-active-zones

结语

回到最初的那条命令,你现在应该能完整读懂它的每一行含义了:

  • public (default, active) → 默认且激活的区域
  • target: default → 未匹配的入站包一律拒绝
  • interfaces: enp1s0 → 规则作用于这块网卡
  • services: dhcpv6-client ssh → 只放行这两个服务
  • 其余为空或 no → 没有额外开放、没有 NAT、没有 ICMP 拦截、没有富规则

firewalld 通过区域抽象、运行时与永久配置分离、以及富规则等机制,在保持灵活性的同时降低了防火墙管理的复杂性。理解每一项配置的真实含义,才能在需要时准确、安全地修改规则——尤其是当你在远程管理一台只能靠 SSH 登录的服务器时。

作者

老丹

关注我
其他文章
上一个

Ubuntu 防火墙迁移指南:从 UFW 到 firewalld 的完整实践

下一个

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

关于博主

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