Skip to content

Commit 849b0e4

Browse files
authored
Document nftables architecture and components
Add comprehensive documentation on nftables, its architecture, core components, and user-space libraries.
1 parent a7ab029 commit 849b0e4

File tree

1 file changed

+317
-0
lines changed

1 file changed

+317
-0
lines changed
Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
# nftables
2+
3+
nftables 是 Linux 上新一代的包过滤框架,它虽然是 Netfilter 的“继任者”,但并不是完全独立的系统——它是基于 Netfilter 核心架构之上重新设计的规则引擎与用户空间接口。
4+
5+
## 整体架构概览
6+
nftables 底层依然依附于 Netfilter 内核框架,但重构了规则存储和执行逻辑
7+
```
8+
┌───────────────────────────────┐
9+
│ 用户空间 (user space) │
10+
│ nft 命令行工具 / libnftables │
11+
└──────────────┬────────────────┘
12+
│ Netlink (NFNETLINK)
13+
┌──────────────┴────────────────┐
14+
│ 内核空间 (kernel) │
15+
│ ┌───────────────────────────┐ │
16+
│ │ nftables 内核子系统 │ │
17+
│ │ ├─ nft_core │ │
18+
│ │ ├─ nft_rule_set (规则树)│ │
19+
│ │ ├─ nft_expr (表达式集) │ │
20+
│ │ ├─ nft_chain (链) │ │
21+
│ │ ├─ nft_table (表) │ │
22+
│ │ └─ nft_hooks (Netfilter)│ │
23+
│ └───────────────────────────┘ │
24+
│ ↑ ↑ │
25+
│ Netfilter 框架钩子 conntrack│
26+
└────────────────────────────────┘
27+
```
28+
关键区别于旧版 iptables:
29+
30+
| 特性 | iptables | nftables |
31+
| ---- | ------------------ | ------------------------ |
32+
| 数据结构 | 每条规则独立链表 | 规则集编译成表达式树 |
33+
| 执行方式 | 线性匹配遍历 | 字节码解释执行(VM) |
34+
| 用户接口 | 专用命令+内核接口 | 通用 Netlink + libnftables |
35+
| 扩展方式 | 内核模块(match/target) | 表达式(expr)和链式扩展 |
36+
| 性能 | 多规则时线性变慢 | 优化结构,可编译字节码 |
37+
38+
39+
## 核心底层技术组件
40+
41+
### Netlink 通信 (nfnetlink)
42+
43+
用户空间的命令 (nft) 与内核空间通信依赖 Netlink 协议族:
44+
- 专用子协议:NFNETLINK_SUBSYS_NFTABLES
45+
- 用户空间通过 libnftables 或 libmnl 构建 netlink 消息;
46+
- 内核模块 nf_tables.ko 解析消息并更新规则集。
47+
48+
这使得:
49+
- 规则更易批量原子更新(transaction-based)
50+
- 用户态与内核态解耦,不需为每种 match/target 写 ioctl。
51+
52+
👉 内核接口:nf_tables_netlink.c
53+
54+
### nftables 虚拟机(nft_expr bytecode engine)
55+
nftables 内核通过一个轻量虚拟机执行规则表达式。
56+
- 每条规则在加载时被“编译”为一组 nft_expr 字节码(表达式链);
57+
- 每个表达式是一个结构体:
58+
59+
```c
60+
struct nft_expr {
61+
const struct nft_expr_ops *ops;
62+
unsigned char data[];
63+
};
64+
```
65+
ops 定义了执行逻辑,如 compare、counter、meta、payload、bitwise 等。
66+
67+
- 运行时遍历这些表达式执行逻辑判断;
68+
- 当匹配成功可调用动作表达式(如 verdict、counter、log、nat 等)。
69+
70+
### Netfilter Hook 集成
71+
72+
底层仍依赖 Netfilter 钩子:
73+
74+
- 对 IPv4/IPv6/ARP/Bridge/Inet 协议族注册:
75+
- NF_INET_PRE_ROUTING
76+
- NF_INET_LOCAL_IN
77+
- NF_INET_FORWARD
78+
- NF_INET_LOCAL_OUT
79+
- NF_INET_POST_ROUTING
80+
- 每当包经过这些点,nftables 会调用相应链表的规则集(chain)。
81+
82+
代码位置:net/netfilter/nf_tables_api.c, nf_tables_core.c。
83+
84+
### nft_set 与查找加速机制
85+
nftables 支持高效的集合匹配(set / map):
86+
- 内核中通过 rhashtable / rbtree / hash 实现。
87+
- 提供高效匹配和关联映射(如 IP → 动作)。
88+
89+
这比 iptables 的线性规则匹配快得多,尤其在大规则集(成千上万条 IP)场景。
90+
91+
### conntrack(连接跟踪)集成
92+
93+
nftables 内部复用 Netfilter conntrack 框架:
94+
95+
提供连接状态(NEW, ESTABLISHED, RELATED...)
96+
97+
用于状态匹配、NAT、反欺骗等。
98+
99+
内核模块:nf_conntrack.ko、nf_nat.ko
100+
对应 nftables 表达式:ct state, ct mark, ct zone。
101+
102+
### 事务(Atomic Transactions)
103+
nftables 通过 事务模型(transaction model)支持原子更新规则集:
104+
- 所有规则修改(add/delete/replace)被放入事务;
105+
- 一次性提交,内核切换新规则集;
106+
- 避免中间状态造成安全空窗。
107+
108+
### 多协议支持(families)
109+
nftables 支持多协议族:
110+
- inet:IPv4 + IPv6 混合
111+
- ip:仅 IPv4
112+
- ip6:仅 IPv6
113+
- arp:ARP 层
114+
- bridge:二层桥接
115+
- netdev:直接挂在网络设备层
116+
117+
## nftables 内核模块结构(源码层)
118+
源码路径:
119+
```
120+
net/netfilter/
121+
├─ nf_tables_api.c → Netlink 接口 & 表/链/规则管理
122+
├─ nf_tables_core.c → 表达式执行引擎(nft_vm)
123+
├─ nf_tables_expr.c → 各种表达式实现(payload, cmp, log, verdict 等)
124+
├─ nf_tables_set.c → set/map 实现(hash, rbtree 等)
125+
├─ nf_tables_trace.c → 调试与 trace 框架
126+
└─ nf_tables_inet.c → inet family 集成
127+
```
128+
129+
## 执行流程简化
130+
以一个 IPv4 包为例:
131+
1️⃣ 内核在 NF_INET_LOCAL_IN 调用 nftables hook
132+
2️⃣ 查找对应 table & chain
133+
3️⃣ 执行 chain 中的表达式序列(nft_expr 数组)
134+
4️⃣ 每个 expr 读取 packet 元数据(IP, TCP, mark...)→ 计算判断
135+
5️⃣ 若匹配成功 → 执行动作表达式(例如 verdict = DROP / ACCEPT / JUMP / COUNTER)
136+
6️⃣ 执行完毕 → 返回 verdict 给 Netfilter 框架
137+
138+
## 技术优势与设计理念
139+
140+
| 目标 | 技术实现 |
141+
| ---- | ---------------------------- |
142+
| 性能 | 字节码解释器 + 高效集合查找 (rhashtable) |
143+
| 可扩展性 | 动态表达式插件机制 (nft_expr_ops) |
144+
| 一致性 | 单一 Netlink 接口统一多协议 |
145+
| 原子性 | 事务模型 |
146+
| 易维护 | 用户空间 libnftables 封装 |
147+
| 安全性 | 无需多模块编译、减少用户态与内核态耦合 |
148+
149+
150+
## 用户态开发
151+
| 层次 | 主要库 | 作用 / 场景 |
152+
| --------------------- | ---------------------------------------------------------------------------- | -------------------------------- |
153+
| 🔹 **通用 Netlink 通信层** | **libmnl** | 与内核的 Netlink 通信(底层基础库) |
154+
| 🔹 **nftables 配置接口层** | **libnftnl**, **libnftables** | 构建、解析、序列化 nftables 规则、表、链 |
155+
| 🔹 **数据包捕获 / 队列层** | **libnetfilter_queue** | 用户空间接收 NFQUEUE 包,执行自定义处理后再决定是否放行 |
156+
| 🔹 **连接跟踪层** | **libnetfilter_conntrack** | 获取、监控、修改 conntrack 状态表 |
157+
| 🔹 **日志接口层** | **libnetfilter_log** | 从内核接收 NFLOG 输出的数据包日志 |
158+
| 🔹 **状态同步层** | **libnetfilter_cttimeout**, **libnetfilter_cthelper**, **libnetfilter_acct** | 管理连接跟踪的超时、helper、计数等高级功能 |
159+
160+
161+
### 库的功能详解
162+
1️⃣ libmnl(Minimal Netlink Library)
163+
164+
📍 作用:
165+
这是所有 Netfilter 用户态库的通信基础。
166+
- 提供简洁的 API 封装 Linux Netlink 套接字;
167+
- 用于构造、发送、解析 Netlink 消息;
168+
- 比传统 libnl 更轻量、无依赖。
169+
170+
📦 用途:
171+
- 开发自定义 Netlink 客户端;
172+
- 自己实现 nftables、conntrack、queue 的高性能控制接口;
173+
- 嵌入式 / 安全代理中常用。
174+
175+
💡 例子:
176+
```
177+
struct mnl_socket *nl = mnl_socket_open(NETLINK_NETFILTER);
178+
mnl_socket_sendto(nl, msg, len);
179+
mnl_socket_recvfrom(nl, buf, sizeof(buf));
180+
```
181+
182+
2️⃣ libnftnl(nftables Netlink API 库)
183+
184+
📍 作用:
185+
- 提供创建、解析、序列化 nftables 对象(table、chain、rule、set、expr 等) 的接口;
186+
- 基于 Netlink 消息构建完整对象描述;
187+
- 是 nft 命令行工具的底层实现依赖。
188+
189+
📦 用途:
190+
- 自己编写程序动态生成 nftables 规则;
191+
- 在控制平面中实现动态防火墙或安全策略下发;
192+
- 替代手工调用 system("nft add rule ...")。
193+
194+
📘 API 示例:
195+
```
196+
struct nftnl_rule *r = nftnl_rule_alloc();
197+
nftnl_rule_set_str(r, NFTNL_RULE_TABLE, "filter");
198+
nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, "input");
199+
nftnl_rule_add_expr(r, expr_payload);
200+
nftnl_rule_add_expr(r, expr_cmp);
201+
nftnl_rule_add_expr(r, expr_verdict);
202+
```
203+
204+
📚 依赖: libmnl
205+
206+
3️⃣ libnftables(高层封装)
207+
208+
📍 作用:
209+
- 比 libnftnl 更高一层;
210+
- 内置一个 nftables 解释器,能解析文本规则语法;
211+
- 可以直接加载 .nft 规则文件、脚本;
212+
- 自动管理事务、错误报告。
213+
214+
📦 用途:
215+
- 若你不想直接构造 Netlink 消息,可用这个库;
216+
- 可直接集成 “nftables CLI 语法”;
217+
- 适合防火墙管理工具、配置守护进程(如 firewalld)。
218+
219+
💡 示例:
220+
```
221+
#include <libnftables.h>
222+
223+
struct nft_ctx *ctx = nft_ctx_new(NFT_CTX_DEFAULT);
224+
nft_ctx_buffer_output(ctx);
225+
nft_run_cmd_from_buffer(ctx, "add table inet myfilter");
226+
printf("%s\n", nft_ctx_get_output(ctx));
227+
nft_ctx_free(ctx);
228+
```
229+
4️⃣ libnetfilter_queue(NFQUEUE 队列接口)
230+
231+
📍 作用:
232+
- 接收从内核通过 NFQUEUE 发送上来的数据包;
233+
- 允许用户空间程序分析、修改、放行或丢弃;
234+
- 常用于 入侵检测/防御系统 (IDS/IPS)、DPI(深度包检测)、流量审计。
235+
236+
📦 用途:
237+
- 防火墙扩展:编写用户空间逻辑(如基于AI或规则的判断);
238+
- 实现流量镜像、过滤、负载均衡等;
239+
- 与 Python 绑定(nfqueue-bindings)配合使用。
240+
241+
💡 例子:
242+
```
243+
#include <libnetfilter_queue/libnetfilter_queue.h>
244+
245+
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
246+
struct nfq_data *nfa, void *data) {
247+
struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa);
248+
printf("Packet id=%u\n", ntohl(ph->packet_id));
249+
return nfq_set_verdict(qh, ntohl(ph->packet_id), NF_ACCEPT, 0, NULL);
250+
}
251+
252+
int main() {
253+
struct nfq_handle *h = nfq_open();
254+
struct nfq_q_handle *qh = nfq_create_queue(h, 0, &cb, NULL);
255+
nfq_handle_packet(h, buf, len);
256+
}
257+
```
258+
5️⃣ libnetfilter_conntrack
259+
260+
📍 作用:
261+
- 提供对连接跟踪表(conntrack table)的管理;
262+
- 可枚举、添加、删除、修改、过滤连接;
263+
- 还可注册事件监听(新建/销毁连接)。
264+
265+
📦 用途:
266+
- 网络状态监控;
267+
- 实现会话级流量控制;
268+
- 防火墙状态同步。
269+
270+
💡 示例:
271+
```
272+
struct nfct_handle *h = nfct_open(CONNTRACK, 0);
273+
nfct_query(h, NFCT_Q_GET, &ct);
274+
nfct_callback_register(h, NFCT_T_ALL, cb, NULL);
275+
```
276+
277+
6️⃣ libnetfilter_log
278+
279+
📍 作用:
280+
- 用于从内核 NFLOG 接口接收日志包;
281+
- 比内核 printk 或 syslog 更高效;
282+
- 可实现自定义日志分析系统。
283+
284+
📦 用途:
285+
- 安全审计;
286+
- 包级别日志系统;
287+
- 与 ELK / SIEM 集成。
288+
289+
7️⃣ 其他辅助库
290+
| 库名 | 作用 |
291+
| -------------------------- | ------------------------------------ |
292+
| **libnetfilter_cthelper** | 管理 conntrack helper(例如 FTP、SIP 协议辅助) |
293+
| **libnetfilter_cttimeout** | 管理 conntrack 超时策略 |
294+
| **libnetfilter_acct** | 连接跟踪的流量计数管理 |
295+
296+
### 常见组合方案(应用场景)
297+
| 场景 | 推荐库组合 |
298+
| -------------------------- | ---------------------------------------------- |
299+
| 🔥 动态防火墙控制面 | libnftables + libmnl |
300+
| 📡 用户态包处理(DPI / IDS / IPS) | libnetfilter_queue + libmnl |
301+
| 📈 流量监控 / 可视化 | libnetfilter_conntrack + libnetfilter_log |
302+
| 🧰 自定义安全策略引擎 | libnftnl + libnftables |
303+
| 🕹️ NFLOG 收集系统 | libnetfilter_log + libmnl |
304+
| 🧩 协议辅助开发 | libnetfilter_cthelper + libnetfilter_cttimeout |
305+
306+
307+
## Refs
308+
309+
🔗 Netfilter 官方项目页 https://www.netfilter.org/projects/
310+
311+
🔗 libnftables API 文档 https://netfilter.org/projects/libnftables/
312+
313+
🔗 libnetfilter_queue examples https://netfilter.org/projects/libnetfilter_queue/
314+
315+
🔗 libnetfilter_conntrack examples https://netfilter.org/projects/libnetfilter_conntrack/
316+
317+
📘 Linux 内核源码:net/netfilter/ 与 include/uapi/linux/netfilter/

0 commit comments

Comments
 (0)