网络报文抓取研究

1     引言

网络报文抓取是指通过对主机网络设备的探测,实现获取该网络当前传输的所有信息,并根据信息的源主机、目标主机、服务协议和端口等信息简单过滤掉不关心数据,然后提交给上层应用程序进行进一步处理。

2     网络数据包捕获原理

一个包捕获机制包含三个主要部分

1) 包捕获机制

不同的操作系统实现的底层包捕获机制可能是不一样的,但从形式上看大同小异。数据包常规的传输路径依次为网卡、设备驱动层、数据链路层、IP层、传输层、最后到达应用程序。而包捕获机制是在数据链路层增加一个旁路处理,对发送和接收到的数据包做过滤/缓冲等相关处理,最后直接传递到应用程序。

2) 包过滤机制

包过滤机制是对所捕获到的数据包根据用户的要求进行筛选,最终只把满足过滤条件的数据包传递给用户程序。

3) 用户程序的接口

对用户程序而言,包捕获机制提供了一个统一的接口,使用户程序只需要简单的调用若干函数就能获得所期望的数据包。这样一来,针对特定操作系统的捕获机制对用户透明。

3     网络数据包捕获主要实现技术介绍

3.1    SOCK_RAW  原始套接字

我们常用的网络编程都是在应用层的报文的收发操作,也就是流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM)。而这些数据包都是由系统提供的协议栈实现,用户只需要填充应用层报文即可,由系统完成底层报文头的填充并发送。

原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM、SOCK_DGRAM的套接字,它实现于系统核心。可以处理特殊的IPv4、ICMP、IGMP等网络报文。总体来说,SOCK_RAW可以处理普通的网络报文之外,还可以处理一些特殊协议报文以及操作IP层及其以上的数据。

3.1.1    SOCK_RAW 抓包实现

1)    利用PF_INET协议族创建RAW SOCKET

socket(PF_INET,SOCK_RAW,IPPROTO_TCP|IPPROTO_UDP)

采用这样的方法接收到的数据都是发往本机的数据,不能接受从本机发出去的数据。第三个参数协议若是指定,只能接受符合指定协议的数据包:

IPPROTO_TCP:接收采用tcp传输的数据包。

IPPROTO_UDP:接受采用udp传输的数据包。

2)     利用PF_PACKET协议族创建RAW SOCKET

socket(PF_PACKET,SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ARP|ETH|RARP))

这种方法创建的套接字是在数据链路层直接抓取以太网帧。可以接收到发往本机和本机发出的数据,第三个参数的协议类型有:

ETH_P_IP 0x0800   :只接收发往本机mac的ip类型的数据帧

ETH_P_ARP 0x0806  :只接受发往本机mac的arp类型的数据帧

ETH_P_RARP 0x8035 :只接受发往本机mac的rarp类型的数据帧

ETH_P_ALL 0x0003 :接收发往本机mac的所有类型的数据帧, 和从本机发出的所有类型的数据帧。

3.2    Libpcap

Libpcap是Packet Capture library的英文缩写,是Unix/Linux平台下的网络数据包捕获函数库,该库提供的C函数接口用于捕获经过指定网络接口(通过将网卡设置为混杂模式,可以捕获所有经过该网络接口的数据包)的数据包。

Libpcap提供的接口函数主要实现和封装了与数据包的采集、构造、发送等有关的功能。著名的tcpdump就是在Libpcap的基础上开发完成的。

3.2.1    Libpcap 工作原理

Libpcap是一个独立于系统的用户级数据包捕获API接口,为底层网络监测提供了一个可以移植的框架。

Libpcap库主要由三个部分组成,网络分接头、数据包过滤器和用户API。

1)     网络分接头

网络分接头(Network Tap)一种链路层旁路机制,负责采集网卡数据包。

