一)个人防火墙技术概述
随着网络安全问题日益严重,广大用户对网络安全产品也越来越关注。防火墙作为一种网络安全工具,早已受到大家的青睐。在PC机上使用的个人防火墙,很大程 度上成为广大网民的安全保护者。Windows下的个人防火墙都是基于对数据报的拦截技术之上。当然在具体的实现方式上它们却有很大的不同。总的来说可分 为用户级和内核级数据报拦截两类。其中内核级主要是TDI过滤驱动程序,NDIS中间层过滤驱动程序,NDIS过滤钩子驱动程序等,它们都是利用网络驱动 来实现的;而用户级的过滤包括SPI接口,Windows2000包过滤接口等。本文主要讲述基于SPI的包过滤实现,它是Winsock 2的一个新特性。
二)Winsock 2 SPI介绍
Winsock 2 是一个接口,而不是协议,所以它可以用于发现和使用任意数量的底层传输协议所提供的通信能力。起初的Winsock是围绕着TCP/IP协议运行的,但是 在Winsock 2中却增加了对更多传输协议的支持。Winsock 2不仅提供了一个供应用程序访问网络服务的Windows socket应用程序编程接口(API),还包含了由传输服务提供者和名字解析服务提供者实现的Winsock服务提供者接口(SPII)和ws2_32.dll。本文仅讨论传输服务提供者及其应用,暂不对名字解析服务提供者进行分析。
Winsock 2的传输服务提供者是以动态链接库的形式(DLL)存在的,它是通过WSPStartup函数为上层函数提供接口,而其他的传输服务提供者函数则是通过分 配表的方式来访问WS2_32.DLL。传输服务提供者的动态链接库只有在应用程序需要时才由Ws2_32.dll来装入内存中的,在不需要时则会被自动 卸载。以下是winsock 2在传输服务提供者上的WOSA(Windows开放服务结构):
----------------------------
|Windows socket 2 应用程序|
----------------------------Windows socket 2 API
| WS2_32.DLL |
----------------------------Windows socket 2 传输SPI
| 传输服务提供者(DLL) |
----------------------------
Windows socket SPI在 服务提供者中使用了以下的函数前缀命名方式:WSP(Windows socket服务提供者),WPU(Windows socket提供者向上调用),WSC(Windows socket配置)。每一个传输服务提供者都有它自己所支持的传输协议,它是使用WSAPROTCOL_INFOW结构来实现的。传输服务提供者把所有的 相关信息都存放在这个结构中,而应用程序就是通过这个结构的内容来将自己和相应的传输服务提供者相关联。
Windows socket SPI提 供三种协议:分层协议,基础协议和协议链。分层协议是在基础协议的上层,依靠底层基础协议实现更高级的通信服务。基础协议是能够独立,安全地和远程端点实 现数据通信的协议,它是相对与分层协议而言的。协议链是将一系列的基础协议和分层协议按特点的顺序连接在一起的链状结构,请参见下图:
API------------------------
| WS2_32.DLL |
SPI------------------------
| 分层协议 |
SPI-------------
| 分层协议 |
SPI------------------------
| 基础协议 |
------------------------
Ws2_32.dll 数据传输部分的主要功能是在服务提供者和应用程序之间提供流量管理的功能。每个应用程序通过Ws2_32.dll和相应的服务提供者进行严格的数据交换。 Ws2_32.dll根据应用程序在创建套接字时所提供的参数来选择特定的服务提供者,然后把应用程序的实现过程转发由所选创建套接字的服务提供者来管 理。也就是说,Ws2_32.dll只是一个中间过程,而应用程序只是一个接口,数据通信的实现却是有服务提供者来完成的。我们说过, Ws2_32.dll是通过创建套接字的API函数WSASocket或socket的参数来确定使用哪一个服务提供者。而 WSASocket/socket的参数中包括了地址族,套接字类型和协议类型,这三个因素共同决定了创建套接字的服务提供者。Ws2_32.dll在服 务提供者中寻找第一个和前面三因素相匹配的WSAPROTOCOL_INFOW结构,然后就调用这个WSAPROTOCOL_INFOW结构相应的 WSPStartup函数,(所有的数据传输服务提供者以DLL的形式,它们对外的接口就只有WSPStartup,其他的服务提供者函数都是通过 WSPStartup来调用的),进而调用如WSPSocket的函数来创建套接字,WSPConnect的函数来建立连接等等。除了流量管理功能外, Ws2_32.dll还提供了其他的服务,比如协议枚举,基于线程的阻塞钩子管理和在Ws2_32.dll和服务提供者之间进行版本协商。
传输服务提供者实现的功能包括建立连接,传输数据,实现流控制和差错控制等函数。其实Ws2_32.dll并不知道服务提供者的请求等活动是如何实现了, Ws2_32.dll在应用程序和服务提供者之间实现了媒介的功能。传输服务提供者可分为两类:套接字描述符是可安装的文件系统(IFS)句柄的提供者; 剩下的是非IFS的提供者。在我们的程序中选用了非IFS提供者。可见,服务提供者实现了底层的与网络相关的协议。Ws2_32.dll提供了介质级别的 流量管理,应用程序则提供了有关如何实现网络相关的操作,它实现了用户所希望的功能。
在传输服务提供者的实现过程中,安装顺序是非常重要 的。我们不仅要正确的安装服务提供者,而且还必须在Windows socket中注册,将相关的系统信息保存在数据库中,这样Ws2_32.dll才能够方便的获得下层服务提供者的相关信息。在Ws2_32.dll中提 供了用来安装服务提供者的函数WSCInstallProvider,它需要服务提供者的有关数据,比如DLL的名称和路径。同时Ws2_32.dll还 提供了卸载服务提供者的函数WSCDeinstallProvider,在不需要时通过它将特定的服务提供者从系统中删除。为什么说传输服务者的安装顺序 很重要呢?在服务提供者配置函数中的WSCEnumProtocols是用来枚举系统中所有已安装的服务提供者,它按照服务提供者的安装顺序相应的列出他 们。在前面我们也提到过,Ws2_32.dll在服务提供者中按安装顺序搜寻和WSASocket/socket提供的三个参数相匹配的服务提供者,所以 安装顺序在一定程度上是决定了服务提供者是否被正确调用的关键。Windows socket 2还提供了一个动态链接库Sporder.dll,它提供了对已安装的所有服务提供者顺序的重新排列(此DLL系统没有自带,common目录中已提 供)。在附录中的T-Sporder.exe是一个查询当前已安装所有数据传输服务提供者属性的工具。
服务提供者系统中区分基础协议,分 层协议和协议链是通过结构WSAPROTOCOL_INFOW中的Protocolchain结构的ChainLen值来实现的。分层协议的 ChainLen值为0,基础协议的值为1,而协议链的值是大于1。在数据传输服务提供者的实现方式中分层协议和基础协议几乎是相同的,它们的不同之处在 安装上。Windows中,现有的系统服务提供者(系统自带)几乎已提供了所有基本的服务,因此我们所写的服务提供者程序,都可以对数据报进行适当“修 饰”后调用系统服务提供者来完成绝大部分剩下的功能,无论是基础服务提供者还是分层服务提供者都可以使用这种技术,免去不必要的劳动。基础服务提供者的实 现过程主要是替换当前系统服务提供者的安装路径为自己的服务提供者的安装路径即可,当然我们必须保存所以系统服务者的相关数据,在我们卸载自己的服务提供 者还原系统服务提供者时要用到这些信息,如系统服务者DLL的名称和路径。而协议链就不同了,首先我们必须安装好所有的基础协议和分层协议后,再构造协议 链的WSAPROTOCOL_INFOW结构链,组成协议链的每个协议都会在协议链的ProtocolChain.ChainEntries数组中被定 义,协议链数组中的第一个协议应该是第一个分层服务提供者。当然在安装分层协议及协议链时我们不会改变系统服务提供者,最多只是改变系统服务提供者的安装 顺序罢了。在此,我们以分层服务提供者为例来说明数据传输服务提供者的安装过程。
Ws2_32.dll是使用标准的动态链接库来加载服务提供者接口的DLL到系统中去的,并调用WSPStartup来初始化。WSPStartup是Windows Socket 2应用程序调用SPI程序的初始化函数,也就是入口函数。WSPStartup的参数LPWSAPROTOCOL_INFOW指针提供应用程序所期望的协议信息,然后通过这个结构指针我们可以获得所保存的系统服务提供者的DLL名称和路径,加载系统服务提供者后查找到系统SPI程序的WSPStartup函数的指针,通过这个指针我们就可以将自己服务提供者的WSPStartup函数和系统SPI程序的WSPStartup函数相关联,进而调用系统的各个服务提供者函数。在数据传输服务提供者的实现中,我们需要两个程序,一个是可执行文件用来安装传输服务提供者;另一个就是DLL形式的数据传输服务提供者。
三)SPI的优点
SPI 技术相比较TDI或NDIS来说难度要低多了,因为对于TDI和NDIS来说编译和调试是非常痛苦的情况,而且SPI是工作在应用层的的,所以对处理高层 的网络封包情况下很有优势。就比如说我现在在做邮件接收和发送过滤程序时感觉SPI就非常不错,因为他是应用层的所以对邮件处理很直感,而且NDIS是工 作在网络层的,那时的数据包都是很难看懂的,而且既然是网络层的IP包那就存在IP分片的问题,如果你想得到整个邮件数据包的话那是非常痛苦的事。所以用 SPI技术就很直观和方便了。
四)SPI的缺点
SPI应该是比较上层的网络封包技术所以很容易被比其低层的技术所绕过(如TDI、NDIS等),并且应用他是工作在应用层的,所以他做不了解析网络封包 的功能,根本不可能知道网络数据包在链路层、网络层、传输层时是什么结构的,只能简简单单的根据SOKCET的SendTo或Send等之类的来实现的判 断是UDP包还是TCP包,并且SPI过滤的内容也非常有限,因为他是SOCKET服务提供者的函数所以只能过滤SOKCET里能处理的内容,比如IP地 址端口号还有BUF里的内容,如果想过滤什么到标志的TCP包之类的功能根本不可能。并且SPI最让我忍受不了的是比如我要监视一台SMTP服务器的发和 接收的SMTP包的内容时发展必须要把SMTP服务重启一下也就是一定要把那个SOKCET重启一下才行,要不然它是不会用你进行处理过的SOKCET 的。所以如果你要对哪个网络程序进行处理必须先把它停了然后把你的SPI程序启起来然后再把那个网络程序运行,这样才行(真是让你受不了的问题)哪到装我 这个邮件过滤程序还要把人家的邮件服务器再重启一下?(晕)