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

如何通过eBPF从tcp_probe追踪点获取TCP载荷?代码异常排查

问题原因及修复方案

核心问题

tp/tcp/tcp_probe 这个tracepoint默认不会捕获TCP数据包的载荷内容,即使data_len显示有载荷长度,__data指向的区域也没有实际的payload数据,导致你读出来的内容为空。

修复步骤

1. 配置tcp_probe捕获payload

内核默认的tcp_probe只记录TCP头部信息,需要手动配置让它携带载荷:

# 设置捕获的最大payload长度(比如256字节,和你的代码数组大小匹配)
echo 'probe:tcp_probe data=$data len=256' > /sys/kernel/debug/tracing/events/tcp/tcp_probe/trigger

也可以通过sysfs直接调整:

echo 256 > /sys/kernel/debug/tracing/events/tcp/tcp_probe/data_size

2. 修正代码读取逻辑

你的代码存在越界风险,需要调整读取长度为payloadSize和数组容量的最小值,避免BPF程序被内核拒绝加载:

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

struct data_t {
      unsigned pid;
      unsigned uid;
      unsigned short sport;
      unsigned short dport;
      int payloadSize;
      char payload[256];
};

SEC("tp/tcp/tcp_probe")
int trace_http2_headers(struct trace_event_raw_tcp_probe *ctx) {
   struct data_t data = {};
   data.pid = bpf_get_current_pid_tgid() >> 32;
   data.uid = bpf_get_current_uid_gid() >> 32;
   bpf_probe_read(&data.sport, sizeof(data.sport), &ctx->sport);
   bpf_probe_read(&data.dport, sizeof(data.dport), &ctx->dport);
   bpf_probe_read(&data.payloadSize, sizeof(data.payloadSize), &ctx->data_len);

   // 计算安全的读取长度,防止数组越界
   int copy_len = data.payloadSize > sizeof(data.payload) ? sizeof(data.payload) : data.payloadSize;
   if (copy_len > 0) {
       bpf_probe_read(&data.payload, copy_len, ctx->__data);
   }
    
   if (data.payloadSize == 0) return 0;
   bpf_printk("PAYLOAD: %.*s\n", data.payloadSize, data.payload);

   return 0;
}

char LICENSE[] SEC("license") = "Dual BSD/GPL"; 

3. 备选方案:换用其他tracepoint

如果tcp_probe的配置过于繁琐,可以改用tcp/tcp_sendmsg或tcp/tcp_recvmsg,这两个tracepoint可以直接获取用户态的缓冲区数据,不过需要用bpf_probe_read_user读取用户态内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:08:12