Linux 防火墙三国杀:ufw / firewalld / iptables / nftables 怎么选
很多人在 Linux 上配防火墙时是懵的:装了 ufw,又听说要用 iptables,新系统又说要换 nftables,红帽系上还有个 firewalld,到底是什么关系?
这篇先把它们的层级关系画清楚,然后再讲怎么选。
一、四层结构:从内核到用户
Linux 内核模块] --> P[网络包流过内核时
按规则放行 / 丢弃]
| 层级 | 角色 | 是什么 |
|---|---|---|
| 内核 | Netfilter | Linux 内核自带的包过滤框架,所有发行版都有 |
| 管理 | iptables / nftables 命令 | 用户态命令行工具,把你的规则翻译成内核能懂的语言 |
| 前端 | ufw / firewalld | 更友好的封装,帮你写 iptables/nftables 规则 |
核心结论:
- Netfilter 是内核功能,不可选,永远在。
- iptables vs nftables:iptables 是老工具,nftables 是 2014 年出现的替代品(语法更统一、性能更好)。新发行版默认都是 nftables(Ubuntu 20.04+、Debian 10+、CentOS 8+)。
- ufw vs firewalld:两者都是”前端”,只是不同发行版预装的不同:
| 发行版 | 默认预装 |
|---|---|
| Ubuntu / Debian 系 | ufw |
| CentOS / RHEL / Fedora 系 | firewalld |
| Arch | 都不装,用户自己选 |
💡 注意:ufw 和 firewalld 不绑定发行版,Ubuntu 上也能装 firewalld,Fedora 上也能装 ufw。
二、“假 iptables”:兼容层是怎么回事
新发行版上敲 iptables,它其实是 iptables-nft——把 iptables 语法翻译成 nftables 规则执行,底层根本不是真的 iptables。
iptables --version# iptables v1.8.7 (nf_tables) ← 兼容层(背后是 nftables)# iptables v1.8.7 (legacy) ← 真正的 iptables🪤 这就是为什么有时候用老教程的
iptables命令在新系统上行为不一致——你以为是 iptables,其实是 nftables 翻译过来的。
三、“为什么 ufw 显示没规则,但还是有规则在拦截?”
这是新手最高频的疑问,答案是:
✅ ufw 只管 ufw 自己写入的规则。Docker、fail2ban 等程序会直接往 iptables/nftables 里写规则,ufw 看不到。
# ufw 看到的(只是 ufw 自己的)sudo ufw status
# iptables 看到的(所有规则,包括 docker、fail2ban 写的)sudo iptables -L -n -vsudo iptables -t nat -L -n -v
# nftables 看到的(新发行版)sudo nft list ruleset实战中最常踩的两个例子:
| 现象 | 原因 |
|---|---|
ufw deny 80 了,docker 容器还能从公网访问 | Docker 自己在 nat 表里写了 DNAT 规则,绕开了 ufw 的 INPUT 链 |
| fail2ban 封了 IP,但 ufw status 看不到 | fail2ban 走的是自己创建的链 |
四、规则的持久化
| 工具 | 持久化方式 |
|---|---|
| ufw | 自带(重启自动恢复) |
| firewalld | 自带(runtime + permanent 双套规则) |
| 裸 iptables | 默认重启清空,需装 iptables-persistent |
| 裸 nftables | 默认重启清空,需写入 /etc/nftables.conf |
iptables-persistent 的配置文件:
/etc/iptables/rules.v4 # IPv4 规则/etc/iptables/rules.v6 # IPv6 规则apt purge iptables-persistent会删除上面的配置文件。apt remove iptables-persistent会保留配置文件,下次重装能复用。
五、ufw 速查(最推荐新手用)
ufw(Uncomplicated Firewall)是 Debian/Ubuntu 上最简单的防火墙前端,但它在所有 Linux 上都能装。
5.1 基础操作
# 启用 / 关闭sudo ufw enablesudo ufw disable
# 看状态sudo ufw statussudo ufw status numbered # 带规则编号(删除时用)
# 重新加载sudo ufw reload
# 重置(清空所有规则)sudo ufw --force reset5.2 默认策略
# 默认拒绝所有入站(强烈推荐)sudo ufw default deny incoming
# 默认允许所有出站sudo ufw default allow outgoing5.3 添加规则
# 按端口sudo ufw allow 22sudo ufw allow 80/tcpsudo ufw allow 443
# 按服务名(看 /etc/services)sudo ufw allow ssh
# 按 IP 限制sudo ufw allow from 192.168.1.100sudo ufw allow from 192.168.1.100 to any port 22
# 拒绝sudo ufw deny 225.4 删除规则
# 按编号删(先用 numbered 查编号)sudo ufw status numberedsudo ufw delete 3
# 按内容删sudo ufw delete allow 80sudo ufw delete deny 225.5 典型 VPS 配置
sudo ufw default deny incomingsudo ufw default allow outgoingsudo ufw allow 22000/tcp # 改了的 SSH 端口sudo ufw allow 80/tcpsudo ufw allow 443/tcpsudo ufw allow from <办公室 IP> to any port 9090 # 面板限制 IPsudo ufw enable六、firewalld 速查
红帽系上常见,特点是”区域(zone)“概念:
# 状态sudo firewall-cmd --statesudo systemctl status firewalld
# 看当前 zonesudo firewall-cmd --get-default-zonesudo firewall-cmd --get-active-zones
# 看 zone 里的规则sudo firewall-cmd --list-all
# 加端口(runtime + 永久)sudo firewall-cmd --add-port=8080/tcpsudo firewall-cmd --add-port=8080/tcp --permanent
# 加服务sudo firewall-cmd --add-service=http --permanent
# 重新加载sudo firewall-cmd --reload
# 删除规则sudo firewall-cmd --remove-port=8080/tcp --permanent⚠️ firewalld 区分 runtime 和 permanent,不加
--permanent重启就丢,改完都要firewall-cmd --reload。
七、原生 nftables 速查
新系统的”正经”方式:
# 看所有规则sudo nft list ruleset
# 看某个表sudo nft list table inet filter
# 加一个 inet 类型的 filter 表sudo nft add table inet filter
# 加 input 链(默认 drop)sudo nft add chain inet filter input { type filter hook input priority 0\; policy drop\; }
# 允许已建立的连接sudo nft add rule inet filter input ct state established,related accept
# 允许 SSHsudo nft add rule inet filter input tcp dport 22 accept
# 保存到 /etc/nftables.conf(持久化)sudo nft list ruleset > /etc/nftables.confsudo systemctl enable --now nftables/etc/nftables.conf 完整模板:
#!/usr/sbin/nft -f
flush ruleset
table inet filter { chain input { type filter hook input priority 0; policy drop; ct state established,related accept iifname lo accept tcp dport 22 accept tcp dport { 80, 443 } accept } chain forward { type filter hook forward priority 0; policy drop; } chain output { type filter hook output priority 0; policy accept; }}八、原生 iptables 速查
老系统 / 兼容层都能用:
# 看规则sudo iptables -L -n -v --line-numbers
# 清空规则sudo iptables -Fsudo ip6tables -F
# 设置默认策略sudo iptables -P INPUT DROPsudo iptables -P FORWARD DROPsudo iptables -P OUTPUT ACCEPT
# 允许 loopbacksudo iptables -A INPUT -i lo -j ACCEPT
# 允许已建立连接sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 允许 SSH / HTTP / HTTPSsudo iptables -A INPUT -p tcp --dport 22 -j ACCEPTsudo iptables -A INPUT -p tcp --dport 80 -j ACCEPTsudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 保存(需要 iptables-persistent)sudo netfilter-persistent save九、如何选
| 场景 | 推荐 |
|---|---|
| 新手 / 简单 VPS | ufw |
| 红帽系生产环境 | firewalld |
| 容器 / 复杂规则 / 写脚本 | 直接 nftables |
| 维护老系统 | iptables |
| 想要可视化 / 配合面板 | 装 ufw 让 1Panel/宝塔托管 |
💡 不要同时启用 ufw 和 firewalld。两者会互相冲突,规则乱掉之后排查是噩梦。
十、清掉所有”奇怪规则”的标准动作
VPS 拿到手发现防火墙规则乱七八糟想从头开始时:
# 1. 停掉 / 卸载所有防火墙前端sudo systemctl stop ufwsudo systemctl disable ufwsudo apt purge -y iptables-persistent ufw
# 2. 清空内存中的规则sudo iptables -Fsudo iptables -Xsudo iptables -t nat -Fsudo iptables -t nat -Xsudo ip6tables -Fsudo ip6tables -X
# 3. 重置默认策略为 ACCEPT(避免清空后断 SSH)sudo iptables -P INPUT ACCEPTsudo iptables -P FORWARD ACCEPTsudo iptables -P OUTPUT ACCEPT
# 4. 重启确认sudo reboot
# 5. 重启后再装回想用的工具sudo apt install -y ufw⚠️ 清空策略前先把 INPUT 默认改成 ACCEPT,否则一清空就断 SSH,下场是去厂商面板用 VNC 救机器。
十一、几条实用经验
- VPS 上配防火墙顺序:先 allow SSH 再 enable,反着来就是自己锁外面了。
- 改 SSH 端口务必同步加防火墙规则,否则改完 ssh -p 新端口连不上。
- Docker 容器端口对外可达是 Docker 自己写的 iptables 规则,不归 ufw 管——要限制 Docker 容器对外暴露,得改 docker-compose 的 ports 写法(绑 127.0.0.1)。
- fail2ban 的封禁也是直接写 iptables,看封禁状态用
fail2ban-client status sshd,不是 ufw status。 - 新系统直接学 nftables 就行,iptables 是历史包袱。
理解到这个层级,再去看任何”防火墙规则没生效”的问题,都能直接定位到底是哪一层在拦。