防火墙之ufw与firewall
2026-02-14
运维
00
请注意,本文编写于 49 天前,最后修改于 5 天前,其中某些信息可能已经过时。

目录

一、Linux 防火墙技术演进史
1.1 三代内核框架
1.2 用户层工具的适配
二、ufw:Ubuntu 的极简防火墙
2.1 架构深度解析
2.2 核心配置文件
2.3 实战命令详解
端口放行(最常用)
源 IP 控制(白名单/黑名单)
连接速率限制(防暴力破解)
默认策略与开关
规则管理
日志管理
2.4 ufw 高级技巧
自定义应用配置
与 Docker 的冲突解决
三、firewalld:RHEL 生态的动态防火墙
3.1 架构设计理念
3.2 核心概念:Zone(区域)
3.3 实战命令详解
端口放行(运行时 vs 永久)
源 IP 控制(富规则 Rich Rules)
连接速率限制
服务(Service)抽象
默认策略与区域
日志管理
完全重置
四、ufw vs firewalld:深度对比
4.1 选型建议
五、底层探秘:nftables 原生操作
5.1 查看翻译后的规则
5.2 直接操作 nftables(高级)
六、故障排查速查表

一、Linux 防火墙技术演进史

1.1 三代内核框架

年代框架特点现状
2000iptables基于 netfilter 钩子,规则链遍历,O(n) 性能维护模式,逐步废弃
2014nftables原生集成功能,规则集优化,O(1) 性能,统一 IPv4/IPv6当前内核标准
2019+bpfiltereBPF 驱动,用户态处理,极致性能实验阶段,未普及

1.2 用户层工具的适配

展开代码
用户命令 │ ├──► ufw (Ubuntu) ──► iptables 语法 ──► iptables-nft ──► nftables 内核 │ ├──► firewalld (RHEL) ──► 直接生成 nftables 规则 ──► nftables 内核 │ └──► iptables 传统命令 ──► xtables-nft 兼容层 ──► nftables 内核

关键认知:现代 Linux 发行版(Ubuntu 22.04+、RHEL 8+、Debian 11+)内核已没有传统 iptables,所有 iptables 命令都通过 iptables-nft 翻译成 nftables 执行。


二、ufw:Ubuntu 的极简防火墙

2.1 架构深度解析

