网络安全 频道

网络监听技术研究综述与分析

1、引言
网络监听与包过滤技术是网络入侵的核心技术,也是网络安全协议技术研究的核心技术.监听技术最初是提供给系统管理员用的,主要是对网络的状态、信息流动和信息内容等进行监视,相应的工具被称为网络分析仪. 在PPDR模型以及几乎所有的IDS(
入侵检测系统)中,最基本的要求就是能够实现网络监听与过滤,所有的部分(安全策略、防护、检测、响应)都建立在此基础上.但是,技术是把双刃剑,网络监听和过滤也成了黑客使用最多的技术,主要用于监视他人的网络状态、攻击网络协议、窃取敏感信息等目的.

2 、网络监听与包过滤实施方法及其关键步骤
2.1 最简单的监听程序模型
最简单的监听程序包括内核部分和用户分析部分.其中内核部分负责从网络中捕获和过滤数据.用户分析部分负责界面、数据转化与处理、格式化、协议分析,如果在内核没有过滤数据包,在这里还要对数据进行过滤.
一个较为完整的基于网络监听和过滤的程序一般包括以下步骤:数据包捕获、数据包过滤与分解、数据分析.
2.2 数据包捕获
常用的方法有两种:
(1)通过设置硬路由器的监听端口;
(2)利用以太网络的广播特性.这种方式必须将网卡设置为混杂(promiscuous)模式.监听程序工作在网络环境的底三层,可以拦截所有经过该机器的网络上传送的数据,然后将这些数据做相应处理,可以实时分析这些数据的内容,进而分析网络当前状态和整体布局.UNIX类操作系统所提供的分组捕获机制主要有以下三种:(1)数据链路提供者接口DLPI(Data Link Provider Interface);(2)Linux的SOCK_PACKET类型套接口;(3)伯克利数据包过滤器BPF(Berkeley Packet Filter).对于windows系统(要求在window2000/xp以上),要实现数据链路层上的数据捕获需要使用驱动程序.网络驱动程序接口规范函数库(NDIS函数库)为了方便用户对网络底层的操作,提供了许多相关函数.基于windows的数据包捕获方案有以下几种:
(1)  使用原始套接字(row socket)机制.方法简单,但功能有限,只能捕获较高层的数据包.在创建了原始套接字后,需要通过setsockopt()函数来设置IP头操作选项,然后再通过bind()函数将原始套接字绑定到本地网卡.为了让原始套接字能接受所有的数据,还需要通过ioctlsocket()来进行设置,而且还可以指定是否亲自处理IP头.至此,实际就可以开始对网络数据包进行监听了,对数据包的获取仍象流式套接字或数据报套接字那样通过recv()函数来完成.但是与其他两种套接字不同的是,原始套接字此时捕获到的数据包并不仅仅是单纯的数据信息,而是包含有 IP头、 TCP头等信息头的最原始的数据信息,这些信息保留了它在网络传输时的原貌.通过对这些在低层传输的原始信息的分析可以得到有关网络的一些信息.由于这些数据经过了网络层和传输层的打包,因此需要根据其附加的帧头对数据包进行分析;
(2)  直接连接调用NDIS库函数,这种方法功能非常强大,但是比较危险,很可能导致系统崩溃和网络瘫痪;
(3)  使用或者自行编写中间层驱动程序,这是微软公司推荐使用的一种方法,微软提供的win2000 DDK中也提供了几个这样的驱动程序.在具体的实现方式上可分为用户级和内核级两类.其中内核级主要是TDI捕获过滤驱动程序,NDIS中间层捕获过滤驱动程序,NDIS捕获过滤钩子驱动程序等,它们都是利用网络驱动来实现的;而用户级的包括SPI接口,Windows2000包捕获过滤接口等;
(4)  使用或自行编写协议驱动程序,文献[1]中给出了一个完整的实现方案;
(5)  使用第三方捕获组件或者库,比如Winpcap.
2.3数据包过滤与分解
捕获数据包后要进行的工作是对其进行包过滤与分解,用通俗的语言表达就是在海量的数据里面找我们感兴趣的内容.关于此部分的研究很多[1,5].不好的过滤规则和程序会导致数据包丢失、来不及分析,严重的影响系统的工作效率,甚至导致系统崩溃.一些基础的过滤规则如下:
(1)站过滤:专门筛选出来自一台主机或者服务器的数据;
(2)协议过滤:根据不同的协议来筛选数据,例如:选择TCP数据而非UDP数据;
(3)服务过滤:根据端口号来选择特定数据包;
(4)通用过滤:通过数据包中某一特定位置开始,选择具有某些共同数据特征的数据包;
大部分情况下,我们的过滤规则是上面基本规则的组合.有时,为了保证我们设置的缓冲区被一些莫名其妙的无效数据溢出,我们必须在捕获前进行粗过滤,然后在捕获后再进行一次过滤,然后进行分析.
过滤完成后,为了使得我们的缓冲区能处理的包更多,我们必须进行包分解(Slice),因为数据包最关键的部分在数据包的头部.即使要分析整个包,包分解的过程还是要的,不过我们得记住包的原始长度.包分解的原则是对捕获的包按照相应协议规定的数据结构来提取结构中每个字段的数据.BPF机制在这方便做的非常成功,关于对BPF原理和BPF虚拟机包的过滤和分解的原理,文献[2]给出了详细的说明.
2.4数据分析
这一部分就是对已经捕获的数据包进行各种分析,比如网络流量分析,数据包中信息分析,敏感信息提取分析等,其功能取决于系统要达到的目的.

