ufw与firewalld深度解析:Linux防火墙规则配置、迁移与排查实战

发布时间:2026/8/30 17:50:27
ufw与firewalld深度解析:Linux防火墙规则配置、迁移与排查实战 很多人第一次认真研究 Linux 防火墙都是从ufw和firewalld这两个名字开始的。但大多数教程只告诉你“开放 22 端口”或“禁用防火墙”却没说清楚这两套工具到底解决什么问题、底层依赖什么、什么时候该用哪一个。结果就是在一台 Ubuntu 服务器上把规则配得好好的换到 CentOS 上却找不到ufw命令或者明明在firewalld里加了端口外部测试却还是不通。这篇文章就把 ufw 和 firewalld 放在一起讲清楚。先看它们各自的定位和底层机制再分别用实例走一遍常用配置、批量管理、错误排查和取舍思路。看完之后你至少能回答这五个问题它们是什么、怎么用、规则为什么没生效、两套工具能不能混用、生产环境到底该怎么选。1. 先搞清楚 ufw 和 firewalld 的本质再动手配规则很多人都把 ufw 和 firewalld 当成两个完全对立的防火墙软件其实这个理解不够准确。它们更像是在不同发行版上默认自带的两套前端管理工具真正干活的底层框架仍然是 Linux 内核里的网络过滤机制。1.1 ufw 是 iptables 的简化前端不是独立防火墙ufw 的全称是 Uncomplicated Firewall设计目标就是“不复杂”。它把 iptables 的链、表、匹配条件这些概念封装成更直观的规则比如你只需要写ufw allow 22/tcp它会在后台帮你处理 INPUT 链、协议判断和端口匹配。但这不代表 ufw 只是个玩具。你可以手动编辑/etc/ufw/下的规则文件也可以查看它生成的完整 iptables 规则。很多云服务器镜像默认预装的就是 ufw尤其是 Ubuntu 和 Debian 系。它适合单机规则管理追求的是“快速上手、少出错”。如果你在 Ubuntu 上执行sudo ufw status verbose输出会显示当前状态、默认策略和已有规则。注意这个 verbose 参数它会连带打印默认的入站、出站和转发策略排查问题时不至于只看到几条规则而无从判断方向。1.2 firewalld 基于 zone 和 services天然适合动态更新firewalld 是 CentOS、RHEL、Fedora 等发行版的选择。它通过 D-Bus 接口实时变更规则不需要像 iptables 那样每次重载整个规则集。它的核心概念是 zone也就是把网络划分为不同信任区域比如 public、internal、trusted。比如你把一张网卡分配到 public 区域那么这个区域里允许的端口和服务就决定外部访问能否成功。它的命令风格也很明确sudo firewall-cmd --list-all sudo firewall-cmd --permanent --add-port8080/tcp注意--permanent这个参数它表示“永久写入配置”但不一定立即生效到当前会话。如果你不加这个参数规则只会加到运行时重启服务后就会消失。这个设计既是优点也是坑点后面会单独展开。1.3 两套工具的共同底色内核 Netfilter不管是 ufw 还是 firewalld最终都会调用内核的 Netfilter 框架。Netfilter 提供了数据包过滤、网络地址转换、连接跟踪等底层能力iptables、nftables 都是操作它的常见接口。从实际排查角度看你要记住一个顺序ufw/firewalld只是你看到的“操作面板”真正的生效链路是规则写入、内核 Netfilter 加载、防火墙策略匹配。如果规则配了但流量不通不要只盯着前端命令输出还要看内核层面的规则表和数据包计数。比如 ufw 状态下可以用 iptables 命令看它生成的内容sudo iptables -L -n -v这时你会看到 ufw 创建的链和规则。很多时候“防火墙没生效”其实是因为规则写进了不同优先级或不同链而不是系统没加载。2. 动手前的环境准备与执行原则看内核、看发行版、看当前状态这三件事应该在动手改防火墙之前做完。很多人直接打开端口却发现根本连不上服务最后查了半天才意识到 SSH 端口被别人改过而防火墙放行的还是默认 22。2.1 确认发行版和默认管理工具先确定自己手上是哪一套工具cat /etc/os-release command -v ufw command -v firewall-cmd不同发行版的默认工具不一样但很多系统也允许手动安装另一套。比如 Debian 系可以安装 firewalldCentOS 也可以安装 ufw。我不建议在同一台主机上同时启用两套管理工具因为它们的策略会互相叠加最后排查起来非常绕。尤其是新装的容器镜像、云服务器测评环境和国产化系统镜像底层服务管理方式可能有差异最好先确认 systemd 服务状态再决定用哪套工具。2.2 先看默认策略再决定放行规则默认策略决定了“没有匹配到任何规则时数据包该怎么处理”。绝大多数安全要求较高的服务器默认入站策略是 deny也就是一切入站连接默认拒绝只有匹配到显式 allow 规则才放行。出站通常是 allow方便服务器主动访问外部更新源、调用接口。ufw 查看默认策略sudo ufw status verbosefirewalld 查看默认区域和策略sudo firewall-cmd --get-default-zone sudo firewall-cmd --list-all --zonepublic我一般会先把这个信息记下来再开始配置。如果默认入站本来就是 deny那我只需要确认需要对外服务的最小端口集合比如 SSH、HTTP、HTTPS。如果默认入站是 allow那我建议先把默认策略调整成 deny再添加白名单式放行规则否则开放的端口越多安全暴露面越大。2.3 修改防火墙前先准备一个可靠的回退通道这句话一定要放在前面配置防火墙时最怕的不是规则写错而是把当前的 SSH 连接干掉。特别是远程服务器场景如果你在防火墙里误删了 22 端口放行规则或者把默认入站策略改成 deny现有连接不会立刻断开但一旦断开会话很难再连回来。更危险的是有些云平台的安全组和系统内防火墙是两层叠加关系系统内封禁之后控制台不一定能帮你快速解掉。比较稳妥的操作顺序不要退出当前终端另开一个 SSH 会话测试规则。先添加白名单式放行再收紧默认策略。每次只改一类规则改完立刻验证。如果用的是云服务器先确认云平台安全组是否放行对应端口。保留一个 VNC 或控制台类型的备用登录入口。这个流程看起来慢但能避免很多生产事故。3. 从最小规则到批量管理ufw 精讲与实战ufw 的语法足够简单但简单不等于可以乱写。下面按一个标准服务器的配置流程从头走一遍每条命令都会解释为什么这么写以及输出长什么样才算正常。3.1 启用和禁用要分清操作目标很多新手执行sudo ufw enable后没看到任何提示就以为规则没生效然后反复执行。实际上 ufw enable 的合理输出是一句警告提示告诉你启用后现有 SSH 连接可能受影响然后让你输入 y 确认。建议先看一下当前状态sudo ufw status如果状态是 inactive再启用sudo ufw enable如果你只是临时调整规则不想完全关闭防火墙不需要执行 disable。用完删除对应规则即可。我记得有个同事为了调试端口把 ufw 整个 disable 了结果服务开完忘掉重新启用服务器裸奔了几个月。所以“关闭防火墙”这种事能不做就不做。3.2 常用规则的写法与判断标准ufw 的基础规则非常直观# 允许 SSH sudo ufw allow 22/tcp # 允许指定端口 sudo ufw allow 8080/tcp # 允许指定 IP 访问指定端口 sudo ufw allow from 192.168.1.100 to any port 3306/tcp # 拒绝某个 IP sudo ufw deny from 203.0.113.10 # 删除规则 sudo ufw delete allow 8080/tcp写规则时要注意两点协议要写清楚是 tcp 还是 udp来源范围要写明白是任意来源还是指定 IP。有些服务虽然显示“监听端口是 8080”但实际对外通信可能同时需要 TCP 和 UDP比如 DNS、NTP、部分音视频服务。如果只放行 tcp另一部分流量仍然会被丢弃。验证方式不复杂sudo ufw status numbered这个命令会输出带编号的规则列表。如果你要插入规则到某个位置可以先看编号再使用insert语法sudo ufw insert 1 allow from 192.168.1.0/24 to any port 22/tcp编号越靠前优先级越高。这种机制在防火墙规则多时非常有用。3.3 修改 SSH 端口时先把新端口放行再改 sshd_config我见过不少案例用户把 sshd 的监听端口从 22 改到 2222防火墙只放行了 22重启 SSH 后直接断线。还有反过来的情况改了 sshd_config却忘了 ufw 规则没加服务端口没监听成功连 log 都看不到。正确步骤# 1. 先放行新端口 sudo ufw allow 2222/tcp # 2. 修改 sshd_config sudo sed -i s/^#Port 22/Port 2222/ /etc/ssh/sshd_config # 3. 检查 sshd 配置 sudo sshd -t # 4. 重启 SSH 服务 sudo systemctl restart sshd # 5. 新窗口测试连接 ssh -p 2222 userserver_ip确认新端口能正常登录后再删除旧的 22 端口放行规则。这个顺序看着啰嗦但能保证你始终保留一个可用通道。3.4 ufw 的日志、转发和默认策略调整ufw 的日志功能经常被忽略。默认日志级别是 off遇到“规则没生效”却不知道丢包原因时打开日志非常关键sudo ufw logging on sudo ufw logging medium日志写在/var/log/ufw.log里面会记录被阻止的数据包信息。配合 dmesg 使用能快速判断是源 IP、目标端口还是转发问题。如果你需要做端口转发比如把外部访问的 8080 转到内网另一台主机的 80 端口可以在/etc/ufw/before.rules中配置 NAT 规则。这里要提醒一句这个文件是 ufw 在加载规则时读取的修改后必须执行sudo ufw reload如果只是用ufw allow添加普通端口规则不需要编辑这个文件。默认策略调整sudo ufw default deny incoming sudo ufw default allow outgoing这句建议在你理解“入站默认拒绝、出站默认允许”的安全模型后再执行。如果服务器要对外提供 Web 服务、数据库服务、API 服务记得在前面把对应端口先 allow 完。4. 从 zone 概念到生产配置firewalld 精讲与实战firewalld 的学习曲线比 ufw 陡一点因为它引入了 zone、runtime、permanent 三个概念。你只有把这三个概念彻底搞清楚才能避免“配置了但不生效”的问题。4.1 runtime 和 permanent 的区别是出现频率最高的问题先看一个例子sudo firewall-cmd --add-port80/tcp执行完后HTTP 端口立刻放行。但如果这时候执行sudo firewall-cmd --reload80 端口可能就没了。原因就是上面这条命令只写入了运行时规则没有写入永久配置文件。要确保规则重启服务后仍然存在必须加上 --permanentsudo firewall-cmd --permanent --add-port80/tcp sudo firewall-cmd --reload这里有一个常见的误解加了 --permanent 之后还需要手动 reload 吗需要。--permanent只是把规则写进配置文件运行时的内核规则并不会自动变更。所以最稳妥的流程是sudo firewall-cmd --permanent --add-servicehttp sudo firewall-cmd --reload sudo firewall-cmd --list-all先用 permanent 写配置再 reload 让配置生效最后 list-all 确认。4.2 zone 的分配逻辑不同网络接口可以有不同的策略firewalld 默认有一个 default zone通常叫 public。所有未指定区域的网络接口默认归入这个区域。你可以查看当前网卡归属sudo firewall-cmd --get-active-zones输出类似public interfaces: eth0在生产环境里比较常见的做法是把内网接口放到 trusted把外网接口放到 public 或者 dmzsudo firewall-cmd --permanent --zonetrusted --change-interfaceeth1 sudo firewall-cmd --reload这样 eth1 上的流量可以享受更宽松的规则而 eth0 上的流量继续走严格策略。对于有多张网卡的服务器这个能力非常重要。4.3 服务、端口和 rich rule 的优先级firewalld 支持三种规则写法按可读性排序--add-servicessh适合系统已知的标准服务。--add-port8080/tcp适合没有标准服务名的应用端口。--add-rich-rule适合带来源 IP、协议、动作等复杂条件的规则。rich rule 举例sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.1.100 port port3306 protocoltcp accept这句的含义是只允许 192.168.1.100 访问本机 3306 端口。如果你需要限制数据库只对内网开放这个写法比单纯放行 3306 更安全。如果你遇到“添加了 service 但连接还是失败”的情况要检查默认区域里--list-services的输出。规则存在但不代表匹配到了当前默认区域。4.4 firewalld 的端口转发和 NAT 配置firewalld 同样支持端口转发。例如把本机 8080 端口的入站流量转发到 10.0.0.5 的 80 端口需要两步sudo firewall-cmd --permanent --add-forward-portport8080:prototcp:toport80:toaddr10.0.0.5 sudo firewall-cmd --reload如果转发不生效大概率是内核转发开关没打开sudo sysctl -w net.ipv4.ip_forward1如果想永久开启写入/etc/sysctl.conf或者/etc/sysctl.d/下的配置文件。注意这只是让内核允许转发真正的防火墙策略还是要通过 firewalld 管理。如果你在云环境里做 NAT 转发还要确认云平台的安全组是否允许该流量进入本机。4.5 临时放行与批量管理思路调试阶段临时放行端口不加 --permanent 是合理的。调试确认后再补加 permanent 规则。这个过程能避免把临时端口写进永久配置。但生产环境最好避免反复在运行时临时加端口因为你可能忘记清理最终出现在运行规则里存在、永久配置里不存在的“幽灵端口”。每次调试完建议用sudo firewall-cmd --list-all和sudo firewall-cmd --permanent --list-all把两份规则做对比确保临时规则和永久规则一致。如果要批量添加端口写循环时要小心for port in 8080 8081 8082; do sudo firewall-cmd --permanent --add-port${port}/tcp done sudo firewall-cmd --reload5. 两套工具交叉使用、迁移思路和生产选择我做项目时经常遇到一个问题运维脚本在 Ubuntu 上跑通拿到 CentOS 上就报ufw: command not found。这种事不是工具本身的问题而是没有提前确认环境。5.1 ufw 和 firewalld 能不能同时安装技术上可以因为它们的底层都依赖 Netfilter但实际不建议。同时启用两套工具会造成规则叠加排查逻辑会变得非常混乱。你明明关闭了 firewalld 的某个端口却忘了 ufw 里还放行着或者反之。生产环境里我建议只保留一套管理工具另一套禁用并设置开机不启动。比如在 CentOS 上如果安装了 ufwsudo systemctl stop ufw sudo systemctl disable ufw原则上系统原生的默认防火墙管理工具优先别为了统一习惯强行替换。5.2 从 ufw 迁移到 firewalld 的规则对照思路迁移不是把命令逐条改一下就行而是要重新梳理业务端口、来源 IP、默认策略这三件事。你可以画一张清单业务协议端口来源范围动作SSHTCP22办公室 IPallowHTTPTCP80全部allowHTTPSTCP443全部allowMySQLTCP3306内网网段allow其他---deny然后按这个清单分别配置 ufw 或 firewalld。迁移过程中最忌讳的是“顺手把不需要的端口也放行”比如把 21、23、445 等旧环境里遗留的端口带过去。5.3 生产环境中如何选择我的经验是如果是 Ubuntu、Debian 或者个人学习机优先 ufw。语法简单规则清晰适合快速落地。如果是 CentOS、RHEL、Rocky、AlmaLinux 这类企业发行版或要管理多网卡、多区域、需要动态更新规则的场景优先 firewalld。如果你已经有一套成熟的 iptables 脚本而且团队很熟悉那不换工具也可以但要确保新规则不会和现有工具冲突。如果服务器数量多建议用自动化工具统一管理防火墙配置而不是逐台手工执行命令。选择标准不是“哪个更安全”而是“哪个更适合你的环境维护方式”。ufw 和 firewalld 本身都只是管理工具安全效果取决于你写进去的规则。5.4 防火墙规则维护的日常习惯我见过很多服务器防火墙问题最后都不是“功能不支持”而是“没人维护规则清单”。建议从第一天就做好三件事每个端口放行都备注业务用途。批量修改前先导出或备份当前规则。每次变更后记录时间和验证结果。ufw 备份可以简单复制配置文件sudo cp -r /etc/ufw /etc/ufw.bak.$(date %F)firewalld 备份可以sudo cp -r /etc/firewalld /etc/firewalld.bak.$(date %F)这个动作耗时不到一分钟但恢复时能省大量时间。6. 规则不生效时的通用排查链路无论你用 ufw 还是 firewalld规则不生效的表现通常有四种完全连不上、部分 IP 能连、连接超时、连接被拒绝。每种现象对应的排查方向不一样。6.1 先确认现象再动规则完全连不上先确认服务进程是否在监听防火墙规则可能不是主要原因。用ss -lntp看端口是否处于 LISTEN 状态如果服务本身没起来改防火墙规则没有意义。部分 IP 能连大概率是防火墙规则里限制了来源地址或者默认区域设置了严格策略。检查规则中是否有来源白名单。连接超时数据包可能被静默丢弃要么是防火墙没有放行要么是网络路径中被安全组拦截。连接被拒绝端口没有监听或者防火墙返回了 reject 而不是 drop。reject 会主动通知客户端不可达drop 则没有响应。6.2 从日志和计数规则里找线索ufw 开日志后直接看/var/log/ufw.log。firewalld 的日志通常在/var/log/firewalld也可能落在内核日志里。你可以先看当前规则匹配计数sudo iptables -L -n -v重点关注 INPUT 链里每条规则左侧的 pkts 和 bytes 数值。如果计数一直没有增长说明数据包根本没有走到这条规则可能是前置 reject、DROP 或网络路径问题。如果计数一直在涨但连接还是失败那么问题可能是服务本身。6.3 常见失败原因的优先级排序我一般按这个顺序排查云平台安全组是否放行端口。服务进程是否监听在正确 IP 和端口上。防火墙默认策略是否拒绝入站。规则是否写进了默认区域。端口协议是否写错例如服务用 TCP但放行写成了 UDP。是否存在 ipset、firewalld 富规则、ufw before.rules 等叠加规则。内核 ip_forward 是否开启涉及转发时必须检查。规则保存后是否执行了 reload 或 restart。这八项里前三项是“环境问题”后五项是“配置问题”。大多数新手卡在第四项和第五项特别是 firewalld 的默认区域和协议写法。6.4 如何快速回滚如果修改后业务受损先不要急着研究为什么优先恢复服务。ufw 可以直接删除错误规则sudo ufw status numbered sudo ufw delete 3如果不知道哪条规则错误也可以临时允许所有流量等确认服务恢复后再逐条收紧sudo ufw default allow incoming注意这并不建议长期使用只是应急手段。firewalld 同理可以用--remove-port或--remove-rich-rule删除问题规则也可以把对应 zone 重新设为默认策略sudo firewall-cmd --permanent --zonepublic --set-targetACCEPT sudo firewall-cmd --reload先把 target 改成 ACCEPT业务恢复后再回头看规则版本和前一天备份的差异。7. 最后的落地建议把 ufw 和 firewalld 放在一起学重点不是背命令而是理解“前端工具 内核过滤 区域策略”这个三层结构。前端负责让管理员少写复杂规则内核负责真正匹配流量区域策略决定不同网卡的可信度。理解这三层之后不管下次遇到的是ufw、firewalld还是直接面对nftables你都能顺着思路排查问题。实际干活时我建议先在一个不重要的测试环境里把本文的规则逐条跑一遍确认每个命令的输出长什么样再把同样的流程迁移到生产服务器。测试环境里不值得调试“策略安全性”但要调试“规则生效路径”。如果你现在面临的问题是“服务器端口连不上”别急着把所有端口都放行先按第六节的八项清单走一遍。多数情况下第一项和第三项就能解决大部分问题。真正需要你花时间研究的其实是后续的批量规则、区域策略和日志监控——这些才是防火墙配置从“能用”走向“好用”的分水岭。