01 · 研究定位与问题定义
1.1 为什么检测引擎必须下沉到内核
在TLS 1.3与QUIC成为默认、ECH逐步抹平SNI明文的时代(详见本子课题首页姊妹篇"TLS/QUIC流量分析"),被动监测的可用信息已整体下沉到流级统计与行为轮廓。但信息下沉的同时,流量规模却在膨胀:企业出口、云主机网卡上的链路速率普遍进入10/25/40Gbps时代。以10Gbps链路、最小包场景估算:按64字节线速包计算,全线卡包率约14.88 Mpps(1488万pps),即使摊到多个CPU核,每个核也面临百万级pps的包处理预算。任何"先把包拷贝到用户空间再慢慢分析"的传统架构,都会在这条算力预算面前崩溃。
对迪妙网络空间安全学院所深耕的反钓鱼、反诈骗与企业安全意识培训业务,eBPF路线给出三重重合的必然性:
- 性能墙——内核态处理消除拷贝与系统调用。XDP程序运行在网卡驱动的软中断上下文,报文尚未创建内核协议栈数据结构(skb)即可完成过滤、计数与特征预提取;公开基准显示通用服务器单核即可达到千万级pps的原始包处理能力(XDP论文报告的弃包基准为单核24 Mpps)[1]。用户空间方案每包至少要付出一次内存拷贝加一次系统调用的固定成本,这是数量级的差距,不是调优所能弥合的。
- 可见性墙——云原生场景中网卡是最后的共同分母。容器、Sidecar、Service Mesh让应用层的观测点碎片化;而无论流量如何编排,最终都要经过宿主机的网络栈。eBPF配合cgroup与namespace过滤,可以在不侵入容器的前提下实现主机级统一观测——这正是加密C2检测在混合云环境落地的现实路径[7]。
- 合规墙——零解密边界要求"就地提取、不留载荷"。《个人信息保护法》的最小必要原则与本课题首页确立的零解密方法论,要求特征提取在数据面就地完成:内核态只产出统计量与结构化元数据,载荷本身不落地、不缓存、不回传。eBPF程序经verifier静态验证、运行沙箱化,恰是满足该约束的技术形态。
核心工程命题:能否在不触碰明文、不破解密码、不引入内核模块安全风险的前提下,把"加密流量残余信息通道"的提取成本,压低到线速可承受、部署可普及、行为可审计的工程水位?本课题三页的研究依次回答:内核机制允许什么(第1页)、特征如何低开销提取(第2页)、判定与评估如何闭环(第3页)。
1.2 三代数据包处理技术的演进对比
数据包高性能处理大体经历了三代技术路线:以libpcap/AF_PACKET为代表的内核旁路读取、以DPDK为代表的用户态轮询旁路、以XDP/eBPF为代表的内核内可编程处理。三者并非简单的替代关系,而是在拷贝次数、上下文切换、可编程性、部署侵入性四个维度上的不同取舍:
| 维度 | AF_PACKET + libpcap | DPDK 内核旁路 | XDP · eBPF 内核可编程 |
|---|---|---|---|
| 包拷贝 | 每包多次拷贝(skb与ring之间) | 零拷贝(轮询驱动 + 巨页) | 无额外拷贝,内核上下文就地处理;AF_XDP可零拷贝直达用户空间 |
| 上下文切换 | 每包系统调用与唤醒 | 无(独占核轮询) | 无(软中断上下文执行) |
| 可编程性 | 有限(经典BPF过滤器) | 完整的用户态C,自由但危险 | 内核沙箱C:经verifier验证,内核API以辅助函数形式受控开放 |
| 部署门槛 | 低(普适) | 高:独占CPU核、网卡绑定、驱动改造、大页内存 | 中:内核≥4.8,主流发行版开箱可用 |
| 与内核协同 | 原生 | 差:旁路后回注内核路径复杂 | 原生:与协议栈、cgroup、Netfilter同一观测平面 |
| 硬件卸载 | 不支持 | 部分(网卡流分类) | 支持:XDP可卸载至兼容网卡硬件 |
综合参考:[1] XDP论文(CoNEXT 2018);[2] Gregg《BPF Performance Tools》;[9] DPDK官方资料。各项为定性归纳,具体数值随硬件与内核版本变化。
迪妙的取舍逻辑:DPDK是网络设备商与超大规模基础设施的理性选择,但对需要"在客户普通服务器上即插即用"的安全检测产品而言,部署侵入性是不可接受的门槛。eBPF路线以接近DPDK的量级性能(XDP层)叠加原生内核协同能力,成为本课题检测引擎的底座。
1.3 研究边界与合规声明
合规与伦理声明:本课题全部eBPF程序运行于自有授权的实验与演练环境,仅用于防御研究与安全教育:不利用eBPF实现隐蔽持久化或绕过内核安全机制,不采集与本课题无关的业务载荷;文中对verifier缺陷(如CVE-2022-23222)的引用仅用于说明安全演进的必要性,不提供任何利用细节。所有检测目标均为零解密前提下的元数据与统计特征。
02 · eBPF体系结构深析
2.1 从cBPF到eBPF:一次三十年的递归
eBPF的血统可以追溯到1993年McCanne与Jacobson在USENIX发表的经典论文:BSD Packet Filter(BPF)以一套基于寄存器的伪指令集在内核态完成包过滤,把"无用包不出内核"的思想变成了系统调用级的性能收益——今天tcpdump的每一个过滤表达式仍是cBPF的活遗产[5]。2014年,Starovoitov在Linux 3.18中引入扩展版BPF:寄存器从2个扩至10个(64位)、引入Map键值存储、支持以bpf(2)系统调用动态加载程序——一个面向通用内核可编程的执行引擎就此诞生,而不再只是包过滤器[3][8]。此后十年,eBPF挂载点从网络扩展到跟踪、安全、调度等子系统,形成今天内核可观测性的基础设施地位。
2.2 执行模型五要素
eBPF程序不是自由运行的内核模块,而是受五要素约束与支撑的事件驱动沙箱。理解这五要素,是后续一切工程决策的前提:
2.3 验证器:安全保证、机制与历史教训
验证器(verifier)是eBPF区别于内核模块的本质设计。它采用抽象解释(abstract interpretation)技术逐指令模拟程序执行:追踪每个寄存器的类型(标量/指针/未知值)与值域,校验所有内存访问的边界可证明性,拒绝存在死代码或无法证明终止性的控制流图。对网络检测而言,这意味着:一段解析TLS ClientHello的eBPF程序,在加载时即被保证不会越界读写内核内存——传统内核驱动最危险的整类缺陷(内存破坏、任意读写)被架构性消除[3]。
但验证器并非数学意义上的完美:历史上出现过边界检查逻辑被绕过的案例,CVE-2022-23222即为代表——攻击者构造特殊程序使验证器对指针算术的推断出错,进而获得越界写能力。该漏洞被CISA已知被利用漏洞目录收录,也推动社区持续加固:引入更严格的指针状态追踪、扩大形式化验证研究、并发展出BPF程序的可信加载与审计生态[6]。对防御方这带来一条工程戒律:eBPF程序本身也必须纳入资产清单与漏洞管理,引擎的Map命中率、加载失败与热更新记录应全部留痕审计(第2页5.4节展开)。
2.4 eBPF与传统内核模块的本质差异
在部署讨论中,eBPF常被简化为"更安全的内核模块"。这个概括方向正确,但工程决策需要更细的对比——两者在失败影响域、接口攻击面、更新方式、可审计性上的差距,正是检测引擎敢以普通服务器为载体的前提:
| 维度 | 传统内核模块(LKM) | eBPF程序 |
|---|---|---|
| 内存安全 | 完全依赖开发者自律,越界/竞态/UAF可直接破坏内核 | verifier静态验证,架构性消除越界读写类缺陷 |
| 失败影响域 | 一个空指针即可Panic整个系统 | 验证失败即拒绝加载;运行时错误被限制在程序自身上下文 |
| 内核接口 | 可调用任意内核符号,攻击面与内核本体同宽 | 仅辅助函数白名单,能力以程序类型为界受控开放 |
| 更新方式 | insmod/rmmod,常与内核版本强耦合,升级需停机 | BPF link原子替换,业务不中断,可灰度可回滚 |
| 可审计性 | 无统一枚举手段,运行时行为难以留痕 | bpftool prog/map 全量枚举,可纳入资产与漏洞管理 |
| 部署门槛 | 高:内核头文件、GPL许可、版本签名 | 中:内核≥4.8即随发行版可得,CO-RE免除头文件依赖 |
对比维度依据内核文档[3]、Gregg[2]与Cilium文档[7]对eBPF安全模型的论述归纳,为定性对比而非基准测量。
03 · 网络挂载点全景与包处理路径
3.1 挂载点能力层级
eBPF在网络栈上提供了梯度化的挂载点体系。选择哪个挂载点,本质是在处理时机(越早开销越低但信息越少)、可见深度(能否看到完整skb与载荷前段)、动作能力(能否丢弃/重定向/打标)三者间做工程权衡:
| 挂载点 | 合入内核 | 包可见度与动作能力 | 在本课题中的用途 |
|---|---|---|---|
| XDP | 4.8+ | 驱动层、skb创建前;PASS / DROP / REDIRECT / TX 四种动作,可经CPU map重定向至指定核 | 线速过滤与预提取:五元组哈希、包长计数、明显无关流量早丢弃 |
| TC(cls_bpf / act_bpf) | 4.1+ | qdisc层,可见完整skb、套接字元数据与载荷前N字节;eBPF作为TC classifier/action的挂载能力于4.1合入,direct-action(da)模式4.4,clsact qdisc 4.5 | 主战场:TLS ClientHello解析、流级统计特征计算、JA4字段提取 |
| socket filter | 3.19+ | socket收包路径,无动作能力,仅过滤 | tcpdump同源的低开销过滤;单进程针对性观测 |
| cgroup skb / sock | 4.x | 容器cgroup出入口,可做计量与策略判定 | 多租户与容器归属标记:流量来自哪个Pod/容器 |
| sk_skb / sk_msg | 4.14—4.17周期 | sockmap(4.14周期合入)之上的流重定向与消息钩子,报文不经TCP栈常规路径;sk_skb/sk_msg程序类型在4.14—4.17周期陆续可用 | L4代理加速等专项架构(本课题不展开) |
| netfilter BPF钩子 | 6.4+ | nf钩子点,与iptables/nftables同平面协同 | 与既有防火墙策略联动的过滤与打标(新兴方向) |
版本依据:内核源码net/sched/cls_bpf.c、sch_clsact.c合入记录、docs.ebpf.io程序类型版本标注,以及tc direct-action模式的公开考据交叉核对[3][8][10][12]。
3.2 XDP四种动作与重定向地图
XDP程序对每包返回四种 verdict 之一:XDP_PASS(放行进入常规内核路径)、XDP_DROP(静默丢弃)、XDP_TX(从原网卡直接发回)、XDP_REDIRECT(经devmap/CPU map重定向至指定网卡或CPU核)。其中DROP与REDIRECT是本课题检测引擎的"性能逃生舱"——对明确无关的流量(非TCP/UDP 443、已知良性大流量)在最早的位置丢弃,为后续深度解析腾出CPU预算;而判定为可疑的流则可经CPU map重定向至专用核,交由TC层做细粒度分析,实现分核分层的流水线[1][2]。
3.3 一个数据包的内核旅程:观测点标注
3.4 XDP三种运行模式与硬件卸载
同一个XDP程序在不同硬件/驱动条件下有三种运行模式,性能差距可达数量级。部署前必须通过 bpftool net 或驱动日志确认实际生效的模式,这是检测引擎上线检查表的第一项:
| 运行模式 | 执行位置与前提 | 性能特征与适用性 |
|---|---|---|
| Native(DRV) | 网卡驱动接收路径直接执行,要求驱动实现ndo_bpf钩子(ixgbe、i40e、mlx5、virtio_net等主流驱动均支持) | 性能最优形态,XDP论文24 Mpps基准即出自此模式;生产检测引擎的目标形态 |
| Offloaded | 程序经兼容智能网卡卸载至硬件执行 | 主机CPU完全不参与包处理;受限于特定硬件,适合作为超大规模节点的可选项 |
| Generic(SKB) | 驱动不支持时的通用回退:程序在内核协议栈早期以skb形式执行 | 性能显著低于前两者,仅适合开发调试;生产引擎检测到Generic模式应触发部署告警 |
三种模式语义依据Linux内核XDP文档与xdp-tools资料[3][8];模式探测方法见bpftool net输出中的"drv/hw/generic"标识。
3.5 AF_XDP:到用户空间的零拷贝通道
XDP_REDIRECT 的另一类目的地是用户空间:AF_XDP(XDP socket,内核4.18引入)允许XDP程序将报文重定向到绑定特定网卡队列的用户空间套接字,应用直接读写与网卡DMA共享的UMEM缓冲区。此处必须给出精确的工程事实:零拷贝模式依赖驱动的显式支持——首个零拷贝驱动补丁于4.19周期合入(ixgbe),并在后续内核版本中扩展到更多驱动(DPDK的AF_XDP PMD文档将零拷贝能力标注为需要内核≥5.4;i40e、mlx5、virtio_net等的零拷贝支持在5.x—6.x周期陆续合入);不具备零拷贝能力时的拷贝模式(copy mode)则普适可用,但每包多付出一次内存拷贝。XDP论文§6.7记录的初步测试显示,其内核到用户空间传输可达约20 Mpps/核[1]。
对本课题的意义:当某类计算超出内核表达能力(复杂多流关联、需要浮点的算法)时,AF_XDP提供了一条接近内核旁路速率、却无需独占CPU与内核旁路的"重计算下沉"通道;而Ring Buffer(第2页4节)继续承担低带宽、高价值的事件上报。两者按特征的信息量与计算成本分工:全量包级处理走AF_XDP,摘要与告警走Ring Buffer。
04 · 运行时约束与工程边界
4.1 必须遵守的硬约束
eBPF的"安全"与"低开销"是以一组严格的运行时约束换来的。检测算法必须在这些约束内设计,或者明确把重计算下沉用户空间:
| 约束项 | 具体限制 | 对检测引擎设计的影响 |
|---|---|---|
| 栈空间 | 固定512字节,无动态分配 | ClientHello解析须分段读取(bpf_skb_load_bytes分段载入),不能整包缓冲 |
| 指令复杂度 | 约100万条上限(Linux 5.2+) | 复杂解析逻辑拆分多程序串联,或下沉用户空间 |
| 循环 | 仅允许可证明上界的有界循环(Linux 5.3+) | 扩展列表遍历设硬上限(如最多64个扩展项),超限即放弃精细特征 |
| 状态存储 | 无堆内存,全部状态须经预声明的Map | 流表容量、条目大小在设计期确定;Map类型与淘汰策略需选型(第2页1.2节) |
| 浮点运算 | 传统上不支持浮点 | 统计特征以定点整数实现:均值用移位定点、方差用整数Welford递推 |
| 执行上下文 | 常规网络程序运行于不可休眠上下文 | 禁止阻塞操作;事件上报走无锁Ring Buffer,杜绝 sleep/wait |
依据:Linux内核BPF文档[3]、内核版本变更记录(kernel.org)。部分约束(如5.3起允许有界循环、5.2放宽指令上限)为明确的版本节点,生产部署需核对目标内核版本。
4.2 CO-RE与BTF:可移植性的工程前提
内核数据结构随版本变化,是eBPF生产部署的最大痛点。CO-RE(Compile Once, Run Everywhere)机制通过BTF(BPF Type Format,内核4.18合入)携带内核类型信息,配合libbpf的重定位逻辑,使同一份编译产物可在不同内核版本上安全运行;Nakryiko的CO-RE参考指南(2020年4月首发)是该机制事实上的权威文档[4]。对检测引擎而言,CO-RE意味着:特征提取逻辑可以版本化、可灰度发布——这与第3页将讨论的"模型热更新"构成同一套工程纪律。
4.3 能力边界声明
本课题不做、也不能做的事:eBPF检测引擎无法解密流量(无密钥、不实施中间人),无法看到ECH内层的真实SNI,无法保证对故意模仿良性行为的加密C2百分之百识别。它的定位是:在零解密合规边界内,以线速可承受的成本,稳定产出高质量的流级特征与结构化元数据——判定由第3页的推理架构完成,对抗与局限在第3页5节诚实列出。
04b · 观测面真实性:网卡卸载与包聚合对检测语义的影响
4b.1 一个容易被忽视的前提:TC层看到的不是网卡上的包
加密流量特征的有效性,建立在"统计对象=线上真实报文"的隐含假设上。但现代网卡与内核的接收卸载机制会在观测点之前改写报文的呈现形态。其中最典型的是GRO(Generic Receive Offload,含其硬件形态LRO):驱动在NAPI轮询中将同一条流的多个TCP段聚合成一个"超级skb",聚合发生在netif_receive_skb之前——也就是说,TC ingress挂载点看到的已经是聚合后的段组而非线上原始包。后果是系统性的:
- 包数被低估(n个线上包呈现为1个skb),直接压低包率类特征;
- 包长均值被高估(呈现的是聚合段的长度),包长矩的均值/方差口径整体漂移;
- IAT与burst失真:段内各包的到达间隔被抹平,burst计数对"突发加密传输"的敏感性显著下降——而burst恰是区分交互式信道与批量传输的高价值特征(第2页3.2节)。
出站方向对称地存在TSO/GSO:TC egress看到的是尚未分段的大skb(长度可达数千字节),出方向包长统计呈现的是"段语义"而非"线上语义"。RSS多队列本身不改变包内容,但与per-CPU流表设计叠加后会影响跨核归并成本(第2页1.4节已述)。
| 机制 | 作用位置 | 对特征的影响 | 工程对策 |
|---|---|---|---|
| GRO / LRO | 驱动NAPI轮询(TC ingress观测点之前) | 包数低估、包长/IAT/burst全面失真(入方向) | 包级统计以XDP层为准(XDP在GRO之前执行,所见即线上包);或在镜像/分流口以 ethtool -K 关闭 gro/lro 后观测;特征口径在训练与推理两侧保持一致 |
| TSO / GSO | 协议栈出方向(TC egress观测点之前) | 出方向包长呈段语义(可达MTU的数十倍) | 方向分离统计时标注段语义;或在观测口禁用gso后采集;JA4等握手特征不受影响 |
| Checksum卸载 | 网卡 | 不影响包长/时序,无需处理 | —— |
| RSS多队列 | 网卡 | 不改变包内容;影响流在CPU核间的分布 | 队列与CPU亲和绑定,使同流同核(第2页1.4节) |
依据:Linux内核接收路径处理顺序(netif_receive_skb、dev_gro_receive合入位置)与ethtool卸载开关语义,属内核公开实现事实[3][10]。本节的工程价值在于:把"观测点选择"从性能权衡问题升级为特征正确性问题。
4b.2 对本课题架构的直接影响
上述事实为第1页3.1节的分层架构补上了最后一条选型理由:XDP层不仅吞吐最高,而且是唯一能看到"线上真实包长与包率"的挂载点——因此包长矩、IAT直方图、burst计数的原始计量必须在XDP层完成;TC层负责解析深度(握手结构、载荷前N字节),其包级计数只作为交叉校验通道。两层的同流计数差(TC数 ≤ XDP数)本身可作为GRO状态的运行期探针:差值异常扩大即提示观测面形态漂移,纳入第3页Runbook健康指标。
一句话总结:eBPF检测引擎统计的不是"流量本身",而是"流量在某一观测点的呈现形态"。观测形态由网卡卸载机制决定——不管理形态,特征口径就是不可审计的。
05 · 与主流方案的综合对比与本页小结
| 方案 | 线速包处理 | 加密流量元数据深度 | 部署侵入性 | 典型适用者 |
|---|---|---|---|---|
| eBPF / XDP | 千万级pps/核(公开基准[1]) | 握手结构、流统计、容器归属(不解密) | 低:内核≥4.8,随发行版可得 | 安全检测、可观测性、云原生网络策略 |
| DPDK | 线速(专用核轮询) | 取决于上层应用自建逻辑 | 高:独占核、绑定网卡 | 电信设备、超大规模网关 |
| 智能网卡 / DPU | 硬件线速卸载 | 预置流表,可编程性受限 | 中:硬件采购与适配 | 大型数据中心、运营商 |
| 云流日志(VPC Flow Logs) | 事后汇总,分钟级延迟 | 五元组/字节数,无载荷前段 | 无(托管服务) | 云租户合规审计、粗粒度排查 |
5.1 产业采用现状
产业实践为上述结论提供了独立旁证:Cloudflare自2018年起公开其基于XDP/eBPF的L4层DDoS缓解系统L4Drop,支撑其边缘网络的毫秒级大规模缓解能力[11];Meta开源的Katran将XDP用于四层负载均衡转发面,随网卡RX队列数线性扩展、经受了超大规模生产流量的长期检验[28];Cilium生态(Hubble流量可视化、Tetragon运行时威胁检测)、Falco与Suricata等项目,已把eBPF带入容器网络、运行时安全与IDS传感器的主流行列[7][27][29][30]。这些事实共同说明:eBPF数据面已经过了超大规模生产的长期检验,本课题将其用作检测引擎底座,风险主要在于工程实现而非技术方向。
本页的核心结论可归纳为一句话:eBPF把"检测点下沉到数据面"从DPDK时代的重型工程,变成了普通服务器上可部署、可审计、可热更新的常规能力。它为第2页的特征提取工程提供了机制基础:XDP负责成本最低的预提取,TC负责最有信息量的解析,AF_XDP为超限计算预留零拷贝下沉通道,Map负责状态,Ring Buffer负责出口。下一页将进入真正的工程深水区——流表设计、TLS/QUIC握手特征的内核态提取与开销控制。
05b · 上线前检查清单(Go / No-Go)
检测引擎进入生产或演练环境前,以下检查项逐项通过方可放行;任一关键项(★)不通过即触发部署阻断:
| # | 检查项 | 验证命令 / 方法 | 级别 |
|---|---|---|---|
| 1 | XDP实际运行模式为 Native(drv),非 Generic | bpftool net 输出含 drv 标识;Generic模式触发部署告警 | ★ |
| 2 | 内核BTF存在(CO-RE前提) | ls /sys/kernel/btf/vmlinux | ★ |
| 3 | 内核版本满足特性底线(≥5.8取Ringbuf;老内核确认Perf降级路径) | uname -r 对照第1页04节约束表 | ★ |
| 4 | 观测口卸载形态确认:包级特征以XDP层为口径,TC层计数作交叉校验 | 比对同流两层包数差(4b.2节探针) | ★ |
| 5 | 流表容量×条目字节数的内存预算复核并留档 | 容量上限 × 第2页3.3节约160B预算 | ★ |
| 6 | 逃生开关演练:XDP直通(PASS)可在不中断流量下生效 | 预演切换与回滚各一次并计时 | ★ |
| 7 | 权限最小化:仅CAP_BPF + CAP_PERFMON + CAP_NET_ADMIN,无CAP_SYS_ADMIN、无privileged容器 | bpftool prog show / 容器securityContext审计 | ★ |
| 8 | RSS队列与CPU亲和绑定生效 | /proc/interrupts 与网卡队列配置核对 | ○ |
| 9 | Ringbuf丢弃计数Map可读,丢弃率纳入监控 | 引擎健康面板/手工bpftool map dump | ○ |
| 10 | 引擎自身资产留痕:程序清单、加载时间、哈希档 | bpftool prog show + 变更审批记录 | ○ |
检查项1—3、7对应内核公开机制[3][8];项4对应本页4b节;项6对应第2页4.4节背压治理与P3逃生机制。
本节参考文献(第1页 · [1]—[12])
Høiland-Jørgensen, T., et al. "The eXpress Data Path: Fast Programmable Packet Processing in the Operating System Kernel", ACM CoNEXT, 2018. dl.acm.org/doi/10.1145/3281411.3281443
Gregg, B. "BPF Performance Tools: Linux System and Application Observability", Addison-Wesley, 2019.
Linux Kernel Documentation. "BPF Documentation" 与 "AF_XDP", kernel.org/doc/html/latest/bpf/;kernel.org/doc/html/latest/networking/af_xdp.html
Nakryiko, A. "BPF CO-RE reference guide", 2020年4月首发. nakryiko.com/posts/bpf-core-reference-guide/
McCanne, S., Jacobson, V. "The BSD Packet Filter: A New Architecture for User-level Packet Capture", USENIX Winter Technical Conference, 1993.
NVD. "CVE-2022-23222: Linux Kernel eBPF verifier boundary check bypass", nvd.nist.gov/vuln/detail/CVE-2022-23222(CISA KEV收录)
Cilium Authors. "Cilium Documentation: eBPF-based Networking, Security and Observability", docs.cilium.io/
eBPF Community. "eBPF Documentation & Resources", ebpf.io/;libbpf项目,github.com/libbpf/libbpf;xdp-tools项目,github.com/xdp-project/xdp-tools
DPDK Project. "Data Plane Development Kit", dpdk.org/
Linux Kernel Source. "net/core/filter.c、net/sched/cls_bpf.c、kernel/bpf/ 实现", git.kernel.org(torvalds/linux)
Fabre, A. "L4Drop: XDP DDoS Mitigations", Cloudflare Blog, 2018. blog.cloudflare.com/l4drop-xdp-ebpf-based-ddos-mitigations/
Monnet, Q. "Understanding tc 'direct action' mode for BPF", Whirl Offload, 2020. qmonnet.github.io/whirl-offload/2020/04/11/tc-bpf-direct-action/