Skip to content

TLS 捕获架构 ​

相关源文件

以下文件被用作生成此维基页面的上下文:

目的与范围 ​

本文档详细介绍了 eCapture 核心 TLS 捕获子系统(tls、gotls 和 gnutls)的内部架构。它解释了 eBPF 程序如何附加到用户态库和运行时,如何在不同版本的 OpenSSL、BoringSSL、Go 和 GnuTLS 之间解析库和符号,内核 C 结构体与用户态 Go 解码器之间的二进制 ABI 契约,以及管理文本、密钥日志和 pcapng 捕获模式的执行流。

Sources: AGENTS.md:74-94, docs/agent/architecture.md:37-49


eBPF 附加与探针生命周期 ​

TLS 捕获引擎依赖 github.com/gojue/ebpfmanager 来管理加载到内核中的 eBPF 程序的生命周期。探针利用 uprobe 和 uretprobe 附加点来拦截目标共享库或编译后的二进制文件中的函数入口和出口。对于 pcapng 和数据包过滤模式,还会附加流量控制(TC)的出口/入口钩子。

图 1:从 CLI 入口到 eBPF 管理器设置的初始化流程。

Sources: AGENTS.md:74-94, internal/probe/gnutls/gnutls_probe.go:57-117

核心探针生命周期遵循严格的初始化和附加序列:

  1. 配置校验:对探针配置进行幂等校验 docs/agent/architecture.md:99-102。
  2. 字节码选择:BaseProbe.SelectBytecode 根据内核 BTF 可用性选择合适的 CO-RE 或非 CO-RE 对象文件 docs/agent/probe-development.md:105-109。
  3. 管理器初始化:manager.Manager 使用嵌入的二进制资产初始化映射(maps)和程序 internal/probe/gnutls/gnutls_probe.go:95-100。
  4. 附加:bpfManager.Start() 将 uprobes 附加到目标符号(例如 SSL_write、SSL_read、gocryptotls_*、gnutls_record_send) internal/probe/gnutls/gnutls_probe.go:101-103, internal/probe/gnutls/gnutls_probe.go:210-212。
  5. 事件循环:Perf 或 ring-buffer 事件读取器将二进制结构从内核映射流式传输到用户态处理器 AGENTS.md:76-88, internal/probe/gnutls/gnutls_probe.go:108-114。

Sources: AGENTS.md:74-94, docs/agent/architecture.md:125-144, internal/probe/gnutls/gnutls_probe.go:57-117


库与符号解析 ​

每个 TLS 模块针对不同的运行时环境,具有不同的符号和数据结构布局:

OpenSSL 与 BoringSSL (tls) ​

Go 原生 TLS (gotls) ​

  • 通过挂载内部 crypto/tls 函数(conn.Read、conn.Write)或标准库 TCP/netFD 绑定来针对 Go 二进制文件 docs/agent/architecture.md:42。
  • 动态解析 Go 的调用约定,通过 kern/go_argument.h 中的辅助宏支持基于栈的 ABI(Go < 1.17)和基于寄存器的 ABI(Go >= 1.17) kern/go_argument.h:18-128。
  • 直接从 Go 的内部 net.netFD 和 net.TCPAddr 运行时结构中提取文件描述符和 IP 元组(src_ip、dst_ip、端口) kern/gotls_kern.c:110-187。

GnuTLS (gnutls) ​

Sources: docs/agent/architecture.md:39-49, kern/go_argument.h:18-128, kern/openssl_masterkey.h:19-40, kern/openssl_masterkey_3.0.h:22-25, kern/openssl_masterkey_3.2.h:26-29


C/Go 事件 ABI 与二进制序列化 ​

内核 eBPF 程序与用户态 Go 代码之间交换的数据构成了严格的二进制 ABI。对字段宽度、符号或填充的任何改动都会破坏解码。

图 2:从内核 C 结构体到用户态 Go 解码器的二进制事件 ABI 流水线。

Sources: AGENTS.md:98-115, kern/gotls_kern.c:33-50, internal/probe/gotls/event.go:34-145

示例:GoTLS 事件 ABI 映射 ​

内核结构体 struct go_tls_event kern/gotls_kern.c:33-50 被直接映射到 Go 中的 GoTLSDataEvent internal/probe/gotls/event.go:34-74。字段使用 binary.Read 按照显式的小端字节序顺序反序列化 internal/probe/gotls/event.go:77-127:

C 字段名称C 类型Go 字段名称Go 类型偏移量 / 大小
ts_nsu64Timestampuint640 / 8 字节 kern/gotls_kern.c:34, internal/probe/gotls/event.go:38
pidu32Piduint328 / 4 字节 kern/gotls_kern.c:35, internal/probe/gotls/event.go:39
tidu32Tiduint3212 / 4 字节 kern/gotls_kern.c:36, internal/probe/gotls/event.go:40
data_lens32DataLenint3216 / 4 字节 kern/gotls_kern.c:37, internal/probe/gotls/event.go:41
event_typeu8EventTypeuint820 / 1 字节 kern/gotls_kern.c:38, internal/probe/gotls/event.go:42
padu8[3]pad[3]byte21 / 3 字节 kern/gotls_kern.c:39, internal/probe/gotls/event.go:43
fdu32Fduint3224 / 4 字节 kern/gotls_kern.c:40, internal/probe/gotls/event.go:44
src_ipu8[16]SrcIP[16]byte28 / 16 字节 kern/gotls_kern.c:41, internal/probe/gotls/event.go:45
datachar[]Data[]byte84 / 可变 kern/gotls_kern.c:49, internal/probe/gotls/event.go:53

Sources: AGENTS.md:98-115, kern/gotls_kern.c:33-50, internal/probe/gotls/event.go:34-145


共享与模块特定的执行流 ​

所有三个核心 TLS 模块(tls、gotls 和 gnutls)在事件到达用户态后共享通用的执行流水线:

  1. 读取器与解码器:Perf 缓冲读取器对传入的原始字节切片调用 DecodeFromBytes,针对恶意或格式错误的输入验证长度和边界 internal/probe/gotls/event.go:77-145。
  2. 同步分发器:解码后的事件被传递给 events.Dispatcher,该分发器同步且无序地扇出到所有已注册的输出处理器 docs/agent/architecture.md:20-24, docs/agent/probe-development.md:125-128。
  3. 捕获模式处理器:

Sources: AGENTS.md:74-94, docs/agent/architecture.md:20-24, docs/agent/probe-development.md:125-128, kern/openssl.h:23-39, kern/openssl_masterkey.h:35-105, internal/probe/gnutls/gnutls_probe.go:180-186

TLS 捕获架构 has loaded
下载