You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Cilium ebpf-go实现网络接口创建追踪的技术求助

实现监控网络接口创建的eBPF方案

一、内核挂载点选择

  • 优先选rtnl_create_link:这个函数是内核处理网络接口创建的核心入口(通过netlink调用),挂载它能精准捕获完整的接口创建事件,比dev_alloc_name更合适——后者仅负责分配接口名称,不对应完整的接口创建流程。
  • 内核版本≥5.5时推荐用fentry替代kprobe:fentry是内核提供的稳定追踪入口,无需处理函数参数偏移问题,可靠性比kprobe更高。

二、ebpf-go核心流程拆解

不用纠结示例的复杂细节,核心分三步:

  1. 编写eBPF字节码(C语言)
    定义perf buffer实现内核态到用户态的信息传递,在追踪程序中提取接口关键信息并发送到buffer:

    #include <vmlinux.h>
    #include <bpf/bpf_helpers.h>
    #include <bpf/bpf_tracing.h>
    
    struct event {
        char name[IFNAMSIZ];
        int ifindex;
    };
    
    struct {
        __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
        __uint(key_size, sizeof(u32));
        __uint(value_size, sizeof(u32));
    } events SEC(".maps");
    
    SEC("fentry/rtnl_create_link")
    int BPF_PROG(trace_link_create, struct net *net, struct net_device *dev,
                 struct rtnl_link_info *info, struct netlink_ext_ack *extack)
    {
        struct event e = {};
        bpf_probe_read_str(e.name, sizeof(e.name), dev->name);
        e.ifindex = dev->ifindex;
        bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &e, sizeof(e));
        return 0;
    }
    
    char _license[] SEC("license") = "GPL";
    
  2. Go用户态程序
    加载eBPF程序与maps,创建perf buffer读取器,循环读取并打印事件:

    package main
    
    import (
        "fmt"
        "os"
        "os/signal"
        "syscall"
    
        "github.com/cilium/ebpf/link"
        "github.com/cilium/ebpf/perf"
        "github.com/cilium/ebpf/rlimit"
    )
    
    // 与eBPF中的event结构体对应
    type event struct {
        Name    [16]byte
        Ifindex int32
    }
    
    func main() {
        // 移除内存限制,允许加载eBPF程序
        if err := rlimit.RemoveMemlock(); err != nil {
            fmt.Fprintf(os.Stderr, "移除内存锁失败: %v\n", err)
            os.Exit(1)
        }
    
        // 加载编译后的eBPF对象
        objs := struct {
            TraceLinkCreate link.Link `ebpf:"trace_link_create"`
            Events          *perf.Map `ebpf:"events"`
        }{}
        if err := loadObjs(&objs, nil); err != nil {
            fmt.Fprintf(os.Stderr, "加载eBPF对象失败: %v\n", err)
            os.Exit(1)
        }
        defer objs.TraceLinkCreate.Close()
        defer objs.Events.Close()
    
        // 创建perf事件读取器
        reader, err := perf.NewReader(objs.Events, os.Getpagesize())
        if err != nil {
            fmt.Fprintf(os.Stderr, "创建perf reader失败: %v\n", err)
            os.Exit(1)
        }
        defer reader.Close()
    
        // 监听退出信号,实现优雅退出
        sig := make(chan os.Signal, 1)
        signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
        go func() {
            <-sig
            fmt.Println("\n正在退出...")
            reader.Close()
        }()
    
        fmt.Println("等待网络接口创建事件...")
        for {
            record, err := reader.Read()
            if err != nil {
                if perf.IsClosed(err) {
                    break
                }
                fmt.Fprintf(os.Stderr, "读取perf事件失败: %v\n", err)
                continue
            }
    
            var e event
            if err := record.Read(&e); err != nil {
                fmt.Fprintf(os.Stderr, "解析事件失败: %v\n", err)
                continue
            }
    
            // 转换为字符串并打印结果
            name := string(e.Name[:])
            fmt.Printf("新网络接口创建: 索引=%d, 名称=%s\n", e.Ifindex, name)
        }
    }
    
  3. 编译与运行

    • 用bpf2go工具将C代码编译为Go可加载的对象,需在代码中添加generate指令:
      //go:generate go run github.com/cilium/ebpf/cmd/bpf2go bpf trace_link.c -- -I/path/to/vmlinux-headers
      
      执行编译:
      go generate
      
    • 以root权限运行Go程序:
      sudo go run main.go
      

三、关键注意事项

  • 内核版本兼容:fentry需要内核≥5.5,若内核版本较低,改用kprobe(需通过bpftool btf dump file /sys/kernel/btf/vmlinux format c获取内核结构体定义,处理函数参数偏移)。
  • 权限要求:必须以root权限运行程序,eBPF程序需要内核态操作权限。
  • 读取优化:若bpf_probe_read_str读取失败,可尝试bpf_core_read_str(需内核≥5.8,依赖BTF)。

内容的提问来源于stack exchange,提问作者Vincenzo Cosi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 15:52:45