eBPF Verifier Principles and the Implementation of a High-Performance Security Detection Engine

免责声明:本文为个人技术学习与工程实践笔记,所涉操作仅应在获得授权的环境中进行。因不当使用造成的后果由使用者自行承担。

在 Kubernetes 环境中,Calico 的网络实现与 eBPF 关系密切。本文沿这条线索梳理 eBPF 的整体架构与验证器的工作方式,并给出一个用于安全检测的实践示例,作为学习笔记记录下来。

什么是 eBPF

eBPF(extended Berkeley Packet Filter)是一项起源于 Linux 内核的技术,它可以在特权上下文中(如操作系统内核)运行沙盒程序

简言之,它通过在操作系统内核中执行沙盒程序,在不修改内核源码或加载内核模块的前提下安全便捷地扩展内核能力

从历史上看,由于内核具有监督和控制整个系统的特权,操作系统一直是实现可观测性、安全性和网络功能的理想场所。同时,由于操作系统内核的核心地位和对稳定性和安全性的高要求,操作系统内核很难快速迭代发展。因此在传统意义上,与在操作系统本身之外实现的功能相比,操作系统级别的创新速度要慢一些。

整体架构

用户态

程序编写:开发者使用 eBPF 汇编或受限 C 语言编写内核逻辑。由于内核环境的特殊性,编写时需遵循 eBPF 特有的辅助函数(Helpers)和语法约束。

字节码编译:借助 LLVM/Clang 编译器前端及 eBPF 后端,将源代码编译为体系结构无关的 eBPF 字节码(Bytecode),确保程序具备跨内核版本的兼容性。

内核加载:通过调用 bpf() 系统调用,将生成的字节码注入内核。在正式运行前,内核验证器(Verifier)会对指令进行静态分析,确保其安全且不会导致系统崩溃。

内核态

安全验证 (Verifier):内核验证器对注入的字节码进行严格的静态分析。它会检查代码是否存在死循环、非法内存访问或堆栈溢出,确保内核的绝对安全。

即时编译 (JIT Compiler):通过验证后,JIT 编译器将通用字节码翻译成当前 CPU 架构(如 x86, ARM)的原生机器码,以实现近乎原生的运行性能。

挂载与触发 (Hooks):程序被附加到特定的内核事件(如网络包到达、系统调用、kprobes 等)。当事件触发时,eBPF 程序立即执行。

状态共享 (Maps):程序在执行过程中,通过 eBPF Maps 将处理结果(如统计数据、监控日志)传回用户态,实现两个层级的数据闭环。

编写第一个 eBPF 程序

直接手写 bpf() 系统调用较为繁琐,借助高层工具更容易理解其工作机制。先准备环境:

1
2
sudo apt update
sudo apt install -y bpftrace

下面的指令用于实时监控 openat 系统调用的执行者,即当前正在打开文件的进程:

1
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s (PID %d) is opening a file\n", comm, pid); }'

image-20260328004024956

在新终端中执行命令,上述监控会实时输出结果。BCC 允许用 C 编写内核逻辑、用 Python 编写用户态逻辑,先安装 BCC

1
sudo apt install -y bpfcc-tools python3-bpfcc

下面这个程序采用相同的思路,监控所有 clone() 系统调用,即进程创建事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# hello_ebpf.py
from bcc import BPF
program = """
int hello_world(void *ctx) {
bpf_trace_printk("Hello Ubuntu! New process created.\\n");
return 0;
}
"""
# 加载程序
b = BPF(text=program)
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello_world")
print("正在监控进程创建")
try:
b.trace_print()
except KeyboardInterrupt:
exit()

image-20260328004316589

理解上述流程之后,可以进一步实现一个基于 XDP(eXpress Data Path)的简单防火墙。XDP 运行在网卡驱动层,甚至在内核协议栈处理数据包之前,这意味着可以以极高的性能丢弃(Drop)攻击包,而不会消耗 CPU 去解析复杂的协议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from bcc import BPF
import time
import sys

# 屏蔽来自 8.8.8.8 的流量
BLOCK_IP = "8.8.8.8"

# 内核态 C 代码
program = """
#include <uapi/linux/bpf.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/ip.h>

int xdp_firewall(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
if ((void*)eth + sizeof(*eth) > data_end)
return XDP_PASS;
if (eth->h_proto != htons(ETH_P_IP))
return XDP_PASS;
struct iphdr *iph = data + sizeof(*eth);
if ((void*)iph + sizeof(*iph) > data_end)
return XDP_PASS;
if (iph->saddr == 0x08080808) {
bpf_trace_printk("Drop packet from 8.8.8.8\\n");
return XDP_DROP;
}
return XDP_PASS;
}
"""
device = "enp1s0"
b = BPF(text=program)
fn = b.load_func("xdp_firewall", BPF.XDP)
print(f"正在 {device} 上启动防火墙,拦截 {BLOCK_IP}...")
try:
b.attach_xdp(device, fn, 0)
b.trace_print()
except Exception as e:
print(e)
finally:
b.remove_xdp(device, 0)
print("\n已卸载防火墙。")

image-20260328004611095

XDP 程序的返回值语义如下

  • XDP_PASS:允许通过

  • XDP_DROP:原地丢弃(防火墙核心)

  • XDP_TX:原路发回(可用于反射攻击防护)

  • XDP_REDIRECT:转发到其他网卡

在安全检测中的定位

上面的防火墙示例只是 eBPF 在安全领域的一个最小应用。把它作为检测引擎使用时,其价值与限制都比较清晰。

作为检测手段的优势

  • 观测点在系统调用与网络层,位于用户态组件之下。以进程创建、文件打开、网络连接等事件为数据源时,检测逻辑不依赖被监控程序自身的日志能力,程序即使不写日志也不影响采集。
  • 开销可控。程序在内核中直接对事件做过滤与聚合,只把需要的结果通过 Maps 传回用户态,避免了全量日志采集带来的开销,因此在生产主机上长时间常驻是可行的。
  • 策略生效即时。由于挂载点在内核事件上,规则更新后无需重启被监控进程,适合对容器与短生命周期进程做持续监控。

部署时需要注意的限制

  • 加载 eBPF 程序需要相应特权,因此承载检测程序的主机与账号本身属于高价值目标,应纳入最小权限与审计范围;在不使用的场景下保持 kernel.unprivileged_bpf_disabled 的收紧配置,避免非特权用户加载程序。
  • 程序能力受内核版本与验证器约束,跨内核版本的可移植性需要提前验证,升级内核前应将 eBPF 程序与内核的兼容性纳入变更清单。
  • 加载行为本身也应被监控:非预期的 eBPF 程序挂载、异常的 Maps 访问都可能意味着主机已被控制。检测工具与检测对象位于同一内核,意味着主机的完整性是这套方案成立的前提。

代表项目

https://ebpf.io/zh-hans/applications/

  1. 网络和负载均衡
    1. Cilium
    2. Calico
    3. Katran
  2. 系统可观测性与监控
    1. SkyWalking
    2. bcc
  3. 系统安全
    1. Falco
    2. tetragon
    3. Cloudflare
  4. 性能调优与性能剖析
    1. Parca / Pyroscope

References

Support via Solana

Solana

Solana

Solana Pay

Solana Pay

WeChat

WeChat