用c#研发网络防火墙技术分析_c#应用

2008-02-23 05:44:15来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

  N-Byte网络守望者是一款单机版网络安全工具,简言之,就是个用.NET研发的个人版防火墙。在N-Byte网络守望者1.0版的研发中,使用了NDIS Hook Driver技术来实现网络封包过滤功能,这使N-Byte网络守望者能够在网络层过滤网络封包,从而实现强大的功能。

  由于软件的主程式是用C#写的,C#中没有提供具备类似DeviceIoControl函数功能的驱动设备控制函数,而NDIS Hook Driver技术下的驱动程式是用DDK下的C语言写的,为了能够实现主程式对驱动程式的控制和相互通信,采用了以下设计方案:

  在以上方案中,需要一个负责主程式和NDIS Hook Driver驱动程式通信和控制的模块DriverDll.dll,并用C#编写的一个封装驱动程式中封包信息的模块,能够发送这个驱动程式信息到主程式,主程式可识别并操作模块中的数据类型。

  在.NET应用程式使用驱动程式的问题上,面临着两个问题:

  1.怎样实现.NET应用程式控制驱动程式的功能?

  2.怎样从驱动程式向.NET应用程式传递非托管的数据类型?

  以下是我们就这些问题的周详解决方法:

  怎样实现.NET应用程式控制驱动程式的功能?

  使用托管C 编写的DriverDll.dll来实现对驱动程式的直接控制,而主程式通过调用其中的方法来实现对驱动程式的间接控制。比如在NByte.h文档中定义了START_IP_HOOK常数用来作为传给驱动程式用来开启驱动程式封包过滤功能的参数,下面在托管C 模块中定义了IoCtrl托管类并定义了下面的向缓冲区写入参数的方法:

//向缓冲区写入数据。

DWORD WriteIo(DWORD code,PVOID buffer,DWORD count)

{

if(hDriverHandle == NULL)

return ERROR_DRIVER_HANDLE;

DWORD bytesReturned;

BOOL returnCode = DeviceIoControl(hDriverHandle,

code,

buffer,

count,

NULL,

0,

&bytesReturned,

NULL);

if(!returnCode)

return ERROR_IO_CTRL;

return SUCCESS;

}

  当然直接使用这个方法不太方便,所以定义一个公有函数,用来提供给主程式调用:

//开始进行封包过滤

bool StartIpHook()

{
 return (WriteIo(START_IP_HOOK, NULL, 0)==SUCCESS);
}

  这样,只要在主程式中声明IoCtrl的对象ic,就能够通过ic.StartIpHook()就能够实现对驱动程式过滤功能的开启,用同样的方法也能够实现对驱动程式进行其他操作,比如添加、修改封包过滤规则等。

  怎样从驱动程式向.NET应用程式传递非托管的数据类型?

  为了能够输出安全日志,必须让主程式获得驱动程式中的封包信息。使用信号量机制能够很方便的实现驱动程式和非托管代码间的信息传递,那么对托管代码呢?这需要向.NET应用程式传递非托管的数据类型ACCESS_INFO。在NByte.h中,是这样定义这个ACCESS_INFO结构的:

typedef struct _ACCESS_INFO

{
 USHORT protocol;
 ULONG sourceIp;
 ULONG destinationIp;
 USHORT sourcePort;
 USHORT destinationPort;
}ACCESS_INFO;

  显然,直接传递非托管数据类型是不能够的,需要转换一下。首先,在IoCtrl类中定义了几个要传递的封包信息参数:

public __gc class IoCtrl
{
 public:
  USHORT protocol; //网际协议类型
  ULONG sourceIp; //源IP地址
  ULONG destinationIp; //目的IP地址
  USHORT sourcePort; //源端口
  USHORT destinationPort; //目的端口
  ………………
}

  然后,在GetAccessInfo()函数中来给这些参数赋值:

void GetAccessInfo()
{
 ACCESS_INFO ai;
 bool result=(ReadIo(GET_INFO,&ai,sizeof(ai))==SUCCESS);
 this->protocol=ai.protocol;
 this->sourceIp=ai.sourceIp;
 this->destinationIp=ai.destinationIp;
 this->sourcePort=ai.sourcePort;
 this->destinationPort=ai.destinationPort;
}

  既然在IoCtrl类中获得了这些信息,但是需要把他们封装成主程式容易处理的数据类型,这样,用C#实现了InfoEvent类用来封装这些信息:

//本类封装了数据包的周详信息,能够通过事件实现对他的模块间传递。

public class InfoEvent:EventArgs
{
 string sInfo; //用来存放输出信息的私有成员
 public int pLength; //CommonFunction.sPort数组的长度
 public ushort protocol; //网络通信协议类型
 public uint sourceIp; //数据包的源IP
 public uint destinationIp; //数据包的目的IP
 public ushort sourcePort; //数据包的源端口
 public ushort destinationPort; //数据包的目的端口
 ………………………………
}

  下面在用托管C 实现的InfoProvider驱动程式信息提供者类中把个InfoEvent类的对象传递给主程式,需要使用一个委托生成一个事件:

//声明委托事件,用来向主程式传递数据。

__delegate void DriverInfo(Object* sender, InfoEvent* e);

//声明响应事件函数。

__event DriverInfo* OnDriverInfo;

  然后在InfoProvider驱动程式信息提供者类中定义一个方法,在主程式中以线程的方式运行这个方法,在这个方法中使用了事件函数OnDriverInfo:

//用来获得驱动程式信息的进程,在主程式中将开启该进程。

void GetInfoThreadProc()
{
 this->hEvent=OpenEvent(SYNCHRONIZE,FALSE,"NBEvent");
 if(!ic->GetDriverHandle())
 {
  return;
 }

 while(true)
 {
  f(!hEvent)
  ExitThread(0);
  WaitForSingleObject(this->hEvent,INFINITE);
  nPackets ;
  ic->GetAccessInfo();
  ic->ResetEvent();
  //定义一个主程式能够识别的对象,通过OnDriverInfo传给主程式。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 利用c#实现分布式数据库查询_c#应用

下一篇: 数据结构和算法(c#实现)系列-----前言_c#教程