|
| 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