防火墙选择困难症?firewalld和ufw到底该用哪个,我踩过的坑都在这了
最近有粉丝盆友让我讲讲firewalld,秉承着来都来了都原则。我选择今天把firewalld和ufw一起讲了。废话不多说,让我们开始吧!
firewalld和ufw到底是什么?
说到Linux防火墙,很多人第一反应就是iptables。但是iptables的命令语法实在太复杂了,对新手很不友好。于是就出现了firewalld和ufw这两个工具,它们本质上都是iptables的"翻译官",把复杂的iptables命令包装成更容易理解和使用的形式。
firewalld是Red Hat公司开发的动态防火墙管理工具,从CentOS 7开始就成为了默认的防火墙解决方案。它最大的特点是引入了"区域(Zone)"的概念,可以根据网络环境的信任程度来应用不同的防火墙规则。比如你在家里、公司、咖啡厅连接不同的网络时,可以自动切换到对应的安全策略。
ufw全称是Uncomplicated Firewall,从名字就能看出来它的设计理念——让防火墙配置变得简单。Ubuntu系统默认安装了ufw,它的命令非常直观,基本上看一眼就能明白什么意思。比如ufw allow 80
就是开放80端口,ufw deny 22
就是禁止22端口,简单粗暴。
这两个工具的底层都是调用iptables来实现防火墙功能,只是提供了不同风格的管理界面。firewalld更适合复杂的企业环境,ufw更适合简单快速的部署场景。就像同样是开车,一个是手动挡一个是自动挡,看你的需求和习惯了。
firewalld - 红帽系的宠儿
firewalld是红帽公司开发的动态防火墙管理工具,在CentOS、RHEL、Fedora这些系统上是默认的防火墙解决方案。
核心概念:区域(Zone)
firewalld最大的特点就是引入了"区域"的概念。什么意思呢?就是把网络连接分成不同的信任级别。比如:
- public:公共区域,不信任网络中的其他计算机
- home:家庭区域,相对信任网络中的其他计算机
- work:工作区域,适用于工作场所
- dmz:DMZ区域,用于隔离区
- internal:内部区域,信任网络中的大部分计算机
这个设计理念其实挺好的,特别是在复杂网络环境下。我之前维护过一个多网段的项目,不同网段的安全要求不一样,用firewalld的区域概念处理起来就很方便。
基本操作命令
#启动服务
systemctl start firewalld
#关闭服务
systemctl stop firewalld
# 查看防火墙状态
firewall-cmd --state
# 查看当前活动的区域
firewall-cmd --get-active-zones
# 查看默认区域
firewall-cmd --get-default-zone
# 设置默认区域
firewall-cmd --set-default-zone=public
# 开放端口(临时)
firewall-cmd --add-port=80/tcp
# 开放端口(永久)
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload
# 开放服务
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
# 查看已开放的端口
firewall-cmd --list-ports
# 查看已开放的服务
firewall-cmd --list-services
#查看当前活动区域的富规则
firewall-cmd --list-rich-rules
#查看特定区域的富规则
firewall-cmd --zone=public --list-rich-rules
这里有个坑要注意,firewalld的配置分为运行时配置和永久配置。运行时配置重启后就没了,永久配置需要加--permanent参数,然后reload才能生效。我刚开始就经常忘记加--permanent,配置完重启服务器就傻眼了。
高级功能
firewalld还支持一些高级功能,比如富规则(Rich Rules):
# 允许特定IP访问特定端口
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept'
# 拒绝特定IP段
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.2.0/24" reject'
# 端口转发
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" forward-port port="8080" protocol="tcp" to-port="80"'
这些富规则功能很强大,但是语法有点复杂,刚开始用的时候经常写错。
ufw - Ubuntu的简约之选
ufw全称是Uncomplicated Firewall,从名字就能看出来,它的设计理念就是简单易用。Ubuntu系统默认安装了ufw,但默认是关闭状态的。
简单直接的操作方式
# 启用防火墙
ufw enable
# 禁用防火墙
ufw disable
# 查看状态
ufw status
# 查看详细状态
ufw status verbose
# 允许端口
ufw allow 22
ufw allow 80/tcp
ufw allow 443/tcp
# 拒绝端口
ufw deny 23
# 删除规则
ufw delete allow 80
# 允许特定IP
ufw allow from 192.168.1.100
# 允许特定IP访问特定端口
ufw allow from 192.168.1.100 to any port 22
# 允许子网
ufw allow from 192.168.1.0/24
看到没有?ufw的命令就是这么直观,基本上看一遍就能记住。不像firewalld那样需要记一堆参数。
应用配置文件
ufw还有个很贴心的功能,就是预定义了很多应用的配置文件:
# 查看可用的应用配置
ufw app list
# 查看应用配置详情
ufw app info 'Nginx Full'
# 允许应用
ufw allow 'Nginx Full'
ufw allow 'OpenSSH'
这个功能对新手特别友好,不用去查各种服务需要开放哪些端口,直接用应用名称就行了。
默认策略设置
# 设置默认策略
ufw default deny incoming
ufw default allow outgoing
# 重置所有规则
ufw --force reset
实际使用场景对比
我在不同的项目中都用过这两个工具,总结一下使用感受:
Web服务器场景
如果是简单的Web服务器,只需要开放22、80、443这几个端口,用ufw就够了:
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable
三行命令搞定,简单粗暴。
用firewalld的话:
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
也不复杂,但是命令稍微长一点。
复杂网络环境
我之前维护过一个项目,有内网、外网、DMZ三个网段,不同网段的访问权限不一样。这种情况下firewalld的区域概念就很有用了:
# 内网接口设置为internal区域
firewall-cmd --permanent --zone=internal --change-interface=eth1
# DMZ接口设置为dmz区域
firewall-cmd --permanent --zone=dmz --change-interface=eth2
# 外网接口保持public区域
firewall-cmd --permanent --zone=public --change-interface=eth0
# 不同区域配置不同的规则
firewall-cmd --permanent --zone=internal --add-service=ssh
firewall-cmd --permanent --zone=dmz --add-port=8080/tcp
firewall-cmd --permanent --zone=public --add-service=http
用ufw处理这种场景就比较麻烦了,需要写很多具体的IP规则。
动态环境
firewalld支持动态修改规则,不需要重启防火墙服务。这在生产环境中很有用,特别是不能中断服务的场景。
ufw虽然也支持动态修改,但是某些复杂规则的修改可能需要重新加载。
性能和资源占用
说到性能,其实这两个工具都是iptables的前端,底层还是调用iptables来实现防火墙功能。所以性能差异主要体现在管理工具本身的开销上。
从我的使用经验来看,ufw的资源占用更小一些,毕竟设计理念就是简单。firewalld功能更丰富,相应的资源占用也会大一点,但差异不是很明显。
在高并发场景下,我测试过两者的性能差异,基本可以忽略不计。真正影响性能的是iptables规则的数量和复杂度,而不是用哪个管理工具。
配置文件和备份
firewalld的配置
firewalld的配置文件在/etc/firewalld/目录下:
# 查看配置文件结构
ls -la /etc/firewalld/
# zones/ # 区域配置
# services/ # 服务定义
# icmptypes/ # ICMP类型定义
备份firewalld配置很简单,直接打包整个目录:
tar -czf firewalld-backup.tar.gz /etc/firewalld/
ufw的配置
ufw的配置相对简单,主要文件在/etc/ufw/:
# 主要配置文件
/etc/ufw/ufw.conf # 主配置文件
/etc/ufw/before.rules # 预定义规则
/etc/ufw/after.rules # 后置规则
/etc/ufw/user.rules # 用户规则
备份ufw配置:
tar -czf ufw-backup.tar.gz /etc/ufw/
我踩过的坑
firewalld的坑
- 忘记reload:修改了永久配置忘记reload,规则不生效。这个坑我踩过无数次...
- 区域混乱:不同接口被分配到错误的区域,导致规则不生效。特别是多网卡服务器,一定要确认接口和区域的对应关系。
- 富规则语法错误:富规则的语法比较复杂,经常写错。建议先在测试环境验证。
ufw的坑
- 规则顺序:ufw的规则是按顺序匹配的,如果顺序不对可能导致规则不生效。比如先写了allow from anywhere,后面的deny规则就没用了。
- IPv6支持:默认情况下ufw会同时处理IPv4和IPv6,如果不需要IPv6要记得在配置文件中关闭。
- 应用配置文件冲突:有时候系统更新会覆盖应用配置文件,导致之前的规则失效。
迁移和兼容性
如果需要在firewalld和ufw之间切换,要注意几个问题:
从firewalld切换到ufw
# 停止并禁用firewalld
systemctl stop firewalld
systemctl disable firewalld
# 安装并启用ufw
apt install ufw # Ubuntu/Debian
ufw enable
从ufw切换到firewalld
# 停止ufw
ufw disable
# 安装并启用firewalld
yum install firewalld # CentOS/RHEL
systemctl enable firewalld
systemctl start firewalld
切换的时候记得先备份原有配置,然后手动迁移规则。自动迁移工具我没找到靠谱的,还是手动比较安全。
监控和日志
firewalld日志
firewalld的日志默认记录在系统日志中:
# 查看firewalld日志
journalctl -u firewalld
# 启用拒绝连接的日志记录
firewall-cmd --set-log-denied=all
ufw日志
ufw的日志配置:
# 启用日志
ufw logging on
# 设置日志级别
ufw logging medium
# 查看日志
tail -f /var/log/ufw.log
选择建议
经过这么多年的使用,我的建议是:
选择ufw的场景:
- 简单的Web服务器
- Ubuntu/Debian系统
- 团队技术水平参差不齐
- 快速部署需求
- 个人项目或小型项目
选择firewalld的场景:
- 复杂网络环境
- CentOS/RHEL系统
- 需要精细化权限控制
- 企业级应用
- 有专业运维团队
其实说到底,这两个工具都只是iptables的包装器,核心功能都能实现。关键是要根据自己的实际情况来选择。但是一般企业都会单独部署防火墙在边界!
一些实用技巧
firewalld实用技巧
快速查看所有配置:
# 这个命令能看到当前所有区域的详细配置
firewall-cmd --list-all-zones
我经常用这个命令来排查问题,特别是接手别人配置的服务器时。
临时测试规则:
# 先添加临时规则测试
firewall-cmd --add-port=9999/tcp
# 测试没问题再添加永久规则
firewall-cmd --permanent --add-port=9999/tcp
firewall-cmd --reload
这个习惯救过我好几次,避免了因为配置错误导致的服务中断。
批量操作:
# 一次性开放多个端口
for port in 80 443 8080 8443; do
firewall-cmd --permanent --add-port=${port}/tcp
done
firewall-cmd --reload
ufw实用技巧
规则编号管理:
# 查看带编号的规则列表
ufw status numbered
# 删除指定编号的规则
ufw delete 2
这个功能在管理大量规则时特别有用。
快速开放常用服务:
# 我常用的Web服务器配置
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw allow 'MySQL'
限制连接频率:
# 限制SSH连接频率,防止暴力破解
ufw limit ssh
这个功能很实用,相当于内置了fail2ban的部分功能。
故障排查经验
常见问题1:规则不生效
我遇到过好几次配置了规则但是不生效的情况:
firewalld排查步骤:
# 1. 确认服务状态
systemctl status firewalld
# 2. 检查接口所在区域
firewall-cmd --get-active-zones
# 3. 检查具体区域的规则
firewall-cmd --zone=public --list-all
# 4. 检查是否有冲突的富规则
firewall-cmd --list-rich-rules
ufw排查步骤:
# 1. 检查ufw状态
ufw status verbose
# 2. 检查规则顺序
ufw status numbered
# 3. 检查底层iptables规则
iptables -L -n
常见问题2:SSH连接断开
这个问题我刚开始经常遇到,特别是远程配置防火墙的时候。
预防措施:
# 方法1:使用at命令定时重置防火墙
echo "ufw disable" | at now + 10 minutes
# 方法2:先开放SSH再配置其他规则
ufw allow OpenSSH
ufw enable
常见问题3:服务无法访问
有时候防火墙规则看起来没问题,但服务还是无法访问:
排查思路:
- 确认服务本身是否正常运行
- 检查服务监听的IP和端口
- 确认防火墙规则是否正确
- 检查SELinux状态(CentOS/RHEL)
- 查看系统日志
# 检查端口监听状态
netstat -tlnp | grep :80
# 或者用ss命令
ss -tlnp | grep :80
# 检查SELinux状态
getenforce
与其他安全工具的配合
防火墙只是安全防护的一部分,通常需要配合其他工具:
与fail2ban配合
fail2ban可以动态添加防火墙规则来阻止恶意IP:
# fail2ban配置示例(/etc/fail2ban/jail.local)
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
与SELinux配合
在CentOS/RHEL系统上,SELinux提供了额外的安全层:
# 检查SELinux状态
sestatus
# 查看SELinux相关的端口策略
semanage port -l | grep http
云环境中的注意事项
现在很多服务都部署在云平台上,云环境中使用防火墙有一些特殊考虑:
AWS安全组
在AWS上,安全组本身就是防火墙,通常不需要在实例内部再配置防火墙。但如果需要更精细的控制,还是可以使用ufw或firewalld。
阿里云/腾讯云
国内云平台通常也有安全组功能,使用时要注意:
- 云平台安全组和系统防火墙不要冲突
- 优先使用云平台的安全组,系统防火墙作为补充
- 注意内网和外网的访问策略
容器环境中的防火墙
Docker和Kubernetes环境中的网络比较复杂:
Docker网络
Docker会自动修改iptables规则,可能与系统防火墙冲突:
# 查看Docker添加的iptables规则
iptables -L DOCKER-USER
Kubernetes网络策略
在K8s环境中,通常使用NetworkPolicy来控制Pod间的通信,而不是传统的防火墙。
写在最后
写了这么多,其实核心观点就是:工具没有绝对的好坏,关键是要选择适合自己场景的。
ufw胜在简单易用,适合快速上手和简单场景;firewalld功能更强大,适合复杂环境和精细化管理。
我的建议是:
- 如果你是新手,或者需求比较简单,选ufw
- 如果你需要复杂的网络策略,或者在企业环境中,选firewalld
- 不管选哪个,都要理解底层的iptables原理
- 一定要在测试环境先验证,再在生产环境部署
- 做好配置备份和文档记录
最重要的是,防火墙只是安全防护的一环,不要指望它解决所有安全问题。还需要配合其他安全措施,比如及时更新系统、使用强密码、启用日志监控等等。
安全是一个系统工程,需要多层防护。防火墙配置好了,只是万里长征走完了第一步。
如果这篇文章对你有帮助,别忘了点赞转发支持一下!想了解更多运维实战经验和技术干货,记得关注微信公众号@运维躬行录,领取学习大礼包!!!我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习,共同进步!
公众号:运维躬行录
个人博客:躬行笔记