Skip to content

开发指南

本文档为向 eCapture 项目贡献代码的开发者提供全面指导。内容涵盖构建系统、开发工作流、测试流程和发布过程。有关实现新捕获模块的信息,请参阅 添加新模块。有关 eBPF 程序开发的详细信息,请参阅 eBPF 程序开发


开发环境设置

前置条件

eCapture 开发需要以下工具和库:

组件最低版本用途
Go1.24用户空间程序编译
Clang9+ (推荐 14)eBPF 程序编译
LLVM9+ (推荐 14)eBPF 字节码生成
Linux Kernel4.18+eBPF 支持
libelf-dev-ELF 文件解析
Linux headers-内核结构定义

环境初始化脚本

项目在 builder/init_env.sh:1-106 提供了自动化环境设置脚本。该脚本执行以下操作:

  1. 检测 Ubuntu 版本并选择适当的 Clang 版本 (builder/init_env.sh:16-39)
  2. 通过 apt-get 安装所需的软件包 (builder/init_env.sh:72-74)
  3. 配置交叉编译工具链 (builder/init_env.sh:43-61)
  4. 为 eBPF 编译准备 Linux 内核源码 (builder/init_env.sh:81-89)
  5. 下载并安装 Go (builder/init_env.sh:94-97)

架构检测: 脚本会自动检测主机架构并配置交叉编译:

手动执行:

bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/gojue/ecapture/master/builder/init_env.sh)"

来源:builder/init_env.sh:1-106


构建系统架构

Makefile 结构

构建系统由三个主要文件组成:

构建系统组件:

来源:Makefile:1-11functions.mk:1-76builder/Makefile.release:1-10

构建目标概览

目标用途包含的字节码
all完整构建(CO-RE 和 non-CO-RE)两者都包含
nocore仅构建 non-CO-RE仅 non-CO-RE
ebpf编译 CO-RE eBPF 字节码CO-RE
ebpf_noncore编译 non-CO-RE eBPF 字节码non-CO-RE
assets生成 Go 嵌入式字节码两者都包含
build编译 Go 二进制文件-
clean删除构建产物-
test-race运行带竞态检测器的单元测试-
e2e运行端到端测试-

来源:Makefile:4-14Makefile:106-245


构建流程

完整构建流水线

来源:Makefile:6-11Makefile:133-201

CO-RE 与 Non-CO-RE 编译

CO-RE(一次编译,到处运行):

bash
clang -D__TARGET_ARCH_x86 \
  -target bpfel \
  -c kern/openssl.c \
  -o user/bytecode/openssl_kern_core.o \
  -g -fno-ident
  • 生成与内核无关的字节码 (Makefile:122-127)
  • 需要支持 BTF(BPF 类型格式)的内核
  • 使用 bpftool btf dump 生成的 vmlinux.h (Makefile:130-131)
  • 文件大小更小,可跨内核版本移植

Non-CO-RE(特定内核):

bash
clang -I /usr/src/linux-source/arch/x86/include \
  -c kern/openssl.c -o - | \
llc -march=bpf -filetype=obj \
  -o user/bytecode/openssl_kern_noncore.o
  • 需要目标内核的内核头文件 (Makefile:144-159)
  • 可在不支持 BTF 的旧内核上工作
  • 针对特定内核,不同内核版本需要重新构建
  • 由于包含内核结构定义,文件大小更大

构建变量:

来源:Makefile:117-159

资源嵌入流程

构建系统使用 go-bindata 将所有 eBPF 字节码文件嵌入到 Go 二进制文件中:

  1. 编译 eBPF 程序:在 user/bytecode/ 中生成 *.o 文件
  2. 生成 Go 代码go-bindata 读取所有 .o 文件 (Makefile:164)
  3. 创建资源包:生成 assets/ebpf_probe.go (Makefile:164)
  4. 嵌入到二进制文件:Go 构建包含嵌入的资源

这种方法消除了在二进制文件旁分发单独字节码文件的需要。

来源:Makefile:162-171


构建 eCapture

标准构建(本地架构)

完整构建,包含 CO-RE 和 non-CO-RE:

bash
make clean
make env          # 显示构建环境
make all          # 构建所有内容

仅 non-CO-RE(用于旧内核):

bash
make clean
make nocore

nocore 目标适用于以下情况:

  • 目标系统缺少 BTF 支持
  • 部署到特定内核版本
  • 通过排除 CO-RE 字节码来减少二进制大小

来源:Makefile:4-14

交叉编译

在 x86_64 上为 ARM64 构建:

bash
make clean
CROSS_ARCH=arm64 make env
CROSS_ARCH=arm64 make all

在 ARM64 上为 x86_64 构建:

bash
make clean
CROSS_ARCH=amd64 make env
CROSS_ARCH=amd64 make all

交叉编译要求:

