基于bpftrace抓取udp包的发送行为

背景

机器上面不清楚有什么程序一直对外发包,需要抓取到这个行为,是谁发起的

通过普通的netstat或者ss进行判断,然后进行抓取,这个方式无法满足发送又马上释放了的情况

抓取方法

编写一个脚本udp_count.bt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env bpftrace

BEGIN
{
printf("=== UDP统计开始,每分钟输出一次快照 ===\n");
}

kprobe:udp_sendmsg
{
$sk = (struct sock *)arg0;
$msg = (struct msghdr *)arg1;

/*
* sendto()/sendmsg()
* 优先从 msg_name 获取本次发送的真实目标地址
*/
if ($msg->msg_name != 0) {
$sa = (struct sockaddr *)$msg->msg_name;

/*
* AF_INET = 2
* 当前只统计 IPv4 UDP
*/
if ($sa->sa_family == 2) {
$sin = (struct sockaddr_in *)$msg->msg_name;

$daddr = ntop($sin->sin_addr.s_addr);
$dport = bswap($sin->sin_port);

@udp_count[comm, pid, $daddr, $dport] = count();
}
} else {
/*
* connect() 后的 UDP send()/sendmsg()
* 从 socket 获取目标地址
*/
$daddr_raw = $sk->__sk_common.skc_daddr;
$dport_raw = $sk->__sk_common.skc_dport;

if ($daddr_raw != 0 && $dport_raw != 0) {
$daddr = ntop($daddr_raw);
$dport = bswap($dport_raw);

@udp_count[comm, pid, $daddr, $dport] = count();
}
}
}

/*
* 每 60 秒输出一次
*/
interval:s:60
{
printf("\n=== UDP统计快照 (%s) ===\n",
strftime("%Y-%m-%d %H:%M:%S", nsecs));

print(@udp_count);

/*
* 清零,因此统计的是“最近一分钟”
*/
clear(@udp_count);
}

END
{
printf("\n=== 最终统计 ===\n");
print(@udp_count);
}

运行抓取

1
btftrace udp_count.bt

效果

1
2
=== UDP统计快照 (2026-08-19 10:32:57) ===
@udp_count[ping, 2678, 192.168.0.1, 33531]: 1

这样就可以摘取到发送的行为了,可以根据自己的需要对脚本进行调整


基于bpftrace抓取udp包的发送行为
https://zphj1987.com/2026/08/19/基于bpftrace抓取udp包的发送行为/
作者
zphj1987
发布于
2026年8月19日
许可协议