引言: 为什么需要nftables?
Linux防火墙技术经历了从ipchains到iptables,再到nftables的演进过程。如果说iptables是“瑞士军刀”,那么nftables就是“现代化多功能工具箱”。2014年,Netfilter核心团队决定重新设计防火墙子系统,旨在解决iptables在可扩展性、一致性和性能方面的固有限制。
一、nftables 架构总览
1.1 三层架构模型

1.2 与iptables的对比
| 特性维度 |
iptables |
nftables |
| 架构设计 |
每协议独立子系统 |
统一的核心引擎 |
| 规则语法 |
线性的命令序列 |
声明式规则集 |
| 匹配机制 |
扩展匹配模块 |
表达式组合 |
| 性能特点 |
线性规则遍历 |
可能的规则合并优化 |
| 可扩展性 |
有限, 需内核模块 |
高, 支持动态表达式 |
| 配置管理 |
脚本式命令 |
可持久化规则集 |
二、核心概念深度解析
2.1 规则集 (Ruleset) - 顶层容器
规则集是nftables配置的根对象,包含所有表、链、规则、集合和流表。你可以把它想象成一本完整的防火墙策略手册。
// 内核数据结构: nftables规则集
struct nftables {
struct list_head tables; // 所有表的链表
struct list_head modules; // 加载的模块
uint32_t flags;
};
2.2 表 (Table) - 命名空间隔离
表是规则的命名空间容器,对应于特定的地址族(Address Family):

表的生命周期管理:
# 创建表
nft add table inet my_firewall
# 列出所有表
nft list tables
# 删除表(级联删除所有内容)
nft delete table inet my_firewall
2.3 链 (Chain) - 执行上下文
链是规则的执行容器,定义在特定钩子点(hook point)上触发:
// 内核中的链定义
struct nft_chain {
struct list_head list; // 链表节点
struct rhlist_head rhlhead; // 哈希链表头
struct nft_table *table; // 所属表
struct nft_chain_ops *ops; // 链操作函数
u64 handle; // 唯一标识
char name[NFT_CHAIN_MAXNAMELEN];
u8 flags; // 链标志
u8 use; // 引用计数
};
钩子点系统 - 数据包的生命周期检查站:

链的类型对比表:
| 链类型 |
描述 |
典型用途 |
示例 |
| 常规链 |
用户定义的规则容器 |
自定义处理逻辑 |
chain my_chain { ... } |
| 基链 |
绑定到Netfilter钩子点 |
入口点过滤 |
type filter hook input priority 0 |
| 跳转目标 |
规则的目标 |
规则执行跳转 |
jump my_chain |
2.4 规则 (Rule) - 最小执行单元
规则由选择器(表达式)和动作(裁决)组成:
# 规则的完整语法结构
nft add rule <表> <链> <表达式> <裁决>
# 示例:
nft add rule inet my_firewall input ip saddr 192.168.1.0/24 accept
内核中的规则表示:
struct nft_rule {
struct list_head list; // 在链中的位置
struct rcu_head rcu_head;
u64 handle:42, // 规则句柄
genmask:2, // 生成掩码
dlen:12, // 数据长度
udata:1; // 用户数据标志
unsigned char data[] // 表达式数据
__attribute__((aligned(__alignof__(struct nft_expr))));
};
2.5 表达式 (Expression) - 规则的构建块
表达式是nftables真正的“超级武器”,每个表达式实现特定的数据包处理功能:

表达式的工作原理:
// 表达式操作结构
struct nft_expr_ops {
// 表达式类型信息
const struct nft_expr_type *type;
// 核心函数指针
void (*eval)(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt);
// 其他管理函数
int (*init)(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[]);
void (*destroy)(const struct nft_ctx *ctx,
const struct nft_expr *expr);
// ...
};
// 表达式实例
struct nft_expr {
const struct nft_expr_ops *ops; // 操作函数
unsigned char data[] // 表达式私有数据
__attribute__((aligned(__alignof__(u64))));
};
常见表达式类型对比表:
| 表达式类别 |
主要表达式 |
功能描述 |
示例 |
| 协议匹配 |
ip, ip6, tcp, udp, icmp |
协议头字段匹配 |
ip saddr 192.168.1.1 |
| 元数据 |
meta, ct |
数据包/连接元数据 |
meta iifname "eth0" |
| 地址转换 |
nat, masquerade, redirect |
地址/端口转换 |
masquerade |
| 流量控制 |
limit, quota |
限速和配额 |
limit rate 10/second |
| 高级操作 |
log, counter, set |
日志、计数、集合操作 |
counter packets 0 bytes 0 |
2.6 集合与映射 (Set & Map) - 高效数据管理
集合和映射是nftables的性能关键特性,允许高效地管理大量元素:

集合的内核实现:
// 集合定义
struct nft_set {
struct list_head list; // 链表节点
struct rhlist_head rhlhead; // 哈希链表
struct nft_table *table; // 所属表
// 集合属性
char name[NFT_SET_MAXNAMELEN];
u64 handle;
u32 ktype; // 键类型
u32 dtype; // 数据类型
u32 objtype; // 对象类型
u32 size; // 元素数量
u8 field_len[NFT_REG32_COUNT]; // 字段长度
u8 field_count; // 字段计数
// 操作函数
const struct nft_set_ops *ops; // 集合操作
u16 flags; // 标志位
u8 klen; // 键长度
u8 dlen; // 数据长度
u8 num_fields; // 字段数
struct rcu_head rcu_head;
};
集合使用示例:
# 创建IP地址集合
nft add set inet my_firewall blacklist {
type ipv4_addr
flags interval # 支持CIDR范围
elements = { 10.0.0.0/8, 192.168.0.0/16 }
}
# 在规则中使用集合
nft add rule inet my_firewall input ip saddr @blacklist drop
# 动态更新集合
nft add element inet my_firewall blacklist { 172.16.0.0/12 }
三、nftables 内核实现机制
3.1 数据包处理流程

3.2 表达式求值引擎
nftables使用基于寄存器的虚拟机来执行表达式:
// 寄存器状态 - 规则执行的上下文
struct nft_regs {
union {
u32 data[20]; // 通用数据寄存器
struct {
u32 verdict; // 裁决寄存器
u32 chain; // 链寄存器
};
};
};
// 数据包信息
struct nft_pktinfo {
struct sk_buff *skb; // socket缓冲区
const struct nf_hook_state *state; // 钩子状态
u8 protocol; // 协议
u8 tprot; // 传输层协议
// ...
};
表达式执行过程:
// 规则执行核心函数
unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv)
{
const struct nft_chain *chain = priv;
const struct nft_rule *rule;
struct nft_regs regs = {};
unsigned int stackptr = 0;
const struct nft_rule *rules[NF_MAX_JUMPCOUNT];
// 初始化寄存器
nft_netdev_set_pktinfo_ipv4(®s, pkt);
// 遍历链中的规则
list_for_each_entry_rcu(rule, &chain->rules, list) {
// 执行规则中的所有表达式
nft_rule_expr_eval(rule, ®s, pkt);
// 检查裁决结果
switch (regs.verdict) {
case NFT_BREAK:
return NF_ACCEPT;
case NFT_JUMP:
case NFT_GOTO:
// 处理跳转
break;
case NFT_CONTINUE:
continue;
default:
return regs.verdict;
}
}
return chain->policy;
}
3.3 状态跟踪 (Connection Tracking)
连接跟踪是状态防火墙的核心机制,它维护网络连接的状态信息,使防火墙能够智能处理数据包:

