bpf filter code 解释

memetao 于 2021-10-06 发布

背景

在linux下编写网络包过滤程序的时候,希望内核只投递指定规则的报文。

概要

主要是记录如何分析bpf filter的规则码。

tcpdump 生成bpf code

tcpdump -i lo ip and udp and dst port 65500 -d 

如下:

(000) ldh      [12]                             # 加载第12字节的word
(001) jeq      #0x800           jt 2	jf 10   # 判断是否是ipv4, 分别跳转到2 或 10
(002) ldb      [23]                             # 加载23字节
(003) jeq      #0x11            jt 4	jf 10   # 判断是否是udp(17), 分别跳转
(004) ldh      [20]                             # 加载第20字节的word
(005) jset     #0x1fff          jt 10	jf 6    # 分析是否出现了 frament(分包)
(006) ldxb     4*([14]&0xf)                     # 计算ip头部长度
(007) ldh      [x + 16]                         # 取ip后的第16字节(word), udp源端口
(008) jeq      #0xffdc          jt 9	jf 10   # 判断源端口是否是65500
(009) ret      #262144                          # match
(010) ret      #0                               # discard

通过 -dd 参数产生具体的struct sock_filter结构的数据:

tcpdump -i lo ip and udp and dst port 65500 -dd

注意点

创建raw socket的时候需要指定收包是从数据链路层开始,还是从ip开始。

使用上述的规则码的时候,必须是从数据链路层开始,即:

int fd = ::socket(PF_PACKET, SOCK_RAW , htons(ETH_P_IP));

如果

int fd = ::socket(PF_PACKET, SOCK_DGRAM , htons(ETH_P_IP));

那么就需要自行修改这个规则码,将所有的”地址” 减去 14(一般来说是以太网,以太网帧头部长14字节).

知道了上述规则后,就具备了修改code的能力。