04 netfilter 与包过滤机制与实现详解
1. 概述
net/netfilter/(~253 文件)是 Linux 包过滤、连接跟踪、NAT、负载均衡 的核心实现。它在协议栈 固定 hook 点 介入 sk_buff 路径,不改变网卡驱动;与 NAPI/收包 正交,作用于 L3 已解析之后 的转发/本地交付决策。
| 项目 | 说明 |
|---|---|
| 源码路径 | rk3588/kernel-6.1/net/netfilter/ |
| 配置 | CONFIG_NETFILTER 及子项(见 Kconfig) |
| 用户态 | nft(nftables)、iptables(legacy)、conntrack |
| 控制通道 | NETLINK_NETFILTER(nfnetlink.c) |
| RK3588 | 无 Rockchip 专属补丁;行为与上游 6.1 一致 |
1.1 目录结构(按功能)
1 | net/netfilter/ |
注意:IPv4/IPv6 的 iptables 表驱动 在 net/ipv4/netfilter/、net/ipv6/netfilter/(如 ip_tables.c、ip6_tables.c),但 hook 框架与 nftables 主体在 net/netfilter/。
2. Hook 框架(core.c)
2.1 Hook 点(IPv4/IPv6 _inet)
定义于 include/uapi/linux/netfilter.h:
| Hook | 典型位置 |
|---|---|
NF_INET_PRE_ROUTING |
路由决策前(入站) |
NF_INET_LOCAL_IN |
本机接收 |
NF_INET_FORWARD |
转发 |
NF_INET_LOCAL_OUT |
本机发出 |
NF_INET_POST_ROUTING |
路由后、出接口前 |
NF_INET_INGRESS |
入口(netdev 早期) |
协议栈调用示例(net/ipv4/ip_forward.c):
1 | return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, net, NULL, skb, |
2.2 注册与存储
nf_register_net_hook()/nf_register_net_hooks():按priority插入 hook 数组- 每
(netns, pf, hooknum)维护nf_hook_entries(RCU 只读遍历) CONFIG_JUMP_LABEL:nf_hooks_needed[pf][hook]无 hook 时跳过nf_hook_slow快速路径
nf_hook_ops 关键字段:
1 | struct nf_hook_ops { |
2.3 nf_hook_slow() — 核心裁决
1 | int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state, |
| Verdict | 含义 |
|---|---|
NF_ACCEPT |
继续下一个 hook 或 okfn |
NF_DROP |
丢弃 skb |
NF_STOLEN |
hook 接管 skb,协议栈不再处理 |
NF_QUEUE |
交用户态队列裁决(nf_queue.c) |
NF_REPEAT |
重新从当前 hook 执行 |
内联入口 nf_hook()(include/linux/netfilter.h)在 static_key 显示无 hook 时直接 okfn(skb)。
3. 连接跟踪(nf_conntrack)
3.1 核心文件
| 文件 | 作用 |
|---|---|
nf_conntrack_core.c |
表项创建/查找/GC、nf_conntrack_in |
nf_conntrack_proto_*.c |
TCP/UDP/ICMP 等 L4 状态机 |
nf_conntrack_expect.c |
期望连接(FTP/SIP 等多通道) |
nf_conntrack_helper.c + nf_conntrack_ftp.c 等 |
ALG 辅助 |
nf_conntrack_netlink.c |
用户态查询/事件 |
3.2 nf_conntrack_in() 流程
挂于 PREROUTING、LOCAL_OUT 等(由 nf_conntrack_l3proto 注册):
1 | nf_conntrack_in(skb) |
连接以 五元组 tuple(可加 zone)哈希入 nf_conntrack_hash;状态如 NEW / ESTABLISHED / RELATED。
3.3 与 NAT 关系
- conntrack 独立于 NAT,但 NAT 修改 tuple 必须同步 conntrack(
nf_nat_core.c) nf_nat_hook通过 RCU 指针在core.c中挂接,避免模块循环依赖
4. NAT(nf_nat)
| 文件 | 作用 |
|---|---|
nf_nat_core.c |
SNAT/DNAT 查找、tuple 改写 |
nf_nat_proto.c |
协议相关校验和/端口映射 |
nf_nat_masquerade.c |
MASQUERADE(出接口地址) |
nf_nat_redirect.c |
REDIRECT(本机端口) |
nf_nat_ftp.c 等 |
NAT helper |
NAT 在 POSTROUTING(SNAT)/ PREROUTING(DNAT)hook 修改 skb 地址端口,并 nf_conntrack_alter_reply() 维护反向 tuple。
5. nftables(现代推荐)
5.1 组成
Makefile 中 nf_tables-objs:
nf_tables_core.c— 规则求值nft_do_chain()nf_tables_api.c— 表/链/规则/集合的 netlink 配置 APInft_chain_filter.c/nft_chain_route.c/nft_chain_nat.c— 链类型与 hook 绑定nft_*.c— 表达式:payload、cmp、lookup、ct、nat、limit、queue…nft_set_*.c— 集合后端:hash、bitmap、rbtree、pipapo(x86 可有 AVX2)
5.2 规则求值:nft_do_chain()
1 | unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv) |
- 规则编译为 字节码 blob(表达式序列),求值用
nft_regs寄存器 - jump stack 支持
jump/goto子链 - gencursor 双缓冲:用户态更新规则时 RCU 切换,数据面无锁读
5.3 Hook 注册
nft_chain_filter.c 将 nft_do_chain_ipv4 注册到各 NF_INET_* hook:
1 | [NF_INET_FORWARD] = nft_do_chain_ipv4, |
nf_tables_api.c 中 nft_chain_hook 管理 base chain 与 nf_register_net_hook 的绑定。
5.4 用户态配置
1 | nft add table ip filter |
内核路径:nft → NFNL_SUBSYS_NFTABLES(nfnetlink)→ nf_tables_api.c。
6. iptables / x_tables(legacy)
| 组件 | 路径 | 说明 |
|---|---|---|
| x_tables | x_tables.c |
match/target 注册框架 |
| xt_*.c | net/netfilter/xt_*.c |
扩展:conntrack、mark、limit、LOG… |
| ip_tables | net/ipv4/netfilter/ip_tables.c |
filter/nat/mangle 表 |
| nft_compat | nft_compat.c |
可选:iptables 规则转 nft 后端 |
xt_conntrack.c 依赖 nf_conntrack;xt_set.c 依赖 ipset。
7. nfnetlink 控制面
nfnetlink.c 实现 NETLINK_NETFILTER,子系统分发表 table[NFNL_SUBSYS_*]:
| 子系统 | 用途 |
|---|---|
NFNL_SUBSYS_NFTABLES |
nft 表/链/规则 |
NFNL_SUBSYS_CTNETLINK |
conntrack 查询/事件 |
NFNL_SUBSYS_IPSET |
ipset 管理 |
NFNL_SUBSYS_QUEUE |
NFQUEUE |
NFNL_SUBSYS_HOOK |
hook 查询(新) |
每 netns:netlink_kernel_create(net, NETLINK_NETFILTER, &cfg)。
详见 10-netlink内核用户通信机制与实现详解.md。
8. 辅助子系统
8.1 ipset(ipset/)
ip_set_core.c:集合类型注册、ip_set_test/add/del- 类型:
hash:ip、hash:net、bitmap:port等(ip_set_hash_*.c) - 供
xt_set/nft_lookup做大规模地址/端口匹配
8.2 nf_flow_table(快速转发)
nf_flow_table_core.c + nft_flow_offload.c:
- 对已 ESTABLISHED 连接缓存
flow_offload条目 - 后续包可 绕过部分协议栈 直接转发(可硬件 offload)
- 依赖 conntrack tuple
8.3 ipvs(ipvs/)
Linux Virtual Server:L4 负载均衡,独立 hook 与调度器(rr、wlc、mh 等),与 filter/NAT 可叠加。
8.4 nf_queue / nf_log
nf_queue.c:NF_QUEUEverdict 将 skb 送用户态(如iptables -j NFQUEUE)nf_log.c/nfnetlink_log.c:LOG/NFLOG 目标
9. 模块依赖关系(简化)
10. 调试与 sysctl(常用)
1 | # 规则 |
11. RK3588 场景
| 场景 | 关注点 |
|---|---|
| 网关/路由器 | nf_conntrack_max、FORWARD 链默认 policy、MASQUERADE |
| Android/嵌入式 | iptables-legacy 或 nft;热点 NAT |
| 容器 | netns 隔离;每 netns 独立 nft 表与 conntrack |
| 性能 | 规则数量、nf_flow_table、避免过多 xt_recent/hashlimit |
| WiFi AP | bridge + iptables FORWARD;或 nft forward chain |
无 net/netfilter/ 内 RK 补丁;板级差异来自 defconfig(CONFIG_NF_* 开关)与用户态规则。
12. 源码索引
| 主题 | 路径 |
|---|---|
| Hook 注册/执行 | net/netfilter/core.c |
nf_hook 内联 |
include/linux/netfilter.h |
| conntrack 入口 | net/netfilter/nf_conntrack_core.c:nf_conntrack_in |
| NAT | net/netfilter/nf_nat_core.c |
| nft 求值 | net/netfilter/nf_tables_core.c:nft_do_chain |
| nft 配置 API | net/netfilter/nf_tables_api.c |
| nft hook 绑定 | net/netfilter/nft_chain_filter.c |
| nfnetlink | net/netfilter/nfnetlink.c |
| ipset | net/netfilter/ipset/ip_set_core.c |
| flow offload | net/netfilter/nf_flow_table_core.c |
| IPv4 iptables | net/ipv4/netfilter/ip_tables.c |
13. 相关文档
14. 小结
| 问题 | 答案 |
|---|---|
| netfilter 在哪介入? | 协议栈 NF_INET_* hook 点,对 sk_buff 裁决 |
| 框架核心文件? | core.c(nf_hook_slow) |
| 现代防火墙 API? | nftables(nf_tables + nft_*) |
| 状态防火墙基础? | nf_conntrack + 可选 nf_nat |
| 如何配置? | 用户态 nft/iptables → NETLINK_NETFILTER |
| 与驱动关系? | 无直接耦合;仅处理已进入网络栈的包 |
正在加载留言…