原始套接字与抓包过滤规则setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, ...)

英文资料:

struct sock_filter filter[] = {
    { 0x28,  0,  0, 0x0000000c },
    { 0x15,  0,  8, 0x00000800 },
    { 0x30,  0,  0, 0x00000017 },
    { 0x15,  0,  6, 0x00000011 },
    { 0x80,  0,  0, 0000000000 },
    { 0x35,  0,  4, 0x00000064 },
    { 0x30,  0,  0, 0x00000050 },
    { 0x15,  1,  0, 0x00000061 },
    { 0x15,  0,  1, 0x00000062 },
    { 0x06,  0,  0, 0xffffffff },
    { 0x06,  0,  0, 0000000000 },
};
size_t N = sizeof(filter) / sizeof(filter[0]);
struct sock_fprog filter_prog = {N, &filter};

int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, sizeof(struct sock_fprog));


/* The setsockopt(2) call to SO_DETACH_FILTER doesn't need any arguments
and SO_LOCK_FILTER for preventing the filter to be detached, takes an
integer value with 0 or 1. */
setsockopt(sockfd, SOL_SOCKET, SO_DETACH_FILTER, NULL, 0);

int value=1;
setsockopt(sockfd, SOL_SOCKET, SO_LOCK_FILTER, &value, sizeof(value));
/* the filter below checks for all of the following conditions that
* are based on the contents of create_payload()
*  ether type 0x800 and
*  ip proto udp     and
*  skb->len == DATA_LEN and
*  udp[38] == 'a' or udp[38] == 'b'
* It can be generated from the following bpf_asm input:
*   ldh [12]
*   jne #0x800, drop    ; ETH_P_IP
*   ldb [23]
*   jneq #17, drop      ; IPPROTO_UDP
*   ld len          ; ld skb->len
*   jlt #100, drop      ; DATA_LEN
*   ldb [80]
*   jeq #97, pass       ; DATA_CHAR
*   jne #98, drop       ; DATA_CHAR_1
*   pass:
*     ret #-1
*   drop:
*     ret #0
*
*

* 中文说明:
安装内核Linux内核源码包+开发工具
sudo apt-get install \
    linux-source-5.0.0 \
    kernel-package \
    libelf-dev \
    binutils-dev \
    libreadline-dev

解压内核源码包进入源码树顶层目录
tar xjvf /usr/src/linux-source-5.0.0.tar.bz2
cd linux-5.0.0

拷贝内核config配置文件
cp /boot/config-`uname -r` .config

编译tools子目录下的bpf_asm工具
make headers_install && make -C tools/bpf/
sudo cp tools/bpf/bpf_asm /usr/local/bin/

运行bpf_asm工具, 转换BPF包过滤脚本为C语言结构体:

cat << EOF | /usr/local/bin/bpf_asm -c -i - | tee myfilter.c
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 脚本功能, 检查数据包是否同时满足下列几条过滤条件
;     ether type 0x800 and
;     ip proto udp     and
;     skb->len >= 100  and
;     udp[38] == 'a' or udp[38] == 'b'
; -----------------------------------
ldh [12]
jne #0x800, drop ; ETH_P_IP
ldb [23]
jneq #17, drop   ; IPPROTO_UDP
ld len           ; ld skb->len
jlt #100, drop   ; 这里DATA_LEN等于int常量#100
ldb [80]
jeq #97, pass    ; DATA_CHAR
jne #98, drop    ; DATA_CHAR_1
pass:
ret #-1
drop:
ret #0
EOF

输出文件myfilter.c内容如下

{ 0x28,  0,  0, 0x0000000c },
{ 0x15,  0,  8, 0x00000800 },
{ 0x30,  0,  0, 0x00000017 },
{ 0x15,  0,  6, 0x00000011 },
{ 0x80,  0,  0, 0000000000 },
{ 0x35,  0,  4, 0x00000064 },
{ 0x30,  0,  0, 0x00000050 },
{ 0x15,  1,  0, 0x00000061 },
{ 0x15,  0,  1, 0x00000062 },
{ 0x06,  0,  0, 0xffffffff },
{ 0x06,  0,  0, 0000000000 },

*
* 中文说明:
* BPF过滤规则还可以通过tcpdump命令生成相似的结果, (输出BPF汇编代码用-d, 输出C结构体用-dd)
*     tcpdump -s 65535   "ip and (udp[38]=0x61 or udp[38]=0x62)" -d
* 或
*     tcpdump -s 65535   "ip and udp" -dd
*/
    struct sock_filter bpf_filter[] = {
    { 0x28,  0,  0, 0x0000000c },
    { 0x15,  0,  8, 0x00000800 },
    { 0x30,  0,  0, 0x00000017 },
    { 0x15,  0,  6, 0x00000011 },
    { 0x80,  0,  0, 0000000000 },
    { 0x35,  0,  4, 0x00000064 },
    { 0x30,  0,  0, 0x00000050 },
    { 0x15,  1,  0, 0x00000061 },
    { 0x15,  0,  1, 0x00000062 },
    { 0x06,  0,  0, 0xffffffff },
    { 0x06,  0,  0, 0000000000 },
};
    struct sock_fprog bpf_prog;

    bpf_prog.filter = bpf_filter;
    bpf_prog.len = sizeof(bpf_filter) / sizeof(struct sock_filter);

    if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf_prog,
                   sizeof(bpf_prog))) {
        perror("setsockopt SO_ATTACH_FILTER");
        exit(1);
    }
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值