Linux防火墙体系
Linux防火墙体系经过多年发展,目前主流的四种工具分别是iptables、nftables、firewalld和UFW。它们底层都基于内核的Netfilter框架,但设计哲学、操作方式和适用场景各有不同。
下面的对比表格可以帮你快速了解它们的核心差异:
| 特性 | iptables | nftables | firewalld | UFW |
|---|---|---|---|---|
| 核心定位 | 传统的底层规则管理工具 | iptables的现代替代品,新一代内核框架 | 动态防火墙管理服务(守护进程) | iptables/nftables的前端简化工具 |
| 设计哲学 | 基于表(tables)、链(chains)、规则(rules) 的线性匹配 | 基于声明式规则集(ruleset),引入集合(sets)、映射(maps) 等高级数据结构 | 基于区域(zones) 和服务(services) 的抽象管理 | 极简主义,命令接近自然语言,隐藏底层细节 |
| 主要优势 | 极其灵活,功能强大,支持复杂的NAT和包修改 | 性能更高(优化了规则遍历),语法更统一,支持动态更新和批量操作,可脚本化 | 动态管理:修改规则无需重启服务,不中断连接;区域化:为不同网络环境(如家庭、公共)快速切换策略集 | 简单易用:语法简洁,适合Linux初学者、桌面用户或快速配置基本策略 |
| 主要劣势 | 语法晦涩,规则变更通常需要全部重载,规则量大时性能下降 | 学习曲线陡峭,理解其声明式语法和数据结构需要一定时间 | 概念相对抽象,若需要配置非常底层的、复杂的NAT规则,不如直接操作iptables/nftables灵活 | 功能相对有限,不适合处理极其复杂的网络拓扑和防火墙策略 |
| 常见发行版 | 几乎所有Linux发行版,曾是RHEL 6/CentOS 6及更早版本的核心 | 较新发行版,如Debian 10+、Fedora、RHEL 9+已将其作为底层默认 | RHEL/CentOS 7+、Fedora的默认防火墙管理工具 | Ubuntu、Debian桌面的默认防火墙管理工具 |
| 底层关系 | 直接与Netfilter交互 | 直接与Netfilter交互,旨在完全替代iptables | 底层可以使用iptables或nftables作为后端 | 底层可以使用iptables或nftables作为后端 |
以下是每种工具的详细介绍:
🛠️ iptables:传统而强大的底层工具
iptables是Linux防火墙界的"老兵"。它直接与内核中的Netfilter框架对话,通过维护一系列规则来工作。这些规则被组织在表(如filter表用于过滤,nat表用于地址转换)和链(如INPUT、OUTPUT、FORWARD)中。
- 工作方式:当数据包到达时,它会按顺序遍历链中的规则,直到找到一条匹配的规则并执行相应的动作(如
ACCEPT或DROP)。这种线性匹配在规则数量庞大时可能会影响性能。 - 典型应用:非常适合需要精细控制的场景,例如配置复杂的端口转发、NAT(网络地址转换)策略,或者运行在老旧系统、嵌入式设备上。
🚀 nftables:iptables的现代继任者
为了解决iptables的一些固有限制(如语法混乱、性能瓶颈、代码重复),nftables应运而生。它也被设计为Linux内核的新一代包过滤框架。
- 核心理念:它将iptables中分散于IPv4、IPv6、ARP等不同协议的工具统一起来,使用相同的语法和内核API。它引入的"集合"和"映射"功能,可以极大地简化需要大量重复规则的场景。
- 性能优势:nftables采用更先进的规则集结构和虚拟机机制,在执行规则查找时更高效,尤其是在规则集很大的情况下。
- 适用场景:如果你正在部署一个全新的Linux服务器(如Debian 10+),希望获得更好的性能和现代化的管理方式,nftables是首选。
🔥 firewalld:动态区域管理专家
firewalld是Red Hat家族(RHEL/CentOS/Fedora)力推的防火墙管理工具。它最大的特点是动态和区域化。
- 动态管理:与iptables修改规则后通常需要全部重载不同,firewalld可以在不中断现有连接的情况下,即时应用规则更改。
- 区域(Zones):这是firewalld最核心的抽象概念。它将网络接口划分到不同的信任区域(如
public(公共)、home(家庭)、trusted(信任)),每个区域有一套预定义的安全策略。例如,你可以将家里的Wi-Fi接口分配给home区域,允许文件共享;而将咖啡店的公共Wi-Fi分配给public区域,只允许SSH连接。 - 适用场景:适合需要频繁调整防火墙规则,或者在不同网络环境间移动的笔记本电脑、服务器。其基于区域的管理模式非常适合构建安全的网络隔离环境。
😊 UFW:简单易用的代名词
UFW的名字"Uncomplicated Firewall"(不复杂的防火墙)就揭示了它的全部使命——让防火墙配置变得简单。
- 用户友好:它本质上是iptables(或nftables)的一个前端封装。你不必关心复杂的底层语法,只需使用类似
ufw allow 22/tcp(允许22端口)这样的命令即可。 - 应用集成:UFW还支持应用配置文件,你可以直接通过应用名来开放端口,如
sudo ufw allow 'Nginx Full',它会自动开放80和443端口。 -
适用场景:如果你是Linux新手、运维个人桌面电脑或一台只需要基本防护的VPS,UFW是最友好的选择,能帮你用最少的命令快速建立起一道安全防线。
下面,我详细讲解下nftables: 在
nftables中开放端口的核心是向对应的基链(如input链)添加一条accept规则。下面以最常见的inet地址家族(同时适用于 IPv4 和 IPv6)的filter表为例,演示如何添加规则。
1. 查看现有规则集(避免重复添加)
sudo nft list ruleset
2. 开放 TCP 端口(例如 80)
假设你已经有一个 inet filter 表,并且其中包含一个挂载在 input 钩子上的基链:
sudo nft add rule inet filter input tcp dport 80 accept
inet filter:指定表,inet表示同时处理 IPv4 和 IPv6,filter是表名(常用名,你也可以用自定义表名)。input:链名,必须是已存在的基链(类型为 filter,钩子为 input)。tcp dport 80:匹配条件,目标端口为 80 的 TCP 流量。accept:动作,允许通过。
3. 开放 UDP 端口(例如 53)
sudo nft add rule inet filter input udp dport 53 accept
4. 开放端口范围(例如 1000-2000)
sudo nft add rule inet filter input tcp dport 1000-2000 accept
5. 同时开放 TCP 和 UDP 的同一端口(例如 53)
可以分别添加两条规则,或使用集合简化:
# 分别添加
sudo nft add rule inet filter input tcp dport 53 accept
sudo nft add rule inet filter input udp dport 53 accept
# 或者使用集合(更简洁)
sudo nft add rule inet filter input meta l4proto { tcp, udp } th dport 53 accept
th dport 是传输层目标端口的通用表达式,适用于 TCP 和 UDP。
6. 如果表或链不存在,需要先创建
# 创建 inet 家族的 filter 表
sudo nft add table inet filter
# 创建 input 基链(类型 filter,钩子 input,优先级 0;默认策略可以先设为 accept 以免锁住自己)
sudo nft add chain inet filter input { type filter hook input priority 0 \; policy accept \; }
注意:在链中设置
policy accept表示默认允许,然后再添加drop规则来限制。更常见的做法是将默认策略设为drop,然后显式开放需要的端口。但若远程操作,请务必先添加允许自己当前连接的规则(如 SSH 端口),再将策略改为drop,以免失联。
规则持久化
上述命令添加的规则重启后会丢失。要使规则永久生效,需要将当前规则集保存到配置文件,并启用 nftables 服务。
-
保存规则:
bash复制sudo nft list ruleset > /etc/nftables.conf -
启用并启动服务:
bash复制sudo systemctl enable nftables.service sudo systemctl start nftables.service
之后每次开机都会自动加载 /etc/nftables.conf 中的规则。
常用变体
-
只针对特定源 IP 开放:
bash复制sudo nft add rule inet filter input ip saddr 192.168.1.0/24 tcp dport 22 accept -
记录日志后接受:
bash复制sudo nft add rule inet filter input tcp dport 80 log accept -
删除规则(按 handle 删除,handle 可通过
nft -a list ruleset查看):bash复制sudo nft delete rule inet filter input handle 3
提示
- 如果系统中没有
inet filter表(例如全新安装),add rule命令会失败,请先按第 6 点创建。 - 如果使用防火墙管理工具(如
firewalld或UFW)管理 nftables,建议通过它们添加规则,避免直接操作底层规则集造成冲突。
在 nftables 中实现“仅允许22端口,禁止其他所有入站流量”的核心策略是:设置默认丢弃(drop)策略,然后显式添加允许(accept)规则。
这里有两条路径可以达到目的:一是通过命令行快速配置,适合临时调试;二是通过编写脚本文件进行原子性加载,这是生产环境(尤其是远程操作)唯一推荐的安全方式。
💡 核心配置步骤
无论哪种方式,一个健壮的最小化安全规则集都至少包含以下三条规则,它们必须按此顺序出现在默认丢弃策略之前:
- 放行回环接口:确保本机内部通信正常。
- 放行已建立的连接:保证你当前SSH会话(以及后续响应)不会中断。
- 放行新的SSH连接:明确允许外部访问22端口。
🛠️ 方案一:命令行逐条添加(适合本地或测试环境)
如果你可以直接在机器前操作,或者想快速测试,可以按以下步骤执行。请注意,如果是远程操作,千万不要在最后一步之前执行设置默认策略的命令,否则会立刻断连!
# 1. 假设你已经有了 inet filter 表和 input 链(如果没有,参考上一轮回复创建)
# 2. 添加基础放行规则(顺序重要!)
sudo nft add rule inet filter input iifname "lo" accept
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input tcp dport 22 accept
# 3. 【高风险!远程操作慎行】将input链的默认策略设置为drop
# 只有在前三条规则成功添加后,才能执行这一步
sudo nft chain inet filter input '{ policy drop ; }'
# 4. 验证规则
sudo nft list ruleset
📜 方案二:脚本原子加载(生产环境标准)
这是最安全的方法。我们将所有规则写在一个文件中,然后一次性加载,整个过程是原子的,要么全部成功,要么失败回滚,不会出现中间状态导致断连。
-
创建规则文件 (例如
~/my-firewall.nft):bash复制cat > ~/my-firewall.nft << EOF #!/usr/sbin/nft -f # 原子性地清空当前所有规则 flush ruleset table inet filter { chain input { type filter hook input priority 0; policy drop; # 允许本地回环接口通信 iifname "lo" accept # 允许已建立的连接及相关连接(保证SSH会话不中断) ct state established,related accept # 明确放行 TCP 22 端口 (SSH) tcp dport 22 accept # (可选)在此处添加其他允许的规则,例如 80, 443 # tcp dport {http, https} accept # 所有未被上面规则匹配的流量,最终都会被链的默认策略 "drop" 处理 # 可以添加一条日志规则来记录被丢弃的包(调试用) # log prefix "Dropped by firewall: " counter drop } chain forward { type filter hook forward priority 0; policy drop; } chain output { type filter hook output priority 0; policy accept; } } EOF这段配置清晰地定义了我们的目标:默认丢弃输入,只开放22端口。
-
原子性加载规则:
bash复制sudo nft -f ~/my-firewall.nft这条命令会一次性应用整个规则集。如果文件中有语法错误,它会拒绝加载并保持你原有的防火墙状态,这是保护远程连接的关键。
-
验证并持久化:
bash复制# 查看当前生效的规则 sudo nft list ruleset # 如果一切正常,将其保存为系统启动时的默认规则 sudo cp ~/my-firewall.nft /etc/nftables.conf # 确保 nftables 服务已启用并启动 sudo systemctl enable nftables.service sudo systemctl start nftables.service
⚠️ 远程操作的“救命”提醒
- 永远不要在生产环境的SSH会话中单独执行清空或修改默认策略的命令(如
nft flush ruleset或nft chain ... policy drop;)。这会瞬间切断你的连接。 - 在加载任何新规则前,最好在另一个终端窗口保持一个到服务器的持久连接(如
screen或tmux会话),或者确保有带外管理控制台(如 iDRAC、IPMI、VNC)可用,以备不测。 - 规则加载成功后,务必先测试一下新的SSH连接,确认无误后再关闭当前的会话窗口。
你当前是通过SSH远程操作吗?如果是的话,强烈建议使用方案二来确保安全。