美文网首页
原始套接字与抓包过滤规则setsockopt(fd, SOL_S

原始套接字与抓包过滤规则setsockopt(fd, SOL_S

作者: 阿群1986 | 来源:发表于2019-10-28 17:01 被阅读0次

    英文资料:

    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);
        }
    

    相关文章

      网友评论

          本文标题:原始套接字与抓包过滤规则setsockopt(fd, SOL_S

          本文链接:https://www.haomeiwen.com/subject/kpbbvctx.html