eBPF开发指南

时间:2024-10-10 22:43:39

0x1:技术背景

bpf:

BPF 的全称是 Berkeley Packet Filter,是一个用于过滤(filter)网络报文(packet)的架构。(例如tcpdump),目前称为Cbpf(Classical bpf)

Ebpf:

eBPF全称 extended BPF,Linux Kernel 3.15 中引入的全新设计, 是对既有BPF架构进行了全面扩展,一方面,支持了更多领域的应用,比如:内核追踪(Kernel Tracing)、应用性能调优/监控、流控(Traffic Control)等;另一方面,在接口的设计以及易用性上,也有了较大的改进。

eBPF 支持在用户态将 C 语言编写的一小段“内核代码”注入到内核中运行,注入时要先用 llvm 编译得到使用 BPF 指令集的 ELF 文件,然后从 ELF 文件中解析出可以注入内核的部分,最后用 bpf_load_program() 方法完成注入。 用户态程序和注入到内核中的程序通过共用一个位于内核的 eBPF MAP 实现通信。为了防止注入的代码导致内核崩溃,eBPF 会对注入的代码进行严格检查,拒绝不合格的代码的注入。

  1. eBPF prog load的严格的verify机制
  2. eBPF访问内核资源需借助各种eBPF 的helper func,helper func函数能在最坏的情况下保证安全
  3. 现在,Linux 内核只运行 eBPF,内核会将加载的 cBPF 字节码 透明地转换成 eBPF 再执行

0x2:技术对比

优劣 eBPF 源码开发 热补丁
优势 1.安全,不会引起宕机
2.自主,可控
2.热加载(良好的加载/卸载流程)
3.开启CO-RE后,移植性高,适配量小
4.可以在注入的代码中写入业务逻辑,优化hids性能
5.开发难度低,上手快
1.体积小
2.*度高
3.性能高
4.功能强大
1.体积小
2.*度高
3.性能高
4.热加载,不需要重启
缺点 1.功能受限(验证器)
2.强依赖于内核版本
3.不支持内核函数调用
4.单函数最大512byte栈空间,通过尾调用扩展到8K
5.性能不如其他两者
1.需要重新编译内核
2.需要重启业务主机
3.需要开发者熟悉内核
4.适配工作量巨大
上发数据有性能瓶颈
1.需要开发者熟悉内核
2.适配工作量大

0x3:运行流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

用 C 编写 BPF 程序
用 LLVM 将 C 程序编译成对象文件(ELF)
用户空间 BPF ELF 加载器(例如 libbpf)解析对象文件
加载器通过 bpf() 系统调用将解析后的对象文件注入内核
内核验证 BPF 指令,然后对其执行即时编译(JIT),返回程序的一个新文件描述符
利用文件描述符 attach 到内核