展开代码
┌─────────────────────────────────────────┐ │ 用户层:ufw CLI │ │ ufw allow 22/tcp │ │ ufw deny from 10.0.0.100 │ └─────────────────┬───────────────────────┘ │ Python 解析 ▼ ┌─────────────────────────────────────────┐ │ 配置层:/lib/ufw/*.rules │ │ -A ufw-user-input -p tcp --dport 22 -j ACCEPT │ -A ufw-user-input -s 10.0.0.100 -j DROP └─────────────────┬───────────────────────┘ │ 调用 /usr/sbin/iptables ▼ ┌─────────────────────────────────────────┐ │ 翻译层:iptables-nft │ │ 将 iptables 语法转换为 nftables 对象: │ add rule ip filter ufw-user-input tcp dport 22 accept └─────────────────┬───────────────────────┘ │ netlink 套接字 ▼ ┌─────────────────────────────────────────┐ │ 内核层:nftables │ │ 真正的包过滤执行引擎 │ └─────────────────────────────────────────┘

2.2 核心配置文件

文件作用修改建议
/etc/ufw/ufw.conf全局开关、日志级别一般不动
/etc/ufw/before.rulesufw 规则之前执行(如 NAT)高级自定义
/etc/ufw/after.rulesufw 规则之后执行(如特殊日志)高级自定义
/etc/ufw/user.rules用户规则主文件(ufw 命令生成)手动编辑需谨慎
/etc/ufw/applications.d/应用配置文件(如 OpenSSH、Nginx)可自定义服务名

2.3 实战命令详解

端口放行(最常用)

展开代码
# 单行放行,立即生效(无需 reload) sudo ufw allow 22/tcp # 多端口逗号分隔 sudo ufw allow 80,443/tcp # 整个区间(如被动模式 FTP) sudo ufw allow 1:65535/udp # 指定 IP + 端口 sudo ufw allow from 192.168.1.10 to any port 3306 # 查看生成的 nftables 规则 sudo nft list chain ip filter ufw-user-input # 输出: # chain ufw-user-input { # tcp dport 22 accept # tcp dport { 80, 443 } accept # udp dport 1-65535 accept # }

源 IP 控制(白名单/黑名单)

展开代码
# 放行整个网段的所有端口(管理网) sudo ufw allow from 192.168.5.0/24 # 仅允许特定 IP 访问数据库 sudo ufw allow from 10.0.0.50 to any port 3306 proto tcp # 显式拒绝(优先级高于 allow,日志记录) sudo ufw deny from 10.0.0.100 # 插入到特定位置(第 3 条规则) sudo ufw insert 3 allow from 172.16.0.0/12

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

展开代码
# SSH 防暴力:30 秒内≥6 次连接,后续 DROP sudo ufw limit 22/tcp # 自定义 HTTP API 限速 sudo ufw limit 8080/tcp # 查看生成的 limit 规则 sudo nft list chain ip filter ufw-user-limit # 输出: # chain ufw-user-limit { # limit rate 6/minute burst 5 packets accept # log prefix "[UFW LIMIT BLOCK] " level 4 # drop # }

原理说明limit 使用 nftables 的 meter 对象,基于令牌桶算法,比传统 fail2ban 更轻量。

默认策略与开关

展开代码
# 外网主动进入全丢弃(最安全的默认) sudo ufw default deny incoming # 本机出站全放行(通常如此) sudo ufw default allow outgoing # 转发包拒绝并回 ICMP(禁止当路由器) sudo ufw default reject routed # 启用防火墙(首次会提示可能断开 SSH,确认 y) sudo ufw enable # 开机自启 sudo systemctl enable ufw # 完全禁用(清空所有规则) sudo ufw disable

规则管理

展开代码
# 查看带编号的规则列表 sudo ufw status numbered # 删除第 5 条规则 sudo ufw delete 5 # 删除特定规则(需完全匹配) sudo ufw delete allow from 192.168.5.0/24 # 重置为初始状态(危险!) sudo ufw reset

日志管理

展开代码
# 启用日志(默认 low,只记录被阻止的新连接) sudo ufw logging on # 详细日志(记录所有匹配,慎用,磁盘压力大) sudo ufw logging high # 关闭日志 sudo ufw logging off # 实时查看 UFW 日志 sudo journalctl -k -f | grep UFW # 或 sudo tail -f /var/log/ufw.log

2.4 ufw 高级技巧

自定义应用配置

展开代码
# 创建自定义服务定义 sudo tee /etc/ufw/applications.d/custom-app <<'EOF' [CustomApp] title=My Custom Application description=This is a custom service running on port 8080 and 8443 ports=8080,8443/tcp EOF # 使用应用名放行 sudo ufw allow 'CustomApp' # 查看所有应用 sudo ufw app list

与 Docker 的冲突解决

Docker 默认绕过 ufw,直接操作 iptables。解决方案:

展开代码
# 方案 1:修改 Docker 默认行为 sudo tee /etc/docker/daemon.json <<'EOF' { "iptables": false } EOF sudo systemctl restart docker # 然后手动用 ufw 放行 Docker 端口 # 方案 2:使用 ufw-docker 工具 sudo wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker sudo chmod +x /usr/local/bin/ufw-docker sudo ufw-docker install

三、firewalld:RHEL 生态的动态防火墙

3.1 架构设计理念

firewalld 与 ufw 的最大区别:firewalld 直接生成 nftables 规则,跳过 iptables 翻译层,且支持 动态区域(zone)运行时/永久配置分离

展开代码
┌─────────────────────────────────────────┐ │ 用户层:firewall-cmd │ │ firewall-cmd --add-port=3000/tcp │ │ firewall-cmd --reload │ └─────────────────┬───────────────────────┘ │ D-Bus 调用 ▼ ┌─────────────────────────────────────────┐ │ 守护进程:firewalld │ │ - 解析 XML 配置 │ │ - 管理 zone、service、rich rules │ │ - 直接生成 nftables 规则 │ └─────────────────┬───────────────────────┘ │ netlink 套接字 ▼ ┌─────────────────────────────────────────┐ │ 内核层:nftables │ │ 真正的包过滤执行引擎 │ └─────────────────────────────────────────┘

3.2 核心概念:Zone(区域)

Zone信任度默认用途
drop最低丢弃所有进入,无响应
block极低拒绝进入,回 ICMP
public公共 Wi-Fi,仅放行 SSH/DHCP
external对外路由器,启用 NAT
internal中高内网,放行更多服务
trusted最高完全信任,放行所有

3.3 实战命令详解

端口放行(运行时 vs 永久)

展开代码
# 仅运行时生效(重启丢失) sudo firewall-cmd --add-port=3000/tcp # 永久生效(写入 XML,需 reload) sudo firewall-cmd --permanent --add-port=3000/tcp sudo firewall-cmd --reload # 多端口 sudo firewall-cmd --permanent --add-port={8080,8443}/tcp # 范围端口 sudo firewall-cmd --permanent --add-port=60000-61000/tcp

关键区别--permanent 只修改配置文件,必须 reload 才生效;这是 firewalld 与 ufw 的最大 UX 差异。

源 IP 控制(富规则 Rich Rules)

firewalld 的富规则比 ufw 更强大,支持 优先级、时间限制、日志级别

展开代码
# 整网段放行任何端口 sudo firewall-cmd --permanent \ --add-rich-rule='rule family="ipv4" source address=192.168.10.0/24 accept' # 仅允许特定 IP 访问 MySQL sudo firewall-cmd --permanent \ --add-rich-rule='rule family="ipv4" source address=10.0.0.50 port port=3306 protocol=tcp accept' # 拒绝恶意 IP(带日志) sudo firewall-cmd --permanent \ --add-rich-rule='rule family="ipv4" source address=192.168.66.100 log prefix="DROP: " level="notice" drop' # 时间限制(工作时间放行) sudo firewall-cmd --permanent \ --add-rich-rule='rule family="ipv4" source address=10.0.0.0/24 service name=ssh accept limit value="2/m"'

连接速率限制

展开代码
# 防暴力破解:30 秒内≥6 次连接 3000/tcp,DROP sudo firewall-cmd --permanent \ --add-rich-rule='rule family="ipv4" port port=3000 protocol=tcp limit value="6/m" accept' # 查看生成的 nftables 规则 sudo nft list chain inet firewalld filter_IN_public_allow

服务(Service)抽象

展开代码
# 查看预定义服务 sudo firewall-cmd --get-services # 输出:ssh dhcpv6-client http https mysql postgresql ... # 放行服务(比端口更语义化) sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https # 自定义服务 sudo tee /etc/firewalld/services/custom-app.xml <<'EOF' <?xml version="1.0" encoding="utf-8"?> <service> <short>Custom App</short> <description>My application on 8080 and 8443</description> <port protocol="tcp" port="8080"/> <port protocol="tcp" port="8443"/> </service> EOF sudo firewall-cmd --reload sudo firewall-cmd --permanent --add-service=custom-app

默认策略与区域

展开代码
# 查看当前生效配置 sudo firewall-cmd --list-all # 输出解析见下方 # 修改默认区域 sudo firewall-cmd --set-default-zone=drop # 网卡绑定到特定区域 sudo firewall-cmd --permanent --zone=internal --change-interface=eth1 # 修改区域默认动作 sudo firewall-cmd --permanent --zone=public --set-target=DROP

--list-all 输出详解

展开代码
public (active) # 当前生效的区域名称 target: default # 默认动作:default/ACCEPT/DROP/REJECT icmp-block-inversion: no # ICMP 是否反向阻止 interfaces: ens18 # 绑定的网卡 sources: # 源地址白名单/黑名单 services: ssh dhcpv6-client http # 放行的服务 ports: 3000/tcp 8080-8090/udp # 单独放行的端口 protocols: # 放行的协议(如 gre) forward: yes # 是否允许 IP 转发 masquerade: no # 是否启用 SNAT(源地址转换) forward-ports: # 端口转发(DNAT) source-ports: # 源端口限制 icmp-blocks: # 阻止的 ICMP 类型 rich rules: # 富规则列表(按优先级) rule family="ipv4" source address=192.168.10.0/24 accept rule family="ipv4" source address=10.0.0.100 drop

日志管理

展开代码
# 记录所有被拒绝的包 sudo firewall-cmd --set-log-denied=all # 仅记录特定区域 sudo firewall-cmd --zone=public --set-log-denied=unicast # 关闭日志 sudo firewall-cmd --set-log-denied=off # 实时查看 sudo journalctl -k -f | grep -E "REJECT|DROP"

完全重置

展开代码
# 停止服务 sudo systemctl stop firewalld # 清空所有配置 sudo rm -rf /etc/firewalld/zones/* sudo rm -rf /etc/firewalld/services/custom-* # 恢复默认并重启 sudo firewall-cmd --reset-to-defaults sudo systemctl start firewalld

四、ufw vs firewalld:深度对比

维度ufwfirewalld
设计目标极简、快速上手企业级、动态管理
默认发行版Ubuntu、DebianRHEL、CentOS、Fedora、SUSE
配置语法类英文(allow 22/tcp参数式(--add-port=22/tcp
生效方式立即生效运行时立即,永久需 reload
底层路径ufw → iptables → nftablesfirewalld → 直接 nftables
区域概念❌ 无✅ 多 zone,动态切换
运行时/永久分离❌ 无(所有规则立即持久化)✅ 明确分离,安全测试
富规则能力基础(IP、端口、limit)强大(时间、优先级、日志、icmp)
服务抽象简单(applications.d)完善(XML 定义,内置 100+)
IPv6 支持自动,同规则自动,同规则
NAT/端口转发需手动编辑 before.rules原生支持(--add-forward-port
与 Docker 集成冲突较多相对友好
学习曲线平缓陡峭但功能更强

4.1 选型建议

场景推荐理由
个人服务器/VPSufw三条命令搞定,不折腾
Ubuntu 云主机ufw官方支持,文档丰富
RHEL/CentOS 企业环境firewalldSELinux 集成,审计合规
需要动态区域切换firewalldzone 机制,网络环境变化自动适配
复杂 NAT/端口转发firewalld原生支持,无需手写规则
容器化环境(K8s)直接 nftablesCilium绕过用户层工具,性能最优

五、底层探秘:nftables 原生操作

5.1 查看翻译后的规则

展开代码
# 查看 ufw 生成的 nftables 规则 sudo nft list ruleset | grep -A20 "chain ufw-user-input" # 查看 firewalld 生成的 nftables 规则 sudo nft list ruleset | grep -A20 "chain filter_IN_public" # 完整规则集 sudo nft list ruleset > /tmp/nftables-rules.txt

5.2 直接操作 nftables(高级)

展开代码
# 创建表和链 sudo nft add table inet my_filter sudo nft add chain inet my_filter my_input { type filter hook input priority 0 \; policy drop \; } # 添加规则 sudo nft add rule inet my_filter my_input tcp dport 22 accept sudo nft add rule inet my_filter my_input ip saddr 192.168.1.0/24 accept # 查看 sudo nft list table inet my_filter

六、故障排查速查表

现象排查命令解决
规则不生效sudo nft list ruleset检查是否有 DROP 在前
ufw 启动失败sudo ufw status verbose检查 before.rules 语法
firewalld reload 报错sudo firewall-cmd --check-config检查 XML 语法
Docker 端口绕过防火墙sudo iptables -t nat -L -n禁用 Docker iptables 或 ufw-docker
日志不记录`sudo dmesggrep -i nft`
连接数暴涨sudo ss -s / `sudo conntrack -Lwc -l`

本文作者:zzz

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!