三层架构设计
相关源文件
以下文件被用作生成此维基页面的上下文:
- CHANGELOG.md
- README.md
- builder/Dockerfile
- builder/init_env.sh
- functions.mk
- internal/config/base_config.go
- internal/domain/configuration.go
- internal/probe/base/base_probe.go
- internal/probe/gotls/gotls_probe.go
- internal/probe/openssl/config.go
- internal/probe/openssl/config_test.go
- kern/boringssl_masterkey.h
- kern/bpf/arm64/vmlinux.h
- kern/bpf/arm64/vmlinux_614.h
- kern/bpf/bpf_core_read.h
- kern/bpf/bpf_helper_defs.h
- kern/bpf/bpf_helpers.h
- kern/bpf/bpf_tracing.h
- kern/bpf/x86/vmlinux.h
- kern/bpf/x86/vmlinux_614.h
- kern/common.h
- kern/core_fixes.bpf.h
- kern/ecapture.h
- kern/openssl.h
- kern/openssl_masterkey.h
- kern/openssl_masterkey_3.0.h
- kern/tc.h
- main.go
- variables.mk
eCapture 采用关注点分离的设计理念,组织为三层架构。这种结构确保了内核层的高性能、用户态控制平面的健壮性与可扩展性,以及配置和数据消费界面的灵活性。
架构概览
下图展示了三层架构之间的关系,以及从内核挂钩到最终输出的数据流。
系统架构与数据流
Sources:
1. eBPF 内核层
内核层由编译成 eBPF 字节码的 C 程序组成。这些程序是 eCapture 的“眼睛”,运行在 Linux 内核上下文中,从源头拦截数据。
核心组件
- 探针 (Probes):附加到特定内核或用户态符号的程序。
- Uprobes:通过挂钩
SSL_read和SSL_write等函数,用于从 OpenSSL、GnuTLS 和 GoTLS 等库中捕获明文 [kern/openssl.h:163-190]。 - TC (流量控制):用于
pcap模式以捕获原始网络数据包 [kern/tc.h:136-150]。 - Kprobes:用于系统级审计,例如 Shell 命令执行。
- Uprobes:通过挂钩
- Maps:用于与用户态通信并存储临时状态的共享内存结构。
perf_event_array:用于向用户态高速传输事件流 [kern/openssl.h:79-92]。hash_maps:用于跟踪函数进入和退出之间的上下文(例如active_ssl_read_args_map)[kern/openssl.h:97-102]。percpu_array:用作“堆”以绕过 512 字节的栈限制 [kern/openssl.h:113-118]。
CO-RE 与 Non-CO-RE 加载
eCapture 支持两种加载机制,以确保跨不同内核版本的兼容性:
| 特性 | CO-RE (一次编译,到处运行) | Non-CO-RE (传统模式) |
|---|---|---|
| 要求 | 带有 BTF 的内核 (/sys/kernel/btf/vmlinux) | 特定版本的内核头文件 |
| 实现 | 使用 vmlinux.h 和 bpf_core_read [kern/ecapture.h:18-26] | 使用系统头文件和固定偏移量 [kern/ecapture.h:27-88] |
| 构建目标 | make (默认) | make nocore [variables.mk:241-250] |
Sources:
2. 用户态探针层
用户态探针层充当控制平面。它负责加载 eBPF 程序、管理其生命周期,并处理从内核接收的原始数据。
代码实体映射
下图将探针层的逻辑组件映射到 Go 代码库中的具体实现。
生命周期管理
BaseProbe 为所有模块提供模板方法模式。它处理:
- 配置校验:确保路径和过滤器正确。
- eBPF 加载:根据内核的 BTF 支持情况选择正确的
.o字节码。 - 附加 (Attachment):将 uprobes 链接到正确的库偏移量(例如,找到
libssl.so并挂钩SSL_write)。 - 事件分发:从
perf缓冲区读取并向EventProcessor发送原始字节。
Sources:
3. CLI 与 输出层
最顶层负责管理用户交互和数据格式化。它将 CLI 参数转换为探针配置,并将拦截的数据格式化以供消费。
组件
- Cobra CLI:位于
cli/cmd/,定义子命令(如tls、gotls、mysqld)并将参数解析为Configuration对象 [main.go:6-11]。 - 输出器 (Writers):位于
internal/output/,处理数据的去向,如StdoutWriter、FileWriter或eCaptureQWebSocket 推送器 [CHANGELOG.md:116-119]。 - 编码器 (Encoders):将内部事件结构转换为特定格式:
- Text:人类可读的控制台输出。
- JSON:用于集成的结构化数据。
- Pcapng:与 Wireshark 兼容的数据包捕获 [CHANGELOG.md:117-118]。
数据路径追踪
- 挂钩:目标进程中调用了
SSL_write。 - 内核:eBPF uprobe [kern/openssl.h:163] 被触发,通过
bpf_probe_read_user读取缓冲区,并将ssl_data_event_t[kern/openssl.h:28-39] 推送到tls_eventsmap。 - 用户态:
Probe模块的分发器从 perf 缓冲区读取事件。 - 处理器:
EventProcessor识别协议(如 HTTP/2)并将其与连接 UUID 关联。 - 输出:
Writer将格式化后的字符串(Text/JSON)发送到用户终端或文件。
Sources: