1.简介
Libpcap是Packet Capture Libray的英文缩写,即数据包捕获函数库。该库提供的C函数接口用于捕捉经过指定网络接口的数据包,该接口应该是被设为混杂模式。这个在原始套接字中有提到。
2.功能
Libpcap主要有如下功能:
(1)数据包捕获
捕获流经本网卡的所有原始数据包,甚至对交换设备中的数据包也能够进行捕获,本功能是嗅探器的基础。
(2)自定义数据包发送
构造任意格式的原始数据包,并发送到目标网络,本功能是新协议验证、甚至攻击验证的基础。
(3)流量采集与统计
对所采集到的网络中的流量信息进行按照新规则分类,按指标进行统计,并输出到指定终端。利用这项功能可以分析目标网络的流量特性。
(4)规则过滤
Libpcap自带规则过滤功能,并提供脚本编程接口,能够按照用户编程的方式对已经采集到的数据包进行过滤,以便提高分析的性能。
3.原理
一个包捕获机制包含三个主要部分,分别是面向底层的包捕获引擎,面向中间层的数据包过滤器,面向应用层的用户接口。
Linux操作系统对于数据包的处理流程是从底到上的方式,依次经历网络接口卡、网卡驱动层、数据链路层、IP层、传输层,最后到达应用程序。
Libpcap也是基于这种原理,Libpcap的捕获机制并不影响Linux操作系统中网络协议栈对数据包的处理。
对应用程序而言,Libpcap包捕获机制只是提供了一个统一的API接口,用户只需要按照相关的编程流程,简单地调用若干函数就可以捕获到感兴趣的数据包。
具体来说,Libpcap库主要由三个部分组成,网络分接头、数据包过滤器和用户API。
(1)网络分接头
网络分接头(Network Tap)是一种链路层旁路机制,负责采集网卡数据包。
(2) 数据包过滤器
数据包过滤器(Packet Filter)是针对数据包的一种过滤机制,在Libpcap中采用BPF(BSD Packet Filter)算法对数据包执行过滤操作,这种算法的基本思想就是基于规则匹配,对伊符合条件的额数据包进行放行。
(3) 用户API
用户API是Libpcap面向上层应用程序提供的编程接口,用户通过调用相关的函数实现数据包的捕获或者发送。
具体来说,Libpcap的工作原理可以描述为,当一个数据包到达网卡时,Libpcap利用创建的套接字从链路层驱动程序中获得该数据包的拷贝,即旁路机制,同时通过Tap函数将数据包发给BPF过滤器。
BPF过滤器根据用户已经定义好的过滤过则对数据包进行逐一匹配,若匹配成功则放入内核缓冲区,并传递给用户缓冲区,匹配失败则直接丢弃。如果没有设置过滤规则,所有的数据包都将放入内核缓冲区,并传递给用户缓冲区。
4.实战例子
测试平台:ubuntu 14.04
1>周期性获取数据包
handle=pcap_open_live(nic_name,4096,1,5,errBuf); if(NULL == handle){ printf("Unable to open the adapter. %s\n", nic_name); }else{ int fd = pcap_get_selectable_fd(handle); int buf_size; socklen_t optlen = sizeof(buf_size); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, &optlen) == -1) { perror("getsockopt failed"); } printf("Kernel buffer size ===>>>>> : %d bytes\n", buf_size); buf_size = 320 * 1024; setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)); setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)); // 设置用户态缓冲区大小为 pcap_set_buffer_size(handle, 320 * 1024); fd = pcap_get_selectable_fd(handle); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, &optlen) == -1) { perror("getsockopt failed"); } printf("NEW Recv Kernel buffer size ===>>>>> : %d bytes\n", buf_size); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, &optlen) == -1) { perror("getsockopt failed"); } printf("NEW Send Kernel buffer size ===>>>>> : %d bytes\n", buf_size); struct bpf_program fp; // const char *filter = "arp or (ether proto 0x8892) or ((ether proto 0x8100 or ether proto 0x88a8))"; // 根据实际情况调整 // const char *filter = "arp or (ether proto 0x88CC) or (ether proto 0x8892) or (ether proto 0x8100) or (ether proto 0x88a8) or ether proto 0x0800"; // 根据实际情况调整 const char *filter = "arp or ether proto 0x88CC or ether proto 0x8892 or ether proto 0x8100 or ether proto 0x88a8 or ether proto 0x0800"; // 根据实际情况调整 // 编译并应用 BPF 过滤器 if (pcap_compile(handle, &fp, filter, 0, PCAP_NETMASK_UNKNOWN) == -1) { fprintf(stderr, "Error compiling filter: %s\n", pcap_geterr(handle)); } if (pcap_setfilter(handle, &fp) == -1) { fprintf(stderr, "Error setting filter: %s\n", pcap_geterr(handle)); } } while(1) { header.len = 0; packet = pcap_next(handle,&header); if(header.len == 0) { continue; } for(int i=0; i printf("%02x ",packet[i]); if(i%32 == 0){ printf("\n"); } }
2>事件方式获取
// 回调函数原型void packet_handler(u_char *user, const struct pcap_pkthdr *hdr, const u_char *bytes){ (void)user; // 避免未使用参数警告 printf("Packet captured! Length: %d\n", hdr->len); for(int i=0; i<len; i++){ printf("%02x ",bytes[i]); if(i%32 == 0){ printf("\n"); } } // 在此解析数据包内容(如解析以太网/IP/TCP头)} //2 event style // 创建未激活的pcap句柄 handle = pcap_create(nic_name, errBuf); if (handle == NULL) { fprintf(stderr, "Could not create handle: %s\n", errBuf); return 2; } // 设置缓冲区大小为 2MB(单位:字节) if (pcap_set_buffer_size(handle, 2 * 1024 * 1024) != 0) { fprintf(stderr, "Error setting buffer size\n"); return 3; } // 设置混杂模式(可选) if (pcap_set_promisc(handle, 1) != 0) { fprintf(stderr, "Could not set promiscuous mode\n"); return 4; } // 激活捕获会话 if (pcap_activate(handle) != 0) { fprintf(stderr, "Activate error: %s\n", pcap_geterr(handle)); return 5; } // 开始事件循环,永久捕获数据包 printf("Starting packet capture...\n"); if (pcap_loop(handle, 0, packet_handler, NULL) < 0) { fprintf(stderr, "pcap_loop failed: %s\n", pcap_geterr(handle)); return 8;}
如需完整测试工程,可在公众号后台打赏后留言~
欢迎关注:
往期相关: