很多刚接触 Linux 运维的同学,在面对“防火墙”这三个字时,总会陷入一种又熟悉又陌生的感觉。熟悉是因为在 Windows 上天天见,陌生是因为一旦切换到 Linux,面对一堆命令行工具,完全不知道从哪下手。尤其是当你所在的单位既有 CentOS 老服务器,又新采购了国产化的 Kylin(银河麒麟)机器,还要兼顾 Ubuntu 开发环境时,三套命令体系来回切,稍不注意就把生产环境的网络搞断了。
这篇文章的核心观点很明确:CentOS、Kylin、Ubuntu 虽然都是 Linux,但它们的防火墙管理工具、底层实现和操作习惯有本质差异。不要试图用一套命令“通吃”三个系统,也不要一上来就systemctl stop firewalld图省事。你需要理解防火墙服务的设计逻辑,才能在不同系统间自由切换,并且在出问题的时候快速定位。
本文将从一个运维老手的视角,把这三大系统的防火墙服务彻底拆开来讲。你会搞清楚 firewalld、ufw、iptables 之间的关系,掌握最常用的放行、禁用、查看规则命令,最后还会得到一份可以直接抄作业的生产环境最佳实践清单。这篇文章约 6000 字,建议先收藏,遇到问题直接回查。
1. 为什么防火墙服务会成为 Linux 运维的第一道坎
防火墙在 Linux 系统里不是一个可有可无的组件,它是所有网络流量的第一道关口。但从实际工作来看,它又往往是新手犯错最多的地方。最常见的场景是这样的:你在一台 CentOS 7 上装好了 Nginx,本地curl localhost一切正常,但外部浏览器就是访问不了。你检查了云安全组、检查了 Nginx 配置,最后才发现是防火墙没有放行 80 端口。
这类问题的根源在于,很多人对 Linux 防火墙缺乏一个整体认知。过去我们习惯把防火墙理解成一个“软件”,但实际上,Linux 防火墙是一套从内核态到用户态的完整机制。内核里有 netfilter 这个数据包过滤框架,用户态有不同的命令去操作它。CentOS 偏好 firewalld,Ubuntu 偏好 ufw,Kylin 则做了一个国产化的兼容整合。工具不同,但底层都是 netfilter。
另外还要注意一个行业趋势。随着 CentOS 7 在 2024 年 6 月停止维护,越来越多的企业开始评估迁移到 Kylin、Ubuntu 或其他发行版。如果你只会 CentOS 的firewall-cmd,却不知道 Ubuntu 的ufw怎么配置,也不知道 Kylin 的防火墙服务是否兼容 CentOS 习惯,那么在系统迁移和日常运维时就会非常被动。所以本文不讲虚的,直接对比,直接实操,直接给结论。
2. 核心概念:从 iptables 到 firewalld,再到 ufw
要讲清楚三个系统的防火墙,必须先搞清楚它们和 iptables 的关系。
2.1 什么是 netfilter 和 iptables
netfilter 是 Linux 内核里负责网络数据包过滤的框架,它允许内核模块在数据包经过网络协议栈时,挂接不同的钩子函数。真正做规则匹配和动作执行的,是 netfilter。
iptables 是用户态的命令行工具,它通过 netlink 接口和内核里的 netfilter 通信,用来定义规则。iptables 的核心概念是“表”和“链”。常用的是 filter 表(负责过滤)、nat 表(负责地址转换),链则包括 INPUT、OUTPUT、FORWARD 等。数据包进入系统时,会依次经过这些链,匹配到规则就执行对应动作。
数据包流向简化模型: --> PREROUTING --> INPUT --> 本机进程 --> FORWARD --> POSTROUTING --> OUTPUT --> POSTROUTING但这个模型在 CentOS 7 之后以及 Ubuntu 18.04 之后的版本中,逐渐被 nftables 取代。nftables 是新一代的框架,它把规则集编译成字节码直接在内核执行,语法比 iptables 更简洁。只是在用户习惯层面,很多人仍把 nftables 也统称为 iptables。更重要的是,CentOS 7 的 firewalld 底层默认用的其实是 iptables(通过 firewalld 调用),而 CentOS 8/9 的 firewalld 底层默认是 nftables。
2.2 firewalld 的设计思路
firewalld 是 CentOS、RHEL 以及国产化 Kylin 系统默认自带的防火墙服务。它的核心设计理念是“动态管理”和“区域(zone)”。
所谓“动态管理”,是指当你通过firewall-cmd修改规则时,规则会立即生效,不需要重启服务,也不会中断已有连接。这比老的 iptables 方式(每次修改都要重启 iptables 服务)要平滑得多。
“区域”是 firewalld 非常重要的概念,它表示“不同信任级别”的网络环境。比如默认的public区域用于不可信的公网环境,internal区域用于可信的内网环境,trusted区域代表完全信任。每个网络接口可以绑定到一个区域。你在public区域放行 80 端口,外部流量访问 80 端口时就会通过;如果你把接口切到trusted区域,那这台机器的所有端口对外部都完全开放。
2.3 ufw 的定位
Ubuntu 默认使用的是 ufw(Uncomplicated Firewall),名字里的“Uncomplicated”就是它的核心卖点:简化。ufw 的底层仍然调用 netfilter/iptables/nftables,但它在用户层做了一层封装,让你可以用最短的命令完成放行和拒绝。
不推荐直接用 iptables 配置规则的原因: 1. 规则语法复杂,写错容易导致所有连接中断; 2. 多条规则之间顺序敏感,排错成本高; 3. 修改需要手动持久化,否则重启失效。ufw 则把常用场景封装成几个命令:allow、deny、status、reload。对绝大多数服务器场景,这些命令已经足够。
2.4 三者的关系对比
| 维度 | CentOS 7/8/9 | Kylin V10 | Ubuntu |
|---|---|---|---|
| 默认防火墙服务 | firewalld | firewalld(兼容层) | ufw |
| 底层实现 | CentOS 7 是 iptables,8/9 是 nftables | nftables | nftables |
| 管理命令 | firewall-cmd | firewall-cmd / kyfirewall-tool | ufw |
| 配置持久化 | permanent / runtime | permanent / runtime | /etc/ufw 目录 |
| 配置文件 | /etc/firewalld | /etc/firewalld | /etc/default/ufw |
| 优势 | 生态成熟,文档多 | 国产化支持,兼容 CentOS 习惯 | 命令简单,适合单机管理 |
从表格可以看出来,Kylin 在防火墙管理上基本延续了 RHEL/CentOS 的体系,这一点对从 CentOS 迁移到国产化系统的团队非常友好。但 Kylin 也有自己的图形化管理工具,这一点我们在后面单独说。
3. 安全底线:修改防火墙之前必须知道的事
正式进入命令操作之前,我必须先强调几条铁律。这些不是理论,是无数运维事故换来的教训。
3.1 修改生产防火墙必须有计划和备份
防火墙的核心功能是控制访问,它天然就具有“把人挡在门外”的能力。修改防火墙时,如果配置错误,最常见的后果是你自己也无法远程连接服务器。尤其是当你使用 SSH 管理一台远程 Linux 服务器时,防火墙规则一旦把 SSH 端口或来源 IP 禁掉,你可能会被立即踢出,且无法再连回去。
所以,在执行任何可能影响 SSH 连接的防火墙操作前,建议先确认几件事:当前是否还有其他登录途径(比如物理控制台、云平台的 VNC 管理),是否知道如何回滚本次修改,是否备份了当前规则。
3.2 先放行,再禁用,最后重启
一个稳妥的操作顺序是:先把需要放行的端口、来源 IP 都加好,验证新规则生效且不影响正常业务,再去处理要禁止的规则。不要一上来就systemctl stop firewalld去验证“是不是防火墙导致的问题”,因为一旦服务停止,所有防护都失效,服务器直接暴露在网络中。
更规范的验证方式是使用firewall-cmd --add-rich-rule临时加一条精细规则,比如只对自己当前的 IP 放行 SSH:
firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="22" protocol="tcp" accept'这条命令执行后立即生效,但重启 firewalld 后失效。你可以拿它来测试,确认网络通了,再把它转成--permanent永久规则。
3.3 最小权限原则
生产环境里,不要放行0.0.0.0/0这种全开放规则,除非真的没办法。更推荐的做法是精确到来源 IP 或网段,比如只允许公司出口 IP 访问 SSH,只允许内网网段访问数据库端口。最小权限不仅是安全要求,也能减少误操作带来的影响范围。
4. CentOS 防火墙服务全面实操
先来把 CentOS 这个基础打牢。CentOS 7 和 CentOS 8/9 在 firewalld 的使用上基本一致,下面所有的命令在两种版本上都可以直接执行。
4.1 查看 firewalld 运行状态
systemctl status firewalld如果你看到active (running),说明防火墙服务正在运行。如果显示inactive (dead),说明服务没有启动。但要注意,服务是 dead 不代表系统真的没有防护,因为 nftables 或 iptables 规则可能仍然存在并生效。更保险的查看方式是:
firewall-cmd --staterunning或not running的输出比 systemd 状态更直观地反映了 firewalld 是否参与工作。
4.2 常用管理命令
查看当前public区域放行的服务和端口:
firewall-cmd --list-all输出样例:
public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: ssh dhcpv6-client ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:这个输出说明系统默认只放行了 SSH 和 DHCPv6 客户端。
放行 80 端口(临时生效):
firewall-cmd --add-port=80/tcp放行 80 端口(永久生效):
firewall-cmd --permanent --add-port=80/tcp firewall-cmd --reload注意:--permanent参数必须配合--reload才能在永久配置中写入并让系统读取。如果不加--reload,尽管规则已写入配置文件,但当前运行中的 firewalld 还不知道。如果不加--permanent,则只是运行期有效,重启后消失。
4.3 关闭 firewalld 的正确方式
生产环境不推荐关闭防火墙,但有些内网测试环境实在懒得管它。如果一定要关闭,务必按顺序执行:
systemctl stop firewalld systemctl disable firewalldstop是停止当前的服务,disable是取消开机自启。如果只stop不disable,重启之后防火墙又回来了。
我见过不少线上事故,就是因为有人给云服务器做了镜像,镜像里stop了 firewalld 但没disable,后续新机器开机后防火墙自动启动,导致所有端口都被挡住。这一类问题往往出现在批量交付的环境中,排查起来很费时间。
4.4 重新加载配置的区别
firewall-cmd --reload这个命令是“优雅重载”,它保留运行时状态,只重新加载永久配置。如果只是临时规则,则会被清掉。
firewall-cmd --complete-reload这个命令会“完全重载”,它会把整个防火墙状态全部重置为永久配置,包括当前动态添加的临时规则都会被清掉。使用--complete-reload时如果有正在进行的连接,可能会短暂中断。
4.5 一个完整示例:放行 Web 服务并验证
以最常见的 Nginx Web 服务器为例,假设你的业务需要同时对外提供 HTTP 和 HTTPS:
firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload然后验证:
firewall-cmd --list-all重点看输出里的services: http https ssh dhcpv6-client。此时再用另一台机器访问本机 IP 的 80 或 443 端口,就能正常打开页面了。
5. Kylin 系统防火墙服务详解
Kylin(银河麒麟)作为国产操作系统,在军政企单位的使用率持续上升。从 CentOS 迁移到 Kylin 的团队最关心的就是:原来那套 Linux 命令还能不能用?在防火墙这一块,答案基本是肯定的。
5.1 麒麟防火墙服务与 CentOS 的兼容性
银河麒麟 V10 的桌面版和服务器版,默认都带有 firewalld。也就是说,你在 CentOS 上常用的firewall-cmd命令,在 Kylin 上可以直接使用,语法完全一样。这一点非常重要,意味着团队的学习成本很低,迁移脚本也不用大改。
systemctl start firewalld systemctl enable firewalld查看运行状态:
firewall-cmd --state查看已放行端口:
firewall-cmd --list-ports添加 MySQL 3306 端口(仅限内网):
firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reload5.2 麒麟专用图形化管理:kyfirewall-tool
除了命令行,Kylin 还提供了一个图形化防火墙管理工具kyfirewall-tool。这对桌面版用户特别友好,尤其是对命令行不太熟练的同事。
在终端输入:
kyfirewall-tool打开后界面是中文的,可以选择放行常用服务,比如 SSH、HTTP、HTTPS、Samba 等,也可以手动添加端口。这个工具底层也是操作 firewalld 的配置,所以和命令行修改是等价的。
在服务器版中,如果未安装该图形工具,可以通过以下命令安装:
yum install -y kyfirewall-tool5.3 麒麟系统防火墙配置文件位置
麒麟防火墙的配置存储与 RHEL 系一致:
/etc/firewalld/存放自定义的永久配置;/usr/lib/firewalld/存放系统自带的默认配置。
当你修改规则时,优先查看/etc/firewalld/zones/public.xml,这是默认 public 区域的配置文件。
查看当前 public 区域配置:
cat /etc/firewalld/zones/public.xml示例:
<?xml version="1.0" encoding="utf-8"?> <zone> <short>Public</short> <description>For use in public areas.</description> <service name="ssh"/> <service name="dhcpv6-client"/> </zone>如果这个文件里已经写了<port port="8080" protocol="tcp"/>,说明规则已写入永久配置。
5.4 麒麟系统特有的注意事项
麒麟系统的 SELinux 默认可能是 enforcing 状态,防火墙放行了端口之后,还要确认 SELinux 没有拦截相应的服务。如果出现“端口已放行但服务仍无法访问”的情况,可以执行:
getenforce如果是Enforcing,可以查看对应服务的 SELinux 布尔值,或临时用setenforce 0验证是不是 SELinux 导致的问题。注意,生产环境不建议直接关闭 SELinux,更合理的做法是调整针对该服务的布尔开关或添加策略模块。
6. Ubuntu 防火墙服务详解
Ubuntu 在开发者和云计算用户中的占比越来越大。很多人在 CentOS 上用惯了firewall-cmd,到了 Ubuntu 上反而不适应。其实 Ubuntu 的 ufw 更简单,你只需要掌握几个关键命令。
6.1 安装与启用 ufw
Ubuntu 默认可能已经安装了 ufw,但状态是不启用的。确认安装:
dpkg -l | grep ufw如果未安装:
apt update apt install -y ufw启用 ufw:
ufw enable启用后系统会提示:
Command may disrupt existing ssh connections. Proceed with operation (y|n)?如果您的 SSH 默认端口是 22,且没有修改过,通常直接输入 y 就能完成启用且保持 SSH 连接。但为了稳妥,我建议启用前先确保放行了 SSH 端口:
ufw allow 22/tcp然后再执行ufw enable。
6.2 ufw 常用命令
查看状态:
ufw status如果想看到更完整的端口信息:
ufw status verbose放行 HTTP:
ufw allow 80/tcp放行 HTTPS:
ufw allow 443/tcp放行 SSH(无论是 22 还是自定义端口):
ufw allow 22/tcp放行某个来源 IP 访问所有端口:
ufw allow from 192.168.1.100删除规则:
ufw delete allow 80/tcp这个命令不会中断现有连接,但之后新的连接会按新规则处理。
6.3 ufw 和 iptables 的关系
很多人发现,自己在 Ubuntu 上直接用iptables -L查看时,看到的规则是空的,但ufw status里明明有规则。这是怎么回事呢?
实际上,ufw 会把规则写入到/etc/ufw/下的配置文件中。ufw enable后,系统通过 systemd 的一个 hook 把这些规则加载到 nftables 或 iptables 中。当你用iptables -L查看时,因为 ufw 的规则链名称是ufw-user-input等自定义链,默认列表不一定直接显示,需要指定-L ufw-user-input才能看到。
iptables -L ufw-user-input -n所以不要在 Ubuntu 里什么都不看就说“防火墙没生效”。用ufw status才是判断 ufw 是否工作的关键途径。
6.4 Ubuntu 防火墙完整示例
假设你在一台 Ubuntu 服务器上部署了 Nginx 和 MySQL,需要对外放行 80、443,对内放行 3306(仅限内网网段):
ufw allow 80/tcp ufw allow 443/tcp ufw allow from 192.168.1.0/24 to any port 3306/tcp然后启用:
ufw enable查看最终状态:
ufw status verbose预期输出:
Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 80/tcp ALLOW IN Anywhere 443/tcp ALLOW IN Anywhere 3306/tcp ALLOW IN 192.168.1.0/24看到Status: active和三条ALLOW IN规则,就说明放行成功了。此时从内网的另一台机器访问 3306 端口应该能通,从外部访问就会被拒绝。
7. 三大系统防火墙服务对比与切换指南
如果之前没有系统地做过对比,表格式的梳理最能帮你建立全局印象。
| 操作需求 | CentOS (firewalld) | Kylin (firewalld/kyfirewall-tool) | Ubuntu (ufw) |
|---|---|---|---|
| 查看状态 | firewall-cmd --state | firewall-cmd --state | ufw status |
| 放行端口 | firewall-cmd --add-port=80/tcp | firewall-cmd --add-port=80/tcp | ufw allow 80/tcp |
| 永久放行 | firewall-cmd --permanent --add-port=80/tcp; reload | 同左 | ufw allow 80/tcp(默认持久化) |
| 删除规则 | firewall-cmd --remove-port=80/tcp | firewall-cmd --remove-port=80/tcp | ufw delete allow 80/tcp |
| 重新加载 | firewall-cmd --reload | firewall-cmd --reload | ufw reload |
| 关闭服务 | systemctl stop firewalld | systemctl stop firewalld | ufw disable |
| 设置开机自启 | systemctl disable firewalld | systemctl disable firewalld | ufw disable(覆盖自启) |
| 查看详细规则 | firewall-cmd --list-all | firewall-cmd --list-all | ufw status verbose |
从表中可以看出几个关键差异点:
第一,CentOS 和 Kylin 的永久规则需要--permanent参数,而 Ubuntu 的 ufw 默认规则就是持久化的,不需要额外参数,记住这一点可以避免很多困惑。
第二,CentOS 和 Kylin 修改永久规则后需要--reload才会让规则生效,ufw 则在执行allow命令时直接生效。
第三,Kylin 的网络管理可能同时存在 NetworkManager 和系统自带网络服务两套体系,修改防火墙时要注意接口名称。推荐先执行nmcli device status查看当前接口,再绑定到 firewalld 区域。
8. 常见问题与排查思路
下面这些问题是运维工作中出现频率最高的,我把排查过程整理成了一张速查表。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 外部访问不到 Nginx 端口 | 防火墙未放行 80 端口 | 执行 firewall-cmd --list-all 或 ufw status 查看端口 | 放行对应端口后 reload |
| 修改防火墙规则后立即断连 | 规则把 SSH 端口或当前来源 IP 拒绝 | 通过云控制台 VNC 或物理控制台登录 | 追加放行 SSH 和来源 IP,删除错误规则 |
| firewalld 服务无法启动 | 配置文件语法错误 | systemctl status firewalld 查看报错日志 | 检查 /etc/firewalld 下 xml 文件格式 |
| ufw enable 后无法 SSH 登录 | 启用前未放行 SSH 端口 | ufw status 查看 22 端口是否 ALLOW | 通过控制台执行 ufw allow 22/tcp 后 enable |
| 防火墙规则已经放行,但仍不通 | SELinux 或云平台安全组拦截 | getenforce 查看 SELinux;检查云控制台安全组 | 调整 SELinux 布尔值或安全组规则 |
| 批量交付的机器端口全不通 | 镜像中只 stop 了 firewalld 未 disable | systemctl is-enabled firewalld | 统一执行 disable 并清理规则 |
如果遇到 “端口明明放行了却还是不通”,按下面顺序排查一般不会漏:
- 先看本机监听情况:
netstat -tlnp或ss -tlnp,确认服务确实在监听相应端口; - 再查防火墙规则:
firewall-cmd --list-all或ufw status,确认端口已放行; - 再看 SELinux:
getenforce,如果是 Enforcing 且不是常见服务,就要排查对应的布尔值; - 最后确认云平台安全组:云服务器即使内部防火墙全放,安全组没放行照样不通。
9. 最佳实践与生产环境建议
防火墙的配置不只是在出问题时才去操作,它应该贯穿服务器的整个生命周期。以下几条建议全部来自真实项目复盘,希望能帮你少走弯路。
9.1 按环境拆分管理策略
测试环境和生产环境不要用同一套防火墙规则。测试环境可以适当放宽,方便调试;生产环境必须收敛规则,仅暴露必要端口。每次上线前,由一名成员专门检查防火墙变更是否符合最小权限原则。
9.2 用 rich rule 实现精细控制
firewalld 的 rich rule 比直接--add-port更精细。比如只允许某个 IP 访问 8080 端口:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.5" port port="8080" protocol="tcp" accept' firewall-cmd --reload删除这条规则:
firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="10.0.0.5" port port="8080" protocol="tcp" accept' firewall-cmd --reload这种写法不仅满足业务需求,也便于以后审计时看清来源。
9.3 屏蔽不必要的 ICMP 请求
在公网环境下,建议屏蔽外部 ping 探测,减少被扫描的概率。firewalld 中默认 public 区域已经屏蔽了部分 ICMP 类型,如果需要自定义,可以在 centos/kylin 里执行:
firewall-cmd --permanent --add-icmp-block=echo-request firewall-cmd --reloadUbuntu 中:
ufw deny out to any port 8 proto icmp这个配置对很多安全性要求较高的政务项目非常常见。
9.4 定期备份防火墙规则
防火墙规则属于系统配置中最容易被“遗忘”的部分。建议每月备份一次:
cp -r /etc/firewalld /backup/firewalld-backup-$(date +%Y%m%d)Ubuntu 中:
cp -r /etc/ufw /backup/ufw-backup-$(date +%Y%m%d)备份的另一个作用是,当系统被人改动后,你可以快速做 diff 找出异常规则。
9.5 自动化脚本里不要直接关闭防火墙
在编写自动化部署脚本时,很多人图省事,一上来就执行:
systemctl stop firewalld这是一个非常危险的习惯。正确的做法是在脚本中先判断哪些端口需要放行,然后调用防火墙命令把这些端口加进去。如果确实遇到服务冲突,再针对具体规则做调整,而不是一刀切停掉服务。尤其是在云原生环境下,很多 Kubernetes 节点需要在宿主机上放开不少端口,你更应该用精确放行的方式来处理,而不是直接关闭防护。
10. 总结与后续学习方向
这篇文章把 CentOS、Kylin、Ubuntu 三大 Linux 系统的防火墙服务做了一个尽量完整的梳理。核心要点可以归纳成三句话:
第一,CentOS 和 Kylin 的防火墙服务是一致的,都使用 firewalld,命令和配置通用,迁移成本极低。学会 CentOS,基本就掌握了 Kylin 的命令行管理。
第二,Ubuntu 的 ufw 更简单,但它不是独立于 netfilter 的另一个东西,它只是 nftables/iptables 的上层封装。在 Ubuntu 上排查问题时,优先看ufw status,而不是iptables -L。
第三,无论是哪个系统,在改防火墙之前都要想清楚:如果这条规则改错了,最坏结果是什么?有没有备用登录方式?能不能快速回滚?谨慎不是胆小,而是专业。
如果你刚接触 Linux,下一步可以做一个小实验:分别在一台 CentOS 虚拟机、一台 Kylin 虚拟机和一台 Ubuntu 虚拟机上安装 Nginx,然后通过防火墙命令放行 80 端口,再用另一台机器测试访问。把这一步跑通了,理解会深入很多。之后再学 NAT、端口转发、富规则等进阶功能,就会轻松不少。
希望这篇文章能在你处理 Linux 防火墙问题的时候提供实在的帮助。如果你在实际环境里遇到过更特殊的防火墙坑,欢迎在评论区记录一下,大家一起补充,后面的同学就能少踩一个坑。