3 、基于Libpcap/Winpcap网络监听与过滤
3.1 Libpcap/Winpcap简介
Libcap(Winpcap是其windows版本)可以提供与平台无关的接口,而且操作简单,它是基于改进的BPF(Berkeley Packet Filter),该软件来自Berkeley的Lawrence National Laboratory研究院.Winpcap是Libpcap 的windows版本,linux用户使用Libpcap,Windows用户使用Winpcap. 使用Winpcap包过程比较规范.在密码学协议分析中,我们常用它来实现协议攻击.
3.2 Libpcap源代码逻辑结构
(1)初始化:这部分的功能包括打开设备、读取设备,设置过滤器部分.主要的函数如下:pcap_read(),pcap_open_live(),pcap_setfilter().在源代码中是以pcap-*.c方式出现;
(2)过滤规则表达式的处理:这部分的功能包括对过滤规则表达式进行编译、优化、调试(该部分过滤机制采用的是伪主机技术),如果各熟悉BPF程序的编码规则,甚至可以修改其中代码,创建自己的过滤规则.这部分代码在:gencode.c,grammar.c,scanner.c,optimize.c,这一部分代码的工作方式是通过将我们输入的过滤规则表达式编译成BPF代码,然后存在一个名为bpf_program的结构中,最后利用pcap_setfilter()来加载;
(3)本机网络设置部分:这部分是通过获取socket的状态,来检测TCP/IP层网络设置.主要函数有:pcap_lookupdev()、pcap_lookupnet()等,这部分代码在inet.c中;
(4)其他部分:在pcap.c中定义了读数据的对外统一接口pcap_next()来获取下一个数据包,获取当前错误信息的pcap_geterr()等函数.另外,Libcap还支持脱机方式监听,在savefile.c中,有两个函数:pcap_open_offline()和pcap_offline_read().
3.2基于Libcap/Winpcap库的基本使用流程
基于Libcap/Winpcap库的基本使用流程比较规范,一般为:
step1: 使用pcap_lookupdev获取设备;
step2: 使用pcap_lookupnet获取网络地址和子网掩码;
step3: 使用pcap_open_live打开设备;
step4: 使用pcap_complile编译过滤规则;
step5: 使用pcap_setfilter设置过滤规则;
step6: 使用pcap_loop循环捕获数据包,在其中调用相应处理函数;
step7: 使用pcap_close关闭设备句柄.
3.3一些使用难点和关键代码说明
(1) 获得本地的网卡列表
pcap_if_t *alldevs; //用于存储网卡信息
char errbuf[PCAP_ERRBUF_SIZE];// 用于存储错误信息
if (pcap_findalldevs(&alldevs, errbuf) == -1) // 这个API用来获得本机网卡列表
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}

