nftables 详解
nftables 是 Linux 内核 Netfilter 项目的下一代包过滤框架。它旨在逐步取代传统的
iptables(以及ip6tables,arptables,ebtables) 工具集,提供一个统一的、高效的、更易于管理和扩展的防火墙解决方案。nftables 引入了一套全新的语法和设计理念,旨在解决 iptables 长期存在的一些问题,例如命令复杂性、重复代码以及 IPv4 和 IPv6 规则管理的独立性等。
核心思想:基于表达式的统一规则集,支持原子性更新,并针对 IPv4/IPv6/桥接等协议提供统一管理。 它的设计哲学是从指令式规则集转向声明式通用虚拟机指令,使得规则处理更高效、更灵活。
一、为什么需要 nftables?iptables 的局限性
虽然 iptables 强大且稳定,但它在设计和使用上存在一些固有的局限性,促使 Netfilter 社区开发 nftables:
语法复杂且碎片化:
iptables(用于 IPv4)、ip6tables(用于 IPv6)、arptables(用于 ARP)、ebtables(用于以太网帧)。每种协议一套独立的工具和规则集,增加了学习和管理的复杂度。- 每个表 (
filter,nat,mangle,raw) 和链 (INPUT,OUTPUT,FORWARD,PREROUTING,POSTROUTING) 都有固定的用途和位置,缺乏灵活性。
性能瓶颈与规则重复:
- 规则是顺序匹配的,当规则集非常庞大时,性能会下降。
- 在多个表中可能需要重复定义类似的匹配条件,增加了内存占用和管理负担。
缺乏原子性操作:
- iptables 每次添加/删除一条规则都是一个独立操作,若要一次性应用大批规则,可能导致短时间内的网络中断或不一致状态。
模块化不足:
- 新的匹配条件和目标需要作为内核模块加载,并且通常在用户空间也需要对应的扩展,增加了开发和维护难度。
nftables 应运而生,致力于解决这些问题,提供一个更现代、更高效的防火墙管理机制。
二、nftables 的核心概念
nftables 采用了一种全新的、基于字节码的过滤引擎,其核心概念包括:
2.1 表 (Tables)
在 nftables 中,表是规则集的最顶层容器,可以根据用户的需求创建任意数量的表。一个表可以包含:
地址族 (Address Family):指定表适用的网络协议类型。
- 最常见的是
ip(IPv4),ip6(IPv6),inet(同时适用于 IPv4 和 IPv6),bridge(以太网桥),arp(ARP 协议),netdev(网络设备,用于在数据包进入网络堆栈之前处理,如流量分类)。 - 通过
inet地址族,可以为 IPv4 和 IPv6 编写一套统一的规则,极大地简化了双栈网络的管理。
- 最常见的是
链 (Chains):表内包含用户自定义的链,链中包含具体的规则。
命令示例:
1 | # 创建一个名为 'my_table' 的 inet 表 |
2.2 链 (Chains)
与 iptables 的预定义链不同,nftables 中的链有两种类型:
基本链 (Base Chains):
- 直接挂载到 Netfilter 的特定钩子点 (Hook Points) 上。
- 这些钩子点与 iptables 的链位置类似:
prerouting,input,forward,output,postrouting。 - 基本链需要指定其类型 (Type) (
filter,nat,route) 和优先级 (Priority)。type filter:用于过滤和丢弃数据包。type nat:用于地址转换 (SNAT/DNAT)。type route:用于在路由决策后修改目的地址(不常用)。
- 优先级决定了在同一个钩子点上,不同链的执行顺序。
- 命令示例:
1
2
3# 在 'my_table' 表中创建一个名为 'input_chain' 的基本链
# 挂载到 input 钩子点,类型为 filter,优先级为 0 (标准过滤)
sudo nft add chain inet my_table input_chain { type filter hook input priority 0 \; }
常规链 (Regular Chains):
- 不直接挂载到钩子点,只包含规则。
- 通过其他链的
jump或goto动作来调用。 - 用途:实现规则的模块化和复用,例如将所有关于 SSH 的规则放在一个单独的常规链中。
- 命令示例:
1
2# 在 'my_table' 表中创建一个名为 'ssh_rules' 的常规链
sudo nft add chain inet my_table ssh_rules
2.3 规则 (Rules)
规则是 nftables 的核心,由匹配条件 (Matches) 和语句 (Statements) 组成。nftables 的规则语法是基于表达式的,更加灵活强大。
- 匹配条件:可以匹配各种数据包字段。
ip saddr <source_ip>:源 IP 地址ip daddr <destination_ip>:目的 IP 地址tcp dport <destination_port>:目的 TCP 端口iif <interface>:入站接口oif <interface>:出站接口meta l4proto <protocol>:四层协议 (tcp, udp, icmp)ct state <state>:连接跟踪状态 (new, established, related, invalid)- 集合 (Sets):nftables 引入了强大的集合功能,可以将 IP 地址、端口、MAC 地址等放入集合中,然后在规则中高效地匹配。这比 iptables 中
--source或--destination每次都列举地址列表的效率更高。- 命令示例:
1
2
3
4
5
6# 定义一个名为 'whitelist_ips' 的 IPv4 地址集合
sudo nft add set inet my_table whitelist_ips { type ipv4_addr \; flags interval \; }
# 向集合添加 IP 地址
sudo nft add element inet my_table whitelist_ips { "192.168.1.10", "192.168.1.20" }
# 在规则中使用集合
sudo nft add rule inet my_table input_chain ip saddr @whitelist_ips accept
- 命令示例:
- 动作 (Statements):数据包匹配规则后执行的操作。
accept:允许数据包通过。drop:默默丢弃数据包。reject:丢弃数据包并返回错误信息。log:记录日志。counter:为规则添加计数器,统计匹配的包和字节。snat,dnat,masquerade:NAT 操作。jump <chain>:跳转到另一个常规链,处理完毕后返回。goto <chain>:跳转到另一个常规链,不返回。return:返回到调用链或上层。
命令示例:
1 | # 允许 loopback 接口的流量 |
三、nftables 常用操作命令
nft 是 nftables 的命令行工具。
3.1 查看和列出规则
sudo nft list tables:列出所有表。sudo nft list table inet my_table:列出指定表中的所有内容(链和规则)。sudo nft list ruleset:列出整个规则集(所有表、链、规则)。sudo nft -a list ruleset:显示更详细的信息,包括句柄 (handle),方便删除或修改。sudo nft list chain inet my_table input_chain:列出指定链中的规则。
3.2 添加和插入规则
- 添加表/链:
1
2sudo nft add table inet my_table
sudo nft add chain inet my_table input_chain { type filter hook input priority 0 \; } - 添加规则 (
add rule默认添加到链的末尾):1
2
3
4# 允许已建立和相关联的连接
sudo nft add rule inet my_table input_chain ct state established,related accept
# 允许所有来自 192.168.1.0/24 网段的 TCP 80 端口访问
sudo nft add rule inet my_table input_chain ip saddr 192.168.1.0/24 tcp dport 80 accept - 插入规则 (
insert rule默认插入到链的开头,也可指定位置):1
2
3
4# 在链的开头插入规则
sudo nft insert rule inet my_table input_chain ip saddr 127.0.0.1 accept
# 在指定句柄 (handle) 之前插入规则 (先用 nft -a list ruleset 查 handle)
# sudo nft insert rule inet my_table input_chain handle 123 ip saddr 10.0.0.1 accept
3.3 删除规则
- 删除表:
sudo nft delete table inet my_table - 删除链:
sudo nft delete chain inet my_table input_chain - 删除规则 (两种方式):
- 按句柄 (handle) 删除 (推荐):
sudo nft delete rule inet my_table input_chain handle 123 - 按规则内容删除:
sudo nft delete rule inet my_table input_chain tcp dport 22 accept(必须精确匹配规则内容)
- 按句柄 (handle) 删除 (推荐):
3.4 清空规则
- 清空表中的所有链和规则:
sudo nft flush table inet my_table - 清空链中的所有规则:
sudo nft delete rule inet my_table input_chain(等同于flush chain)
3.5 NAT 规则示例 (SNAT/DNAT)
场景描述:
- 路由器/防火墙:公网 IP
203.0.113.10(接口eth0),内网 IP192.168.1.1(接口eth1) - 内部 Web 服务器:
192.168.1.100,提供 HTTP 服务 (端口 80)。
DNAT (端口转发):将外部访问
203.0.113.10:80的请求转发到192.168.1.100:80。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 启用 IP 转发
sudo sysctl -w net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1
# 创建一个 inet 表用于 NAT 规则
sudo nft add table inet nat_table
# 创建 DNAT 基本链
sudo nft add chain inet nat_table prerouting { type nat hook prerouting priority -100 \; } # priority -100 是标准的 prerouting NAT 优先级
# 创建 SNAT / Masquerade 基本链
sudo nft add chain inet nat_table postrouting { type nat hook postrouting priority 100 \; } # priority 100 是标准的 postrouting NAT 优先级
# 添加 DNAT 规则
# 当目的地是公网接口的公网 IP,且端口为 80 的 TCP 连接,执行 DNAT
sudo nft add rule inet nat_table prerouting iifname "eth0" ip daddr 203.0.113.10 tcp dport 80 dnat to 192.168.1.100:80
# 添加 SNAT 规则 (确保内部服务器的回包能正确返回给外部客户端)
# 当源 IP 是内部服务器,且出站接口是公网接口时,执行 masquerade (自动获取公网 IP 作为源 IP)
sudo nft add rule inet nat_table postrouting oifname "eth0" ip saddr 192.168.1.100 masquerade注:nftables 通常会默认启用
filter表,其forward链的默认策略可能为accept,所以无需像 iptables 那样显式添加FORWARD规则,但最佳实践仍是配置明确的filter规则。
四、持久化 nftables 规则
nftables 规则默认不持久化,系统重启后会丢失。需要将规则保存到文件,并在系统启动时加载。
保存规则到文件:
1
sudo nft list ruleset > /etc/nftables.conf
/etc/nftables.conf是常见的规则文件路径。
自动加载规则:
- Systemd 服务:大多数 Linux 发行版会提供
nftables.service。1
2sudo systemctl enable nftables.service # 启用服务,使其在开机时启动
sudo systemctl start nftables.service # 立即启动服务加载规则nftables.service通常会执行nft -f /etc/nftables.conf来加载规则。
- Systemd 服务:大多数 Linux 发行版会提供
五、nftables 的优势
- 统一的语法和工具:
nft命令统一管理 IPv4、IPv6、桥接等所有协议的规则,消除了iptables系列工具的碎片化。 - 原子性更新:可以一次性加载整个规则集,保证规则集的原子性更新,避免了瞬时中断或不一致状态。
- 高性能:基于内核的字节码解释器,可以更高效地处理数据包和规则匹配。引入了更高效的数据结构(如集合、映射)。
- 灵活的规则定义:用户可以任意定义表和链,更灵活地组织规则。
inet地址族允许 IPv4 和 IPv6 规则的合并。 - 增强的匹配能力:支持更复杂的匹配表达式,例如基于各种网络协议头部字段匹配,以及强大的集合 (Set) 和映射 (Map) 功能。
- 简化 NAT:NAT 配置更加直观,例如
dnat to <ip>:<port>。 - 连接跟踪改进:结合了 Netfilter 的连接跟踪器,可以更精细地控制连接状态。
六、总结
nftables 是 Linux 防火墙技术的一次重大飞跃,它在设计理念、性能和易用性方面都超越了传统的 iptables。通过统一的管理工具、灵活的规则结构、原子性更新和高效的内部处理机制,nftables 为 Linux 系统网络数据包过滤和管理提供了一个更强大、更现代的解决方案。虽然其语法与 iptables 截然不同,需要一定的学习成本,但随着主流发行版(如 Debian、Ubuntu、Fedora、RHEL)逐渐将其作为默认防火墙后端,掌握 nftables 将成为 Linux 系统管理员和网络工程师必备的技能。
