Netfilter钩子是内核网络子系统扩展,适用于中低吞吐、高灵活性场景,如协议字段检查或会话策略,单核处理10–50万PPS;不适合10G+线速过滤或海量规则匹配。

明确适用场景与性能边界
Netfilter 钩子适合中低吞吐、高灵活性场景,比如:深度协议字段检查(非正则)、会话级策略(如基于 TCP 状态+自定义标签的放行/重定向)、与用户态协同(通过 netlink 传递事件)。它运行在软中断上下文,单 CPU 核处理能力通常在 10–50 万 PPS(取决于逻辑复杂度)。
不适合:线速 10G+ 过滤、海量规则匹配(如百万 ACL 条目)、需要零拷贝或绕过协议栈的场景(此时应选 XDP)。
核心钩子注册与高效编码原则
在模块初始化中注册钩子时,注意三点:
-
选择最小必要优先级:例如仅需过滤 IP 层,用
NF_INET_PRE_ROUTING;避免在NF_INET_LOCAL_IN处理本机流量,除非真要拦截本地 socket 接收 -
钩子函数必须极简:禁止睡眠(不可调用
msleep、wait_event)、禁用浮点、避免大循环或复杂查找。常用优化:
▪ 使用 per-CPU 变量缓存统计计数
▪ 用哈希表(struct rhashtable)替代链表遍历
▪ 对固定格式报文(如 IPv4+TCP),用指针偏移直接取字段,跳过skb_header_pointer()拷贝 -
尽早返回 verdict:能
NF_DROP就别NF_ACCEPT后续再丢;对确定放行包,用NF_STOLEN避免继续走协议栈(需自行释放 skb)
规避常见陷阱
以下问题极易导致崩溃或性能骤降:
-
skb 共享与克隆误操作:修改
skb->data前必须调用skb_make_writable(),否则可能破坏其他模块引用的共享缓冲区 -
并发安全被忽略:钩子在软中断中并发执行,全局变量需加
spin_lock_bh()(不能用 mutex);rhashtable 插入/查找本身线程安全,但业务逻辑仍需保护 - 忘记清理资源:模块卸载时必须注销所有钩子、销毁哈希表、释放 per-CPU 内存,否则下次加载会因重复注册失败或内存泄漏
比纯钩子更优的现代替代方案
若目标是“高性能清洗”,请优先评估:
-
XDP(eXpress Data Path):在网卡驱动层运行,支持
xdp_drop/xdp_redirect,10G 线速下可达千万 PPS。用 C + LLVM 编译为 BPF 字节码,无需写内核模块 - nftables + ct helper + meta 表达式:声明式配置,内核自动优化匹配路径,支持连接跟踪、限速、geoip 扩展,运维友好
-
eBPF tc classifier(cls_bpf):在内核 TC 子系统中挂载 BPF 程序,可做精细流控与标记,配合
tc filter add ... bpf部署
纯 Netfilter 钩子模块应作为最后手段——仅当你需要访问内核私有结构(如 struct nf_conn 内部字段)、或与现有 Netfilter 模块(如 iptables 扩展)深度耦合时才考虑。



















