eBPF 主机入侵检测:内核态进程与文件监控实战 核心要点图解,eBPF 可在内核态无侵入监控进程与文件行为,实现低开销 HIDS。;通过 tracepoint 和 kprobe 挂载 eBPF 程序,捕获 execve 和文件操作事件。;结合用户态守护进程分析事件流,可实时告警异常进程与敏感文件访问。;部署前需确认内核版本≥4.9 并开启 BPF 相关配置。
eBPF 主机入侵检测:内核态进程与文件监控实战 · 核心要点一图读懂(AegisX)

核心要点(TL;DR)

  • eBPF 可在内核态无侵入监控进程与文件行为,实现低开销 HIDS。
  • 通过 tracepoint 和 kprobe 挂载 eBPF 程序,捕获 execve 和文件操作事件。
  • 结合用户态守护进程分析事件流,可实时告警异常进程与敏感文件访问。
  • 部署前需确认内核版本≥4.9 并开启 BPF 相关配置。

为什么需要 eBPF 主机入侵检测?

传统 HIDS 依赖用户态轮询(如 ps、lsof)或审计日志(auditd),存在延迟高、资源消耗大、易被绕过等痛点。eBPF 允许在内核态安全地执行沙箱程序,实时捕获进程与文件系统事件,实现低开销、高精度的入侵检测。本文将手把手带你用 eBPF 构建一个轻量级监控原型,涵盖进程执行与敏感文件访问的捕获与分析。

环境准备与内核要求

首先确认系统支持 eBPF:

uname -r  # 建议 4.9 以上,推荐 5.4+
grep CONFIG_BPF /boot/config-$(uname -r)  # 应输出 CONFIG_BPF=y 和 CONFIG_BPF_SYSCALL=y

安装必要工具链(以 Ubuntu 为例):

sudo apt install -y clang llvm libelf-dev libbpf-dev linux-tools-common linux-tools-$(uname -r) bpftool

验证 bpftool 可用:

sudo bpftool feature probe

若输出包含 “eBPF syscall” 和 “BPF maps” 等支持信息,则环境就绪。

捕获进程执行事件

进程创建是入侵检测的关键点。我们通过 tracepoint 捕获 execve 系统调用,记录进程路径与参数。编写 eBPF 程序(C 语言):

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

struct event {
    u32 pid;
    char comm[16];
    char filename[256];
};

struct bpf_map_def SEC("maps") events SEC(".maps") = {
    .type = BPF_MAP_TYPE_RINGBUF,
    .max_entries = 256 * 1024,
};

SEC("tracepoint/syscalls/sys_enter_execve")
int handle_execve(void *ctx) {
    struct event *e;
    e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
    if (!e) return 0;
    e->pid = bpf_get_current_pid_tgid() >> 32;
    bpf_get_current_comm(&e->comm, sizeof(e->comm));
    bpf_probe_read_user_str(&e->filename, sizeof(e->filename), (void *)ctx + 8); // 参数偏移需根据架构调整
    bpf_ringbuf_submit(e, 0);
    return 0;
}

char LICENSE[] SEC("license") = "GPL";

用户态程序使用 libbpf 加载并读取 ring buffer,输出事件。编译命令:

clang -O2 -target bpf -c execve.bpf.c -o execve.bpf.o

加载后运行用户态程序,即可实时看到进程执行记录。

监控敏感文件访问

文件监控聚焦于 /etc、/bin、/usr/bin 等目录的写入与打开操作。通过 kprobe 挂载到 vfs_open 和 vfs_write:

SEC("kprobe/vfs_open")
int handle_vfs_open(struct pt_regs *ctx, struct path *path) {
    struct event *e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
    if (!e) return 0;
    e->pid = bpf_get_current_pid_tgid() >> 32;
    bpf_get_current_comm(&e->comm, sizeof(e->comm));
    // 读取 path->dentry->d_name.name 到 filename
    bpf_probe_read_kernel_str(&e->filename, sizeof(e->filename), path->dentry->d_name.name);
    bpf_ringbuf_submit(e, 0);
    return 0;
}

用户态程序过滤文件路径前缀(如 /etc/),仅对敏感操作告警。注意:vfs_open 触发频繁,需在 eBPF 程序中做初步过滤以减少事件量。

部署与检查清单

将 eBPF 程序编译为字节码,通过 systemd 服务常驻运行。部署前检查:

  • 内核版本 ≥ 4.9,且启用 BPF 相关配置;
  • 已安装 clang、llvm、libbpf 等工具;
  • 用户态程序具有 CAP_BPF 或 root 权限;
  • ring buffer 大小合理(建议 256KB~1MB);
  • 敏感文件路径列表已配置;
  • 日志输出到 syslog 或文件,并设置轮转。

运行后,使用 bpftool 查看已加载程序:

sudo bpftool prog list

检查事件流是否正常:

sudo ./hids-monitor -f /etc/

若输出进程与文件事件,则监控生效。

行动建议

eBPF 主机入侵检测具备低开销、实时性强的优势,适合作为传统 HIDS 的补充或替代。建议从监控进程执行和敏感文件写入开始,逐步扩展网络连接、权限提升等事件。生产环境可结合 AegisX 的 eBPF 安全能力,实现开箱即用的入侵检测与响应,减少自研维护成本。立即动手编写你的第一个 eBPF 监控程序,体验内核态安全的威力。

常见问题(FAQ)

eBPF 主机入侵检测需要什么内核版本?

建议使用 Linux 内核 4.9 及以上版本,并确保编译时开启 CONFIG_BPF、CONFIG_BPF_SYSCALL 等选项。生产环境推荐 5.x 以上内核以获得更完善的 eBPF 特性支持,如 BTF 和 CO-RE,便于程序移植。

eBPF 监控会影响系统性能吗?

eBPF 程序在内核态运行,经过 JIT 编译后性能开销极低,通常对系统吞吐影响小于 1%。但需注意避免在 eBPF 程序中执行复杂逻辑或频繁向用户态发送大量事件,否则可能增加 CPU 负载。合理设置采样和过滤规则可进一步降低开销。

如何捕获进程执行事件?

可通过挂载 eBPF 程序到 tracepoint:syscalls:sys_enter_execve 或 kprobe:__x64_sys_execve 来捕获进程执行事件。在 eBPF 程序中读取寄存器或参数字段获取可执行文件路径和参数,然后通过 perf event 或 ring buffer 发送到用户态分析。

eBPF 能监控文件打开和写入吗?

可以。通过 kprobe 挂载到 vfs_open、vfs_write 等内核函数,或使用 tracepoint:syscalls:sys_enter_openat 和 sys_enter_write,能够捕获文件路径、操作类型和进程信息。结合文件路径过滤,可重点监控敏感目录如 /etc、/bin 等。

如何将 eBPF 事件输出到用户态?

常用方式包括 perf event array 和 BPF ring buffer。perf event array 兼容性好,适合高吞吐场景;ring buffer 更高效且支持多消费者。用户态程序通过 libbpf 或 BCC 框架读取事件,进行聚合、告警和存储。