tc-dump 是一个基于 eBPF 的 tc 抓包工具,支持抓取 tc 的 ingress 和 egress 方向的包。

最近,tc-dump 支持了 pcap-filter,即支持了 pcap 的过滤语法。

与此同时,tc-dump 还支持跟踪 tc-bpf 程序;即如果 tc 上已挂载了 tc-bpf 程序,那么 tc-dump 会自动跟踪该 tc-bpf 程序。

所以,一个有趣的玩法:先在一个终端窗口跑 ./tc-dump -d XXX,然后在另一个终端窗口跑 ./tc-dump -d XXX,即可在后一个 tc-dump 中跟踪前一个 tc-dumptc-bpf 程序。

tc-dump 支持 pcap-filter

有位大佬开源了 pcap-filter 注入的库:elibpcaptc-dump 就是基于该库实现的。

tc-dump 中,pcap-filter 的使用方式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# ./tc-dump -h
Usage: ./tc-dump [options] [pcap-filter]
    Available pcap-filter: see "man 7 pcap-filter"
    Available options:
  -d, --device strings       network devices to run tc-dump
  -m, --filter-mark uint32   filter mark for tc-dump
  -k, --keep-tc-qdisc        keep tc-qdisc when exit
pflag: help requested
# ./tc-dump -d enp0s1 tcp port 8888
2023/11/26 10:54:14 Listening events for if@2:enp0s1 INGRESS by TC...
2023/11/26 10:54:14 Listening events for if@2:enp0s1 EGRESS by TC...
ifindex: 2(enp0s1) dir=INGRESS mark=0x0(0)
    ETH: 3e:22:fb:b9:64:64 -> de:97:0a:be:b0:2d, protocol IPv4
    IPv4: 192.168.64.1 -> 192.168.64.2, header length 20, dscp 0x10, total length 64, id 0x0000, TTL 64, protocol TCP
    TCP: 61307 -> 8888, seq 87516102, ack 0, flags SYN,ECE,CWR, win 65535
ifindex: 2(enp0s1) dir=EGRESS mark=0x0(0)
    ETH: de:97:0a:be:b0:2d -> 3e:22:fb:b9:64:64, protocol IPv4
    IPv4: 192.168.64.2 -> 192.168.64.1, header length 20, dscp 0x

elibpcap

elibpcap 是一个注入 pcap-filter 的库,它的使用方式如下:

1
2
3
4
5
6
7
    progSpec := specTc.Programs["on_ingress"]
    progSpec.Instructions, err = elibpcap.Inject(flags.PcapFilterExpr,
        progSpec.Instructions, elibpcap.Options{
            AtBpf2Bpf:  "filter_pcap_ebpf_l2",
            DirectRead: true,
            L2Skb:      true,
        })

不过,elibpcap 使用 libpcap.a 去编译 pcap-filter 表达式,所以在编译 tc-dump 前需要先编译 libpcap.a

1
2
3
4
5
6
# Get latest libpcap from https://www.tcpdump.org/
wget https://www.tcpdump.org/release/libpcap-1.10.4.tar.gz
cd libpcap-1.10.4
./configure --disable-rdma --disable-shared --disable-usb --disable-netmap --disable-bluetooth --disable-dbus --without-libnl
make
sudo make install

而后,elibpcap 会使用 github.com/cloudflare/cbpfc 去将 libpcap.a 编译得到的 cBPF 汇编转换成 eBPF 汇编。

最后,将得到的 eBPF 汇编注入到指定的 bpf2bpf 函数中。

tc-dump 支持跟踪 tc-bpf

tc-dump 支持跟踪 tc-bpf 的实现方式参考 eBPF Talk: 给 pwru 添砖加瓦 中的 Support tracing tc-bpf 小节。

pwru 不同的是,tc-dump 是根据网络设备去查找 tc-bpf 程序的,而不是 pwru 中直接跟踪所有 tc-bpf 程序。

小结

tc-dump 是一个基于 eBPF 的 tc 抓包工具,支持抓取 tc 的 ingress 和 egress 方向的包。

tc-dump 支持了 pcap-filter,即支持 pcap 的过滤语法;抛弃了复杂的选项,增加了灵活的包过滤语法。

tc-dump 支持跟踪 tc-bpf,即如果网络设备的 tc 上已挂载了 tc-bpf 程序,那么 tc-dump 会自动跟踪该 tc-bpf 程序。