pcap_freealldevs(alldevs);//最后用pcap_freealldevs()释放内存资源
(2) 接受数据包
使用循环调用pcap_next来接受数据报,当然也可以用pcap_next_ex来接受数据包,不过pcap_next_ex效率会高些.
pcap_t *adhandle;
int res;
struct pcap_pkthdr *header;
u_char *pkt_data

while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){ }

(3) 数据包过滤
数据包过滤处理是监听技术中的难点和重点.我们用pcap_compile()来编译一个过滤设备,它通过一个高层的boolean型变量和字串产生一系列的能够被底层驱动所解释的二进制编码.boolean表示语法能够在这个文件的过滤表示语法中找到.pcap_setfilter() 用来联系一个在内核驱动上过滤的过滤器,这时所有网络数据包都将流经过滤器,并拷贝到应用程序中.下面的代码展示了如何编译并社定一个过滤设备.注意我们必须从pcap_if结构中获得掩码,因为一些过滤器的创建需要这个参数.下面的代码段中的pcap_compile()的"ip and tcp"参数说明只有IPV4和TCP数据才会被内核保存并被传递到应用程序.

if(d->addresses != NULL)
// 获得第一个接口地址的掩码
netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
//如果这个接口没有地址那么我们假设他为C类地址
netmask=0xffffff;
//编译过滤规则
if(pcap_compile(adhandle, &fcode, "ip and tcp", 1, netmask) <0 ){
fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
pcap_freealldevs(alldevs);
return -1;
}
//设置过滤器
if(pcap_setfilter(adhandle, &fcode)<0){
fprintf(stderr,"\nError setting the filter.\n");

(4)与脱机方式监听相关操作
有些时候我们想使用脱机方式以便进一步深入研究.Winpcap为我们提供了很多API函数来处理脱机器监听.通过Winpcap,我们可以将流经网络的数据包保存到一个堆文件,以后也可以读取堆的内容.详细过程和完整示例代码请参考[6].
将数据包保存到文件的过程如下:打开网卡后,调用pcap_dump_open()来打开一个文件,将文件和某个网卡相关联.在自己的包处理函数packet_handler()内部通过调用pcap_dump()来将捕获的数据报存储到文件.
从文件读数据包的过程如下:利用pcap_open_offline()用来打开一个堆文件,之后用pcap_loop()来循环从文件中读取数据. Winpcap的最新版本提供了一个新的方法来将数据包存储到磁盘,就是使用pcap_live_dump()函数.他需要三个参数:一个参数文件名、一个参数是该文件允许的最大长度、一个参数是该文件所允许的最大包的数量.对这些参数来说, 0意味着没有最大限制.但是实际上我们可以在调用pcap_live_dump()前设置一个过滤器来定义哪些数据包需要进行存储.pcap_live_dump() 是运行在非阻塞模式的,所以他会立刻返回:数据的存储过程将会异步的进行,直到文件到达了指定的最大长度或最大数据报的数目为止.应用程序能够用pcap_live_dump_ended()来等检查是否数据存储完毕,如果你指定的最大长度参数和数据报数量为0,那么该操作将永远阻塞.pcap_live_dump() 和 pcap_dump()的不同在于性能,pcap_live_dump()采用Winpcap NPF驱动来从内核级的层次上向文件中写数据,从而使内存拷贝最小化.显然,这些特点在其他的操作系统下是不能够实现的,pcap_live_dump()是Winpcap所特有的,而且只能够应用于Win32环境.

4、总结
Libcap/Winpcap库函数的使用简化了我们的工作,使得我们在网络监听与包过滤技术的研究主要集中在过滤规则的设置和对数据包的分析上,为我们的研究提供了大大的方便.[6]中给出了Libcap/Winpcap库函数在IPV6下的许多新特性.另外,在网络协议分析攻击的真正实现和IDS实现上, Libcap/Winpcap库函数提供了巨大的帮助,使得我们可以把主要的精力放在原理方案设计上,而不需要关注底层的细节.在IPV6下的对网络监听的技术研究是目前的一个热点话题,我们将继续关注,进一步深入研究.
http://netadmin.77169.com/HTML/20060603003339.html
0
相关文章