四、实战示例: 构建企业级防火墙
4.1 完整配置文件示例
以下是一个企业级防火墙配置示例,涵盖了常见的安全策略和优化技巧:
#!/usr/sbin/nft -f
# 清空现有规则
flush ruleset
# 定义企业防火墙表
table inet enterprise_fw {
# 定义集合
set admin_ips {
type ipv4_addr
flags interval
elements = {
10.0.1.0/24, # 管理网段
192.168.100.0/28 # 管理服务器
}
}
set blacklist {
type ipv4_addr
elements = {
203.0.113.0/24, # 已知恶意IP段
198.51.100.5 # 特定攻击IP
}
}
set ssh_bruteforce {
type ipv4_addr
size 65535
flags dynamic,timeout # 动态集合, 带超时
timeout 1h
}
# 定义流表跟踪SSH连接
ct timeout ssh_rate {
protocol tcp
l3proto ip
dst-port ssh
policy = {
new: 1m, # 新建连接跟踪1分钟
established: 12h, # 已建立连接12小时
}
}
# 输入链
chain input {
type filter hook input priority 0; policy drop;
# 基础检查
ct state invalid drop
ct state established,related accept
# 本地回环
iifname "lo" accept
# ICMP协议(有限类型)
ip protocol icmp icmp type {
echo-request,
echo-reply,
destination-unreachable,
time-exceeded
} accept
# 管理访问
ip saddr @admin_ips tcp dport {ssh, https} accept
# Web服务器
tcp dport {http, https} accept
# SSH防护: 限速和动态黑名单
tcp dport ssh {
# 限制每秒3个新连接
limit rate 3/second burst 5 packets accept
# 超过限制的加入黑名单
add @ssh_bruteforce { ip saddr } drop
}
# 拒绝并记录黑名单尝试
ip saddr @blacklist log prefix "Blacklisted: " drop
# 默认拒绝并记录
log prefix "Denied input: " drop
}
# 转发链
chain forward {
type filter hook forward priority 0; policy drop;
ct state established,related accept
# DMZ区域转发规则
iifname "eth1" oifname "eth0" ip daddr 10.0.2.0/24 accept
log prefix "Denied forward: " drop
}
# 输出链
chain output {
type filter hook output priority 0; policy accept;
# 限制特定出站连接
tcp dport {25, 587} accept # SMTP
udp dport {53, 123} accept # DNS和NTP
}
# NAT链
chain postrouting {
type nat hook postrouting priority 100; policy accept;
# 出站伪装
oifname "eth0" masquerade
}
}
4.2 动态规则管理
# 实时监控工具
# 1. 实时规则统计
nft list ruleset -a # 显示所有句柄和计数器
# 2. 监控动态集合
watch -n 1 'nft list set inet enterprise_fw ssh_bruteforce'
# 3. 动态添加规则
nft insert rule inet enterprise_fw input position 5 \
ip saddr 192.168.200.5 accept
# 4. 紧急封锁IP
nft add element inet enterprise_fw blacklist { 10.1.1.1 }
# 5. 规则替换
nft replace rule inet enterprise_fw input handle 15 \
tcp dport 8080 accept
五、高级特性与性能优化
5.1 规则优化机制

