[ecapture]go1.20 tls fd抽取

[ecapture]go1.20 tls fd抽取 关键词ebpfecapture提交PR[merged]v1: https://github.com/gojue/ecapture/pull/956mastee(v2): https://github.com/gojue/ecapture/pull/947版本信息机器x86_64(字长为8)caddy2.7go程序依赖go1.20gogo1.20.12Go 1.20.12 结构体布局图 (x86_64 Linux)tls.Conn (crypto/tls/conn.go) ├─ conn net.Conn (interface, offset 0, size 16) ← 接口占16字节 │ ├─ type pointer (offset 0, 8 bytes) ← 指向类型信息 │ └─ data pointer (offset 8, 8 bytes) → *net.TCPConn ← 指向具体TCP连接 │ └─ net.TCPConn (net/tcpsock.go) │ └─ conn (embedded, offset 0, size 8) ← 嵌入的net.conn结构体 │ └─ fd *netFD (offset 0, 8 bytes) → *net.netFD │ └─ net.netFD (net/fd_unix.go) │ ├─ pfd poll.FD (offset 0, size 56) ✓ │ │ ├─ fdmu fdMutex (offset 0, size 16) ✓ │ │ │ ├─ state uint64 (offset 0, 8 bytes) │ │ │ ├─ rsema uint32 (offset 8, 4 bytes) │ │ │ └─ wsema uint32 (offset 12, 4 bytes) │ │ └─ Sysfd int (offset 16, 8 bytes) ← ✓ 文件描述符 │ ├─ family int (offset 56, 8 bytes) │ ├─ sotype int (offset 64, 8 bytes) │ ├─ isConnected bool (offset 72, 1字节) │ ├─ net string (offset 80, 16字节) ← string: ptr(8) len(8) │ ├─ laddr Addr (offset 96, 16字节) ← interface: type(8) data(8) │ └─ raddr Addr (offset 112, 16字节) ← interface: type(8) data(8)相关资料x86_64上go运行时 一个接口变量interface在内存中占用两个机器字wordGo 的内存对齐8 字节对齐结构体内存对齐规则成员对齐每个结构体成员的起始存放地址必须是“其自身对齐要求”的整数倍结构体整体对齐结构体整体的大小必须是其所有成员中最大对齐要求的整数倍成员顺序影响大小成员在结构体中的定义顺序会直接影响填充字节的多少从而导致结构体总大小的差异gotls hook位置确认需要hook caddy二进制文件的tls实现caddy默认使用标准crypto/tlscrypto/tls.(*Conn).writeRecordLocked crypto/tls.(*Conn).Read数据来源go tool nm caddy | grep -F (*Conn).Read go tool nm caddy | grep -E writeRecordLocked在ecapture中确认到hook位置与实际1.20.12相同相关资料二进制文件是自包含的caddy使用的go是自包含的不会用到机器上的gocaddy默认使用标准crypto/tlshttp3通过配置启动使用qtlshook 位置不同Caddy 多线程eBPF捕获gotls_events实现流程图数据流时序图代码实现详见https://github.com/skylar2826/ecapture-fork/tree/feature/gotls2主要代码https://github.com/skylar2826/ecapture-fork/blob/feature/gotls2/kern/gotls_kern.c运行结果推测http2复用导致日志乱序使得write比read先打印期望时序read - write - read - write相关资料kprobe与kretprobe、uprobe与uretprobeConnect Events获取Connect Events获取