PF_RING使用BPF过滤器
来源:互联网 发布:淘宝商品视频广告制作 编辑:程序博客网 时间:2024/05/29 12:47
转载:http://blog.chinaunix.net/uid-10540984-id-3240755.html
PF_RING是支持BPF过滤器的,这个在PF_RING的UserGuide中也有相应的函数原型说明。
当编译创建配置的时候,也可以关闭BPF的支持。
./userland/lib/configure --disable-bpf
默认是支持开启BPF过滤器的,在./userland/lib/pfring_mod.c源码中,会有一个宏定义:
#ifdef ENABLE_BPF
#include <pcap/pcap.h>
#include <pcap/bpf.h>
#include <linux/filter.h>
#endif
所以默认没有关闭BPF支持的情况下gcc编译时需要加入pcap的动态库。
PF_RING自己也有过滤器,确实功能功能比较少,习惯了pcap的过滤器书写,当然能使用它的过滤器是再好不过了。
代码中使用了PF_RING过滤器方式和BPF过滤器方式,用gcc编译时加"-D PRINT_ARG"则捕捉arp包,否则捕捉tcp包(其中排除了ssh和samba)
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <stdlib.h>
- #include <pfring.h>
- #include <string.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <linux/if_ether.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
- #include <getopt.h>
- #define SNAP_LEN 1518
- #define MIN_LEN (sizeof(struct ethhdr) + sizeof(struct iphdr) \
- + sizeof(struct tcphdr))
- #ifdef ARP_SWICTH
- #define PRINT_ARG "arp"
- #else
- #define PRINT_ARG "tcp and not (dst port (22 or 445) or src port (22 or 445))"
- #endif
- static pfring *pd;
- static char *in_dev = NULL;
- static struct option opts[] = {
- {.name = "interface", .has_arg = 1, .val = 'i'},
- {.name = "help", .has_arg = 0, .val = 'h'},
- {NULL}
- };
- static void printHelp(void) {
- printf("-h Print this help\n");
- printf("-i <device> Device name. Use device\n");
- exit(EXIT_FAILURE);
- }
- static int process_packet(const struct pfring_pkthdr *header,
- const u_char *packet) {
- struct ethhdr *ethh;
- struct arphdr *arph;
- struct iphdr *iph;
- struct tcphdr *tcph;
- struct in_addr src, dst;
- /* 判断长度避免访问到空指针 */
- if (header->caplen < MIN_LEN) return;
- ethh = (struct ethhdr *)packet;
- printf("Eth_type:");
- switch(ntohs(ethh->h_proto)) {
- case 0x0800:
- printf("IP | ");
- /* 打印IP协议的目的地址和源地址 */
- packet += sizeof(struct ethhdr);
- iph = (struct iphdr *)packet;
- src.s_addr = iph->saddr;
- dst.s_addr = iph->daddr;
- printf("%s->", inet_ntoa(src));
- printf("%s | ", inet_ntoa(dst));
-
- switch (iph->protocol) {
- case 6:
- packet += sizeof(struct iphdr);
- tcph = (struct tcphdr *)packet;
- printf("Protocol:TCP sport:%d->", ntohs(tcph->source));
- printf("dport:%d", ntohs(tcph->dest));
- break;
- case 1:
- printf("Protocol:ICMP");
- break;
- }
- break;
- case 0x0806:
- printf("ARP_request ");
- struct in_addr *src_in_addr, *dst_in_addr;
- struct macaddr {
- u_char MAC[6];
- };
- struct macaddr *src_mac, *dst_mac;
- packet += sizeof(struct ethhdr) + 8;
- src_mac = (struct macaddr *)packet;
-
- packet += 6;
- src_in_addr = (struct in_addr *)packet;
- printf("%s", inet_ntoa(*src_in_addr));
-
- packet += 4;
- dst_mac = (struct macaddr *)packet;
- packet += 6;
- dst_in_addr = (struct in_addr *)packet;
- printf(" -> %s", inet_ntoa(*dst_in_addr));
- printf(" %02x:%02x:%02x:%02x:%02x:%02x",
- src_mac->MAC[0], src_mac->MAC[1], src_mac->MAC[2],
- src_mac->MAC[3], src_mac->MAC[4], src_mac->MAC[5]
- );
- printf(" -> %02x:%02x:%02x:%02x:%02x:%02x",
- dst_mac->MAC[0], dst_mac->MAC[1], dst_mac->MAC[2],
- dst_mac->MAC[3], dst_mac->MAC[4], dst_mac->MAC[5]
- );
- break;
- case 0x8035:
- printf("ARP_response ");
- break;
- }
- printf("\n");
- }
- int main(int argc, char *argv[]) {
- char c;
- while((c = getopt_long(argc, argv, "hi:", opts, NULL)) != -1) {
- switch(c) {
- case 'h':
- printHelp();
- break;
- case 'i':
- in_dev = strdup(optarg);
- break;
- }
- }
- if(in_dev == NULL) printHelp();
- printf("Capturing from %s\n", in_dev);
- /* 打开pf设备 */
- pd = pfring_open(in_dev, SNAP_LEN, PF_RING_PROMISC);
- if(pd == NULL) {
- printf("pfring_open %s error [%s]\n", in_dev, strerror(errno));
- exit(EXIT_FAILURE);
- } else {
- u_int32_t version;
- /* 获取版本号 */
- pfring_version(pd, &version);
- printf("Using PF_RING v%u.%u.%u\n",
- (version & 0xFFFF0000) >> 16,
- (version & 0x0000FF00) >> 8,
- version & 0x000000FF);
- }
- /*
- 设定捕获方向
- rx_and_tx_direction 双向捕获
- rx_only_direction 只捕获接收
- tx_only_direction 只捕获发送
- */
- if (pfring_set_direction(pd, rx_only_direction) != 0) {
- printf("pfring_set_direction is failure error [%s]\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- #if 0 /* PF_RING过滤器 */
- int rc;
- filtering_rule rule;
- memset(&rule, 0, sizeof(rule));
- rule.rule_id = 1; /* 设置规则运行优先级,数值越小优先级越高 */
- /* 匹配哪些情况 */
- rule.rule_action = forward_packet_and_stop_rule_evaluation;
- // rule.core_fields.proto = 6 /* 设置需要过滤的传输层协议 6 TCP*/;
- rule.core_fields.dhost.v4 = inet_addr("8.8.8.8"); /* 过滤出的IP地址*/
- rule.core_fields.dhost_mask.v4= inet_addr("255.255.255.255"); /* 主机子网 */
- /* 编译规则 */
- if((rc = pfring_add_filtering_rule(pd, &rule)) < 0)
- fprintf(stderr, "pfring_add_filtering_rule(2) failed\n");
- exit(EXIT_FAILURE);
- else
- printf("Rule added successfully...\n");
- /* 开启过滤器,第二个参数0表示drop,非零则为accept*/
- pfring_toggle_filtering_policy(pd, 0);
- #endif
- #if 1 /* 使用BPF过滤器 */
- /* 过滤掉目标端口为22或455的数据包,也可以在前面加协议 */
- char filter_buffer[] = {PRINT_ARG};
- if (pfring_set_bpf_filter(pd, filter_buffer) != 0) {
- printf("set_BPF is failure!\n");
- exit(EXIT_FAILURE);
- }
- #endif
- /* 开启pfring */
- if (pfring_enable_ring(pd) != 0) {
- printf("pfring_enable is failure error [%s]\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- while(1) {
- struct pfring_pkthdr hdr;
- u_char *buffer;
- int rc;
- /* 接收处理数据报文,最后一个参数非0则为阻塞*/
- if((rc = pfring_recv(pd, &buffer, 0, &hdr, 1) > 0)) {
- /* 调用函数处理捕获的数据包 */
- process_packet(&hdr, buffer);
- } else{
- /* 稍等PF_RING就绪 */
- usleep(10);
- }
- }
- pfring_close(pd);
- return(0);
- }
0 0
- PF_RING使用BPF过滤器
- 使用socket BPF
- linux 下的 包过滤器 BPF
- bpf
- bpf
- BPF分析及使用方式
- PF_RING
- pf_ring
- PF_RING Libzero中使用HugePage
- PF_RING Libzero中使用HugePage
- PF_RING数据捕获,tcpreplay使用
- pf_ring安装 使用 修改缓冲区
- 使用EOS中bpf创建流程失败问题解决办法
- 过滤器使用
- 过滤器使用
- 使用过滤器
- PF_RING浅析
- PF_RING 总结
- 编程语言中一些令人抓狂的规则
- 链表的操作---带菜单
- shell脚本
- Activity 生命周期 ——各种情况测试
- 安卓手机调试,出现can't connection to 10.0.2.2
- PF_RING使用BPF过滤器
- 自适应波束形成(一)——窄带波束形成和宽带波束形成
- C# 定时器的使用
- 程序员面试攻略试题1
- 3D数学基础,图形与游戏开发笔记1
- rails 4 安装gem install mysql 报checking for main() in -llibmysql... no错
- or1200开发环境的使用
- Sed
- 产品口味测试研究方法