限制上网 SPI 获取 IE 代理地址
某些程序需要实现控制计算机上网的功能,譬如允许孩子星期六 8:00-20:00 可以上网,
其他时间不能上网。经过研究,用户态下实现这个功能大致有以下几种方法(以下讨论基于
windows 各平台):
1、使用 windows Hook,监视 IE 或其他浏览器的地址栏,发现有 www 或 http 字样的,
则更改这些 url,使之不能访问相应的 url。这种方法实现可能相对容易,但是不准确,不能
限制所有的上网软件。糊弄未成年小孩可能比较有效。
2、基于 SPI 的数据包过滤。通过编写自己的 Winsock 服务提供者(SPI),过滤掉不符
合规则的包,如过滤访问 Internet 的数据包。下面会详述此方法。
3、使用 Winsock 2 的 WSAIoctl 特性进行包过滤。WinSock 2 允许程序使用 WSAIoctl()
给一个 SOCK_RAW 类型的 socket 设置 SIO_RCVALL 属性,这样 Socket 可以接收到所有经
过本机的数据。此方法详细参阅文档“无需驱动程序的 Sniffer-IPMon”
以上三种都是在用户态(user-mode)的实现方法。优点是方便实现,无须编程者理解驱
动方面的知识,缺点是还是可能遗漏一些数据包,譬如那些一些病毒软件可能不通过 socket
接口来访问网络,这样用户态的程序就无法捕获到这些包。但由于我们的目的是限制普通用
户上网,而不是做防火墙,所以第 2 种方法基本可以接受。至于第 3 种方法,据文档 1 描述
经常无法看到本机发出去的数据包,我也没有仔细测试,有兴趣的朋友可以自己试试。
第 2 种方法主要参考了 VC 知识库《在线杂志》第 20 期中 TOo2y 的文章:“基于 SPI
的数据报过滤原理与实现”。Windows 也有一个例子 Layered.zip。另外, 《windows 网络
编程技术》(Anthony Jones 著 京京工作室译,机工出版),这本书第 14 章“Winsock2 服务
提供者接口”较详细讨论了 SPI 知识。
下面讨论实现方案。以一个局域网中的电脑为例,实现目标是:不能访问 Internet,但
可以访问局域网。我们知道,PC 机上网有两种方式:A 通过网关(路由器)上网,B 通过
代理服务器上网。
对于 A,则其访问 Internet 时的地址都是公网地址,我们直接通过自己的传输服务提供
者直接过滤掉。如下:
int WSPAPI WSPSendTo(
SOCKET s,
LPWSABUF lpbuffer,
DWORD dwbuffercount,
LPDWORD lpnumberofbytessent,
DWORD dwflags,
const struct sockaddr FAR *lpto,
int itolen,
LPWSAOVERLAPPED lpoverlapped,