libpcap的包捕获机制就是在数据链路层加一个旁路处理。当一个数据包到达网络接口时,libpcap首先利用已经创建的Socket从链路层驱动程序中获得该数据包的拷贝,再通过Tap函数将数据包发给BPF过滤器。

2)     数据包过滤器

数据包过滤器(Packet Filter) 针对数据包的一种过滤机制,在Libpcap中采用BPF(BSDPacket Filter)算法对数据包执行过滤操作,这种算法的基本思想就是基于规则匹配,对符合条件的数据包进行放行。

3)    用户API

用户API是Libpcap面向上层应用程序提供的编程接口,用户通过调用相关的函数实现数据包的捕获或者发送。

其具体的工作流程如下图所示:

 

3.2.2    Libpcap 抓包框架

由于Libpcap是一种与系统无关,采用分组捕获机制的分组捕获函数库,用于访问数据链路层,在不同的平台上采用统一的编程接口,使用LibPcap编写的程序可以自由地跨平台使用。

Libpcap具体抓包流程如下图所示:

 

3.2.3    Libpcap 库主要抓包函数

1)     打开设备进行嗅探

pcap_t*pcap_open_live(char *device, int snaplen, int promisc,

 int to_ms, char *ebuf)

2)     编译过滤规则

int pcap_compile ( pcap_t * p, struct bpf_program * fp, char * str,

int optimize, bpf_u_int32 netmask )

3)     设置编译后的过滤规则

intpcap_setfilter(pcap_t *p, struct bpf_program *fp)

4)     抓包

intpcap_loop(pcap_t *p, int cnt, pcap_handler callback,

u_char*user)

5)     回调函数

voidgot_packet(u_char *args, const struct pcap_pkthdr *header, const u_char*packet)

6)     关闭会话

voidpcap_close(pcap_t *p)

3.3    WinPcap

WinPcap是LibPcap的Windows版本,它是一个基于Win32的捕获数据包和网络分析的体系结构,它包括一个内核级的包过滤器,一个底层的动态链接库(Packet.dll),一个高层并且与系统无关的库(WPcap.dll,基于LibPcap0.6.2版本)。WinPcap是集成于Windows95,98,ME,NT,2000和XP操作系统的设备驱动程序,它可以从网卡捕获或者发送原始数据,同时能够过滤并且仓储数据包。开发WinPcap这个项目的目的在于为Win32应用程序提供访问网络底层的能力。

3.3.1  WinPcap内部结构

Winpcap是针对Win32平台上的抓包和网络分析的一个架构,它由内核级的网络组包过滤器(Netgroup Packet Filter,NPF)、用户级的动态链接库Packet.dll和Wpcap.dlI等 3个模块组成[7]。

1)网络组包过滤器。它是运行于操作系统内核中的驱动程序,它直接与网卡驱动程序进行交互,获取在网络上传输的原始数据包。NPF与操作系统有关,WinPcap开发组针对不同的Windows操作系统提供了不同版本的NPF。在Win95/98/ME系统中,它以VXD文件形式存在,在WindowsNT和Windows 2000系统中,它以SYS文件形式存在。该模块提供了抓取数据包以及发送数据包的基本功能,此外还提供了一些高级功能,如数据包过滤系统和检测引擎。

2)低级动态链接库。Pactet.dll用于在Win32平台上为数据包驱动程序提供一个公共的接口。不同的Windows版本在用户态和内核态之间提供互不相同的接口,而Pactet.dll可以屏蔽这些接口区别,提供一个与系统无关的API。基于Pactet.dll开发的数据包截获程序可以运行于不同的Win32平台而不必重新进行编译。Pactet.dll可以执行如获取适配器名称、动态驱动器加载以及获得主机掩码及以太网冲突次数等低级操作。