libpcap 交叉编译: 构建系统自动为交叉编译配置 libpcap:

bash
CC=aarch64-linux-gnu-gcc AR=aarch64-linux-gnu-ar \
  ./configure --host=aarch64-linux-gnu

来源:Makefile:56-65Makefile:176-184.github/workflows/go-c-cpp.yml:56-65

Android 构建

为 Android 构建(ARM64):

bash
make clean
CROSS_ARCH=arm64 make env
ANDROID=1 CROSS_ARCH=arm64 make nocore

Android 特定注意事项:

来源:Makefile:95.github/workflows/go-c-cpp.yml:61-65

构建环境变量

变量说明示例
CROSS_ARCH目标架构arm64amd64
ANDROIDAndroid 构建标志1(启用)
DEBUG调试构建标志1(启用调试符号)
SNAPSHOT_VERSION覆盖版本字符串v0.8.0

环境显示:

bash
make env

此命令显示所有构建变量,包括:

  • 主机架构检测
  • 内核版本
  • 编译器版本
  • 目标架构设置
  • 版本信息

来源:Makefile:19-63


测试

单元测试

运行单元测试:

bash
go test -v ./...

使用竞态检测器运行:

bash
make test-race

竞态检测器构建 (Makefile:216-224):

  • 启用 CGO_ENABLED=1 以实现 C 集成
  • 与 libpcap 静态链接
  • 使用竞态检测器识别数据竞争

来源:Makefile:216-224

端到端测试

项目为每个主要模块提供 E2E 测试脚本:

运行特定 E2E 测试:

bash
make e2e-tls       # 测试 TLS/SSL 捕获
make e2e-gnutls    # 测试 GnuTLS 捕获
make e2e-gotls     # 测试 Go TLS 捕获

运行所有 E2E 测试:

bash
make e2e

来源:Makefile:226-244


CI/CD 流水线

GitHub Actions 工作流架构

来源:.github/workflows/go-c-cpp.yml:1-128.github/workflows/release.yml:1-129

CI 构建矩阵

CI 系统构建并测试多种配置:

架构本地构建交叉编译Android
x86_64✓ CO-RE + non-CO-RE✓ arm64 目标✓ arm64
arm64✓ CO-RE + non-CO-RE✓ amd64 目标✓ amd64

CI 构建步骤:

  1. 设置环境 (.github/workflows/go-c-cpp.yml:16-33):

    • 安装 Go 1.24.6
    • 安装 Clang 14、LLVM 工具
    • 提取并准备 Linux 内核源码
  2. 本地 CO-RE 构建 (.github/workflows/go-c-cpp.yml:38-44):

    bash
    make clean
    make env
    DEBUG=1 make -j8
  3. 代码质量检查 (.github/workflows/go-c-cpp.yml:45-50):

    • 对 Go 代码运行 golangci-lint
    • 版本:v2.1
  4. Non-CO-RE 构建 (.github/workflows/go-c-cpp.yml:51-55):

    bash
    make clean
    make nocore
  5. 交叉编译 (.github/workflows/go-c-cpp.yml:56-65):

    bash
    CROSS_ARCH=arm64 make env
    CROSS_ARCH=arm64 make -j8
    ANDROID=1 CROSS_ARCH=arm64 make nocore -j8
  6. 测试执行 (.github/workflows/go-c-cpp.yml:66-67):

    bash
    go test -v -race ./...

来源:.github/workflows/go-c-cpp.yml:9-127

编译器版本管理

CI 系统确保一致的编译器版本:

Clang/LLVM 设置:

bash
for tool in "clang" "llc" "llvm-strip"
do
  sudo rm -f /usr/bin/$tool
  sudo ln -s /usr/bin/$tool-14 /usr/bin/$tool
done

这会创建符号链接以强制使用 Clang 14 (.github/workflows/go-c-cpp.yml:20-24)。

内核源码准备:

bash
cd /usr/src
source_file=$(find . -maxdepth 1 -name "*linux-source*.tar.bz2")
sudo tar -xf $source_file
cd $source_dir
sudo make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- prepare V=0

为交叉编译准备内核头文件 (.github/workflows/go-c-cpp.yml:25-32)。

来源:.github/workflows/go-c-cpp.yml:16-33


发布流程

发布工作流

来源:.github/workflows/release.yml:1-129builder/Makefile.release:1-151

发布目标

创建快照(开发构建):

bash
make -f builder/Makefile.release snapshot

创建发布(特定版本):

bash
SNAPSHOT_VERSION=v0.8.0 make -f builder/Makefile.release release

发布到 GitHub:

bash
SNAPSHOT_VERSION=v0.8.0 make -f builder/Makefile.release publish

release 目标编排 (builder/Makefile.release:10):

  1. snapshot:构建 Linux 产物
  2. build_deb:创建 DEB 包
  3. snapshot_android:构建 Android 产物

来源:builder/Makefile.release:10-151

打包格式

TAR.GZ 归档文件

归档内容:

  • ecapture 二进制文件
  • LICENSE
  • CHANGELOG.md
  • README.mdREADME_CN.md

命名约定:

ecapture-{VERSION}-{OS}-{ARCH}[-nocore].tar.gz

示例:

  • ecapture-v0.8.0-linux-amd64.tar.gz(CO-RE + non-CO-RE)
  • ecapture-v0.8.0-android-arm64-nocore.tar.gz(仅 non-CO-RE)

归档创建 (builder/Makefile.release:62-76):

bash
$(CMD_MKDIR) -p $(TAR_DIR)
$(CMD_CP) LICENSE $(TAR_DIR)/LICENSE
$(CMD_CP) bin/ecapture $(TAR_DIR)/ecapture
$(CMD_TAR) -czf $(OUT_ARCHIVE) $(TAR_DIR)

来源:builder/Makefile.release:62-76functions.mk:62-76

DEB 包

包结构:

ecapture-v0.8.0-amd64.deb
├── DEBIAN/
│   └── control
└── usr/
    └── local/
        └── bin/
            └── ecapture

控制文件字段 (builder/Makefile.release:143-149):

  • Package: ecapture
  • Version: 从 git 标签提取
  • Architecture: amd64 或 arm64
  • Maintainer: CFC4N cfc4ncs@gmail.com
  • Description: capture SSL/TLS text content without CA cert by eBPF

构建过程:

bash
make -f builder/Makefile.release deb

使用 dpkg-deb --build 创建 DEB 包 (builder/Makefile.release:151)。

来源:builder/Makefile.release:132-151

Docker 镜像

多架构构建:

bash
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --build-arg VERSION=v0.8.0 \
  -t ecapture:v0.8.0 \
  -t ecapture:latest \
  --push .

Dockerfile 阶段 (builder/Dockerfile:1-39):

  1. 构建器阶段:Ubuntu 22.04 基础镜像

    • 安装编译器(Clang 14、Go 1.24.6)
    • 使用 make all 构建 eCapture
  2. 运行时阶段:Alpine Linux

    • 仅复制 ecapture 二进制文件
    • 设置 ENTRYPOINT 为 /ecapture

镜像标签:

  • {username}/ecapture:v{VERSION}(特定版本)
  • {username}/ecapture:latest(最新发布)

来源:.github/workflows/release.yml:101-129builder/Dockerfile:1-39

发布说明生成

发布工作流自动生成发布说明:

  1. 获取前一个标签 (.github/workflows/release.yml:63-67):

    bash
    PREVIOUS=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
  2. 通过 GitHub API 生成说明 (.github/workflows/release.yml:68-80):

    bash
    gh api --method POST \
      /repos/$REPO/releases/generate-notes \
      -f tag_name=$TAG \
      -f previous_tag_name=$PREVIOUS_TAG
  3. 创建发布 (builder/Makefile.release:124):

    bash
    gh release create $(VERSION) $$FILES \
      --title "eCapture $(VERSION)" \
      --notes-file $(RELEASE_NOTES)

来源:.github/workflows/release.yml:63-87builder/Makefile.release:114-124


开发工作流总结

典型开发周期

  1. 设置环境:

    bash
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/gojue/ecapture/master/builder/init_env.sh)"
  2. 克隆并构建:

    bash
    git clone https://github.com/gojue/ecapture.git
    cd ecapture
    make env          # 验证环境
    make all          # 构建所有内容
  3. 进行修改:

    • kern/ 中修改 eBPF 程序
    • cli/user/ 或其他包中修改 Go 代码
  4. 测试:

    bash
    make clean
    make all
    go test -v ./...
    make e2e          # 如果测试模块
  5. 格式化代码:

    bash
    make format       # 使用 clang-format 格式化 C 代码
  6. 提交并推送:

    bash
    git add .
    git commit -m "Your change description"
    git push origin your-branch
  7. 创建 Pull Request:

    • CI 自动在 x86_64 和 arm64 上运行
    • 测试本地和交叉编译构建
    • 使用 golangci-lint 检查代码质量

关键构建命令参考

命令用途使用场景
make env显示构建环境验证配置
make all完整构建(CO-RE + non-CO-RE)开发
make nocore仅 non-CO-RE 构建旧内核
make clean删除构建产物清理重建
make test-race使用竞态检测器运行测试查找并发问题
make e2e运行 E2E 测试集成测试
make format格式化 C 代码代码风格
CROSS_ARCH=arm64 make为 ARM64 交叉编译ARM 目标
ANDROID=1 make nocore为 Android 构建移动部署

来源:Makefile:1-245builder/Makefile.release:1-151

开发指南 has loaded