全部博文(29)
分类: LINUX
2016-03-16 17:40:58
学习NDIS一段时间了,不过还是毫无头绪,理论都能明白,可是不知道怎么下手去做,网上没有没有太详细的教程。我是比较笨,而且比较懒的。:)
所以准备暂缓NDIS网络和驱动方面的学习,等今后遇见师父了再请教之,好运~
NDIS中的网络数据都是原始的,即没有经过主机协议栈处理的网络数据,如果学习网络协议的话,我觉得研究原始数据包还是挺合适的。
Socket通信中,主机A与主机B之间通信,Socket接收到的内容都是通信的内容,没有附带主机A或主机B的信息,这点可以回想最开始学习Socket编程的时候,主机A发送“Hello,mydearfriend.”,那么主机B收到的确实是“Hello,mydearfriend.”。不像原始数据包中,还会带有以太网帧头、IP头、TCP/UDP头,然后才是通信的内容。所以呢,当我们通过NDIS获取到了原始数据包之后,应该按照现在的网络通信模型对原始数据包进行解析。
=============================================================================================
常用的以太网MAC帧格式有两种,标准:DIXEthernetV2标准(即以太网V2标准)和IEEE的802.3标准。现在使用最多的是以太网V2的MAC帧格式。该标准由5个字段组成:6字节的目的地址、6字节的源地址、2字节的类型(用来标识上一层的协议类型,例如:0x0800表示上层使用是IP数据报)、46字节至1500字节长度不等的IP数据报,以及4字节的帧检验序列(FCS)。分析每一帧可以得到此数据包的源MAC地址和目的MAC地址,并且可以得到IP数据报的完整内容。
IP数据报的第4至7位是IP首部长度,该字段可以用来准确定位上层协议的起始位置(例如:TCP的首部)。第10字节是协议字段,指出该IP数据报携带的数据使用何种协议,常用的协议字段如表1所示。第13至16字节是源IP地址,第17至20字节是目的IP地址。因此可以据此解析出该数据包的源IP地址和目的IP地址。
表1常用的IP协议和相应的字段值
协议名 |
ICMP |
IGMP |
TCP |
EGP |
IGP |
UDP |
IPv6 |
OSPF |
协议字段值 |
1 |
3 |
6 |
8 |
9 |
17 |
41 |
89 |
TCP报文段的第1至2字节是源端口号,第3至4字节是目的端口号。第13字节的前4位是数据偏移,该字段实际上指出了TCP报文段的首部长度。如果TCP承载的是HTTP协议,则可以据此定位HTTP协议的起始位置。系统处理时,如果分析是HTTP协议,则提取出HTTP的内容,以明文显示。而可以直接显示HTTP报文信息的原因是:HTTP是应用层协议,使用面向连接的TCP作为传输层协议,在向下层传递时是以明文的方式直接传递,即TCP在HTTP报文前加TCP头封装HTTP报文。因此,只要把捕获到的数据包依次剥去MAC头、IP头、TCP头,就可以显示HTTP报文的内容了。
HTTP报文分为两种:请求报文和响应报文。
对于判断是否为HTTP报文,目前还没有快速有效的方法。传统的方法依据:①传送HTTP报文前是否有TCP的三次握手;②判断数据包中是否含有诸如“GET”、“HTTP/1.1”等关键字。对于这两种方法,第①点需要一定的空间开销,要判断TCP承载的是否为HTTP报文,需要分配一定的空间存储前3个数据包的相关信息(实际并不需要存储3个数据包的全部内容,但是即便是若干比特的信息,也会增加NPF的负担),这给NPF(NetgroupPacketFilter)的运行速率和存储器带来挑战;对于第②点,由于HTTP是面向文本的,因此在报文中的每一个字段都是一些ASCII码串,因而各个字段的长度都是不确定的。请求报文中除了“GET”方法外,还有7种常用的方法,如果要一一模式匹配来确定是否是HTTP报文,显然会造成很大的时间开销。此外,响应报文含“HTTP/1.1”(或HTTP/1.0)的版本号,这个字段在请求报文中也有,具体的版本是1.1还是1.0则是不确定的。因此,综合考虑时间和空间的开销,本文采取模式匹配“HTTP”的方法来判断是否为HTTP报文。具体方法是:捕获到的数据包从TCP的尾部(HTTP的第一个字节)开始匹配“HTTP”,如果匹配成功,则认为是HTTP报文,否则就不是。这种方法存在的问题是:①如果TCP承载的是FTP或SMTP等其他应用层协议,恰好在某个部分也含有“HTTP”字样,则会误判为HTTP报文。但是由于基于HTTP协议的Web服务已经成为Internet的主流,非HTTP协议只占到小部分,因此误判的几率很小。系统测试期间,还未发现此类误判问题,用户界面显示的明文信息表明:确为HTTP协议的请求报文或响应报文。②该方法本身不存在“漏判”,因为所有的HTTP报文都含有“HTTP”字样,而抓到的数据包只要含有“HTTP”字样,就被过滤认为HTTP报文。但是,由于该方法需要一定的时间开销,可能来不及匹配后续的数据包而造成广义上的“漏判”。这个问题通过编写高效的模式匹配算法可以得到一定的改进,但是不能解决根本问题。根本问题在于匹配速度和内核的存储器容量的限制。
对于过滤用户指定的IP地址和端口号,用户输入的IP地址为char[]字符数组型,而且是用标准的Internet的“.”间隔格式来表示一个Internet地址,而捕获得到的数据包拆包后的IP地址是网络字节的,因此不可直接比较。本文的方法是:首先用inet_addr()将用户输入的IP地址转换成一个无符号长整型数(实际上是in_addr类型),然后与抓到的数据包的4字节IP地址一一比较,即可过滤出用户指定的IP地址。对于端口号亦可类似处理。
=============================================================================================
这里仅对原始数据包中HTTP的解析,如果是原始数据包中其他应用层的协议解析,也可参考此思路。
说明:这里例举原始数据包中HTTP的解析的原因是,我想做一个防火墙,不仅可以屏蔽某个网站(这里有两种方法:①屏蔽该网站的IP地址②主机发送到该网站的HTTP请求时,自己通过程序伪造一个HTTP应答在网站的主机返回HTTP应答之前返回给浏览器,毕竟和“127.0.0.1”比其他IP地址通信更快。可能第二种方法有问题。),还可以屏蔽某网站的某个页面(方法可参考屏蔽某个网站的方法②)。