前言

从本篇开始,将来聊一下网络过滤驱动。

网络分层模型

在谈这个之前,要简单介绍一下网络分层模型。
常见的有 4,5,7层模型。

0.png

000.png

在4层模型中,将数据链路层和物理层合并为了网络接口层。
一份数据要经由网络传递时,该数据会逐层包装成相应的协议格式提供给各方使用,在到达后又会逐层解包。

之所以会这么做,是为了满足不同需求(有时候需要保证数据正确到达,有时不需要等等各类情况),归根揭底的原因是网络硬件设备并不可靠,传输速度并不够快,所以需要协议来弥补这些缺陷,可以简单认为是硬件不够完美。

其间每一层都肩负着各自的任务,用 c++ 的话说,它们是继承关系,下面是父类上面是子类,一顺继承下去,各自又包含各自的方法和属性。

具体可配合RFC手册,在 wireshark 中抓一个包来查看,本文只是为了建立这样一种概念。

TDI在哪?

1.png

本文所讲的 TDI 全称为 Transport Driver Interface,位于网络模型中的传输层,其分为3个部分,分别是 TDI客户驱动,TDI接口,以及TDI传输驱动。

TDI接口是在联系TDI客户驱动和TDI传输驱动时所构建的一套函数,数据及宏定义。

  • AFD.sys,NETBT.sys 和 Http.sys都是TDI 客户驱动。
  • TCPIP.sys,NWLINK.sys和TCPIP6.sys都是TDI传输驱动。
  • TDI.sys 一般视为为 TDI 接口驱动。

虽然TDI客户驱动一般在TDI传输驱动上层,但也有些TDI客户驱动在网络栈中逻辑上是和TDI传输驱动在同一层甚至在TDI传输驱动下层。

另外由于TDI层较为接近应用层,在TDI层过滤更为容易获得应用程序相关信息。

TDI相关驱动开发

在做TDI相关开发时,一般分为以下两类

  • 调用 TDI 接口,在内核模式下进行网络编程
  • 针对指定传输层协议做网络流量过滤

Windows Vista 起,微软为以上两大用途都提供了新的解决方案。

本文要说明的内容便是 针对指定传输层协议做网络流量过滤 这一种使用方式。

TCP过滤--附加设备

要过滤 "TCP" 协议数据,需要附加到 \Device\TCP 所处的设备栈。
其在 Windows Vista 之前由 "tcpip.sys" 创建,
而之后的版本中则由 "tdx.sys" 创建。
TDX是微软提供的一种妥协方案,旨在为旧TDI驱动提供兼容。
2.png
笔者的电脑使用的win10,可以看到此时该设备由 tdx 创建。
当然这些都不是重点,在附加的时候并不需要这个设备由哪个驱动创建。

既然是传统过滤驱动,要做的事情也很简单

  1. 打开目标设备
  2. 创建过滤设备附加到目标设备的设备栈

具体可以参考开源项目 tdifw

TCP过滤--IRP请求

由于这类驱动中除了过滤用的设备,还有驱动本身和应用层通信的设备,所以要在派遣函数中分别处理。

通常比较关注的是 MajorFunction IRP_MJ_INTERNAL_DEVICE_CONTROL 的请求,
MinorFunction 包含

TDI_ACCEPT
TDI_LISTEN
TDI_CONNECT
TDI_SEND
TDI_RECEIVE
TDI_DISCONNECT
...

可以过滤诸如 连接,收发等操作。

在 IrpSp->Parameters 中存放着一个相关联的结构,通过该结构就能进一步提取信息,以此决定接下来的操作(例如禁止目标访问网络等),
可以挂起这个请求,也可以完成掉,又或者是继续下发,这点根据实际需求判断即可,在写法上,和其他传统过滤驱动并无太大的区别。

具体的操作说明可到MSDN中查看。

最后值得注意的是
过滤驱动最好不要卸载,不然很容易BSOD,这是由于无法判断(或者很难判断)是否还存在某线程位于当前驱动的派遣函数中

总结

本文概括TDI过滤驱动的基础实现及相关知识。