3)高级动态链接库。Wpcap.dll模块与Unix系统下的BSD截获架构提供的Libpcap库完全兼容。它提供了一组功能强大且跨平台的函数,利用这些函数可以不去关心适配器和操作系统的类型。Wpcap.dll含有诸如产生过滤器、定义用户级缓冲以及包注入等高级功能。编程人员既可以使用包含在Pactet.dll中的低级函数直接进入内核级调用,也可以使用由Wpcap.dll提供的高级函数调用,这样功能更强,使用也更为方便。Wpcap.dll的函数调用会自动调用Pactet.dll中的低级函数,并且可能被转换成若干个NPF系统调用。

3.3.2  WinPcap的主要函数库

Winpcap函数库主要有如下函数:
1)int  pcap_findalldevs (pcap_if_t **,char *)
用来获得网卡的列表
2)voidpcap_freealldevs (pcap_if_t *)   
与int pcap_findalldevs (pcap_if_t **,char *)配套使用,当不需要网卡列表时,用此函数释放空间
3)pcap_t     *pcap_open_live(const char *, int, int,int, char *)
用来得到一个包抓取得描述符
4)Int  pcap_loop(pcap_t *, int, pcap_handler, u_char*)
捕获数据包,不会响应pcap_open_live()中设置的超时时间
5)int     pcap_dispatch(pcap_t *, int, pcap_handler,u_char *)
捕获数据包。可以不被阻塞
6)int          pcap_next_ex(pcap_t *, structpcap_pkthdr **, const u_char **)
捕获数据包
7)int          pcap_compile(pcap_t *, structbpf_program *, const char *, int,  bpf_u_int32)
编译一个过滤设备,与pcap _ setfilter () 配合使用
8)int     pcap_setfilter(pcap_t *, struct bpf_program*)
用来联系一个在内核驱动上过滤的过滤器,这时所有网络数据包都将流经过滤器,并拷贝到应用程序中。

3.4    JPcap

JPcap是一个能够捕获,发送网络数据包的Java类库包。这个包用到了LibPcap和WinPcap。使用时需要安装LibPcap(UNIX平台) 或者WinPcap(Windows平台)库。

目前JPcap在FreeBSD 3.x,Linux RedHat 6.1,Solaris和Microsoft Windows 2000/XP系统上已经做过测试,并且支持Ethernet,IPv4,IPv6,ARP/RARP,TCP,UDP,ICMPv4协议。JPcap是一个Java类集合,它为网络数据包的捕获提供接口和系统支持。JPCAP的类库结构

Jpcap0.4版本共有1个接口14个类,分别简介如下:

1、 接口综述

JpcapHandler:这个接口用来定义分析被捕获数据包的方法

2、 类综述

ARPPacket:这个类描述了ARP/RARP包,继承了Packet类 

DatalinkPacket:这个抽象类描述了数据链路层的包,它继承了java.lang.Object

EthernetPacket:这个类描述了以太帧包,继承DatalinkPacket类

ICMPPacket:这个类描述了ICMP包,继承了IPPacket类

IPAddress:继承了java.lang.Object,这个类描述了IPv4和IPv6地址,其中也包含了将IP地址转换为域名的方法

IPPacket:这个类描述了IP包,继承了Packet类,支持IPv4和IPv6

IPv6Option:它继承了java.lang.Object,这个类描述了IPv6选项报头

Jpcap:它用来捕获数据包,继承了java.lang.Object

Jpcap.JpcapInfo:Jpcap的内部类,它包含被捕获数据包的信息(在jpcap0.4修改部分BUG之后不再使用这个类)

JpcapSender:它用来发送一个数据包,继承了java.lang.Object

JpcapWriter:它用来将一个被捕获的数据包保存到文件,继承了java.lang.Object

Packet:这个类是所有被捕获的数据包的基类,继承了java.lang.Object

TCPPacket:这个类描述TCP包,继承了IPPacket类

UDPPacket:这个类描述了UDP包,继承了IPPacket类

posted @ 2019-03-07 12:36  h2z  阅读(1230)  评论(0编辑  收藏  举报