性能优化技巧表:
| 优化方法 |
实现方式 |
性能提升 |
适用场景 |
| 集合使用 |
用集合代替多个OR规则 |
极高 |
大量离散值匹配 |
| 早期拒绝 |
黑名单规则放前面 |
高 |
攻击流量过滤 |
| 协议排序 |
按流量比例排序规则 |
中等 |
混合协议环境 |
| 连接跟踪 |
利用ct状态早期接受 |
极高 |
已建立连接 |
| 规则批处理 |
一次性提交多条规则 |
高 |
规则初始化 |
5.2 内核模块扩展
nftables支持动态加载表达式模块,允许开发者自定义功能:
// 自定义表达式示例
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <net/netfilter/nf_tables.h>
struct my_expr_priv {
u32 my_data;
};
static void my_expr_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
const struct my_expr_priv *priv = nft_expr_priv(expr);
// 自定义匹配逻辑
if (priv->my_data == pkt->skb->len) {
regs->verdict = NFT_BREAK;
}
}
static struct nft_expr_type my_expr_type __read_mostly = {
.name = "my_expr",
.ops = &my_expr_ops,
.policy = nft_my_expr_policy,
.maxattr = NFTA_MY_EXPR_MAX,
.owner = THIS_MODULE,
};
static int __init my_expr_init(void)
{
return nft_register_expr(&my_expr_type);
}
module_init(my_expr_init);
六、诊断与调试
6.1 调试工具集
# 1. 基础诊断
nft --version
nft list ruleset # 完整规则集
nft list tables # 所有表
nft list chains # 所有链
# 2. 规则跟踪(内核5.3+)
nft add rule inet enterprise_fw input meta nftrace set 1
nft monitor trace # 实时跟踪
# 3. 性能分析
nft list ruleset -n -a # 数字格式, 显示句柄
nft list ruleset -s # 统计信息
nft list ruleset -nn # 数字端口显示
# 4. Netlink监控
nft monitor # 实时规则变更
nft monitor events # 事件监控
6.2 常见问题排查表
| 问题现象 |
可能原因 |
排查命令 |
解决方案 |
| 规则不生效 |
链类型/优先级错误 |
nft list chain <表> <链> |
检查链类型和钩子点 |
| 性能低下 |
规则顺序不合理 |
nft list ruleset -s |
重排序规则, 常用放前 |
| 内存泄漏 |
动态集合无超时 |
nft list sets -n |
为动态集合添加timeout |
| 连接跟踪失败 |
超时设置过短 |
cat /proc/net/nf_conntrack |
调整ct timeout |
| 规则丢失 |
缺少持久化 |
nft list ruleset > /etc/nftables.conf |
配置持久化存储 |
七、从iptables迁移到nftables
7.1 迁移工具使用
# 1. 使用iptables-translate工具
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
# 输出: nft add rule ip filter INPUT tcp dport 22 counter accept
# 2. 批量转换
iptables-save > iptables.rules
iptables-restore-translate -f iptables.rules > nftables.conf
# 3. 混合运行模式(过渡期)
modprobe nf_tables
iptables-nft -A INPUT -p tcp --dport 80 -j ACCEPT
nft list ruleset # 查看转换后的规则
7.2 迁移对比表
| iptables概念 |
nftables对应 |
迁移注意事项 |
iptables命令 |
nft命令 |
语法完全不同 |
-A INPUT |
add rule ip filter input |
链指定方式不同 |
-p tcp --dport |
tcp dport |
协议匹配简化 |
-m state |
ct state |
连接跟踪方式变化 |
-j LOG |
log |
日志集成到规则 |
| 自定义链 |
同名链概念 |
语法类似但更灵活 |
八、总结与展望
8.1 nftables核心优势总结
经过深入分析,nftables的几大核心优势包括:
- 统一的架构设计:告别了iptables中各个协议独立的后端,实现了真正的统一管理。
- 强大的表达式系统:模块化设计使得功能扩展更加容易和安全。
- 出色的性能特性:集合、映射和规则优化机制大幅提升匹配效率。
- 灵活的策略管理:声明式语法和丰富的命令操作简化了复杂策略管理。
- 良好的向后兼容:通过兼容层支持iptables规则迁移。
8.2 架构演进对比图

8.3 未来发展方向
根据Netfilter项目的路线图,nftables的未来发展重点包括:
- 更智能的规则优化:基于机器学习的规则自动优化。
- 增强的安全特性:与内核安全模块深度集成。
- 云原生支持:更好的容器和Kubernetes集成。
- 硬件卸载:支持特定网卡硬件的规则卸载。
- 策略即代码:与配置管理工具深度集成。
8.4 生产环境建议
对于不同规模的环境,配置建议如下:
| 环境规模 |
nftables配置建议 |
关键特性利用 |
| 个人/开发 |
基础规则集 |
快速配置, 基础安全 |
| 中小企业 |
分层策略结构 |
集合、动态黑名单、性能优化 |
| 大型企业 |
模块化规则集 |
规则分片、性能监控、自动化管理 |
| 云服务商 |
动态策略引擎 |
API集成、租户隔离、硬件卸载 |
结语
nftables代表了Linux防火墙技术的现代化方向,它不仅解决了iptables长期存在的架构问题,还引入了许多创新特性。虽然学习曲线相对陡峭,但其强大的功能和优秀的性能使其成为现代Linux系统防火墙的不二选择。
正如Netfilter核心开发者Pablo Neira Ayuso所说:“nftables是我们在防火墙领域15年经验的结晶,它不仅仅是iptables的替代品,更是对Linux网络过滤的一次重新思考。”
掌握nftables需要理解其背后的设计哲学和实现机制,但一旦掌握,你将拥有一个强大、灵活且高效的防火墙工具,能够应对从家庭网络到数据中心的各种场景需求。
参考资源:
- Netfilter官方文档: https://wiki.nftables.org
- nftables内核源码: net/netfilter/nf_tables*.c
- 《The nftables Journey》Pablo Neira Ayuso
- Linux内核文档: Documentation/networking/nf_tables.txt
工具链:
- nft命令: 主要配置工具
- conntrack-tools: 连接跟踪管理
- wireshark: 配合nftrace进行深度分析
- systemtap/ebpf: 内核级性能分析