WEB开发网
开发学院网络安全防火墙 基于IMD的包过滤防火墙原理与实现 阅读

基于IMD的包过滤防火墙原理与实现

 2008-12-18 12:18:47 来源:WEB开发网   
核心提示: 想想我们要实现的包过滤的功能,我们只需要在中间层接收到数据报的时候进行规则判断就可以了,基于IMD的包过滤防火墙原理与实现(3),而在passthru中,接收数据报是用protocol.c文件中的PtReceive和PtReceivePacket这两个函数来实现的,释放pPacketCon

想想我们要实现的包过滤的功能,我们只需要在中间层接收到数据报的时候进行规则判断就可以了,而在passthru中,接收数据报是用protocol.c文件中的PtReceive和PtReceivePacket这两个函数来实现的。根据微软的解释,微软建议接收包用PtReceivePacket函数,因为可以得到更高的效率,然而,为了向下兼容,也保留了PtReceive函数给老的网卡使用。所以,在一块网卡上,只可能有一个函数在工作,这要取决于你的网卡型号了。巧的是,我的两台机器的网卡应用的函数正巧不一样。同样是IBM的机器,一台P4 1.5G的机器的网卡是Realtek RTL8139(A) PCI Fast Ethernet Adapter,另外一台P4 2.0G的机器的网卡是Intel(R) PRO/100 VE Network Connection,其中Realtek网卡用的是PtReceive来接包,而Intel的网卡是用PtReceivePacket来接包。

现在我们知道了哪个函数负责接收数据报,那么我们就可以对这个函数进行修改了。从兼容和通用性考虑,我们需要对PtReceive和PtReceivePacket函数进行修改,其中加上我们需要判断的规则进行过滤,下面就贴详细的代码了。

四、部分演示代码

我们的目的是在调用接受数据报函数的时候能执行我们的过滤代码,所以,我们要在函数代码中添加我们自己的代码,下面用过滤特定协议类型的数据报来做演示。

首先修改PtReceive,看一下protocol.c文件中函数的代码,代码中用NdisGetReceivedPacket函数得到一个PNDIS_PACKET的结构Packet,数据报内容就存放在这个结构中的链表内。我们定义一个PUCHAR结构的pPacketContent,然后用下面的代码获得整个数据报的内容:

  //---------------------------------------------
   int PacketSize;
   PUCHAR pPacketContent;
   PUCHAR pBuf;
   UINT BufLength;
   MDL * pNext;
   UINT i;
  //把数据包内容从Packet拷贝到pPacketContent
  NdisQueryPacket( Packet,NULL,NULL,NULL,&PacketSize);
  Status= NdisAllocateMemory( &pPacketContent, 2000,
  0,HighestAcceptableMax);
  if (Status!=NDIS_STATUS_SUCCESS ) return Status;
  NdisZeroMemory (pPacketContent, 2000);
  NdisQueryBufferSafe(Packet->Private.Head, &pBuf, &BufLength, 32 );
  NdisMoveMemory(pPacketContent, pBuf, BufLength);
  i = BufLength;
  pNext = Packet->Private.Head;
  for(;;)
  {
  if(pNext == Packet->Private.Tail)
  break;
  pNext = pNext->Next; //指针后移
  if(pNext == NULL)
  break;
  NdisQueryBufferSafe(pNext,&pBuf,&BufLength,32);
  NdisMoveMemory(pPacketContent+i,pBuf,BufLength);
  i+=BufLength;
   }
   //数据拷贝完毕
   //-------------------------------------------------
  现在,我们已经在PtReceive函数中得到了数据报的内容,存放在pPacketContent中,数据报的格式你可以去查书。通常,在以太网中,得到的数据报大致是如下结构,以太帧头14个字节,放在pPacketContent[0]到pPacketContent[13]中,其中前六个字节是目的MAC地址,然后六个字节源MAC地址,然后两个字节是协议类型,通常的协议类型有0x08 0x00 ->IP,0x08 0x06 ->ARP,0x08 0x35 ->RARP,所以,可以通过pPacketContent[12]和pPacketContent[13]来判断协议类型。如果是IP包,然后pPacketContent中存放的是IP头,根据IP头的格式,可以得到第23个字节pPacketContent[23]表示传输层协议:1 ->ICMP,2 ->IGMP,6 ->TCP,17 ->UDP,剩下的就是数据报内容了。因为我们只是做演示,所以只要知道这几个标志性的就好了,其他的你可以根据你的需要扩展。我们通过pPacketContent中的内容可以做些规则,比如过滤ICMP包,我们只要比较pPacketContent[12]和pPacketContent[13]还有pPacketContent[23]这三个标志位就可以了,如果不是ICMP包,那么不做任何工作,如果匹配了,那就返回一个NDIS_STATUS_NOT_ACCEPTED,将包丢弃,释放pPacketContent,就可以过滤ICMP包了,下面就是过滤规则的代码。  //---------------------------------------------------------
  //规则标志位(1表示过滤,0表示放行,你可以通过改这个数值来配置规则)
  UINT ICMP = 1; //ICMP数据报规则
  UINT IGMP = 0; //IGMP数据报规则
  UINT TCP = 0; //TCP数据报规则
  UINT UDP = 0; //UDP数据报规则
  //规则判断
   if (ICMP == 1)
   {
   if(((char *)pPacketContent)[12] == 8 &&
   ((char *)pPacketContent)[13] == 0 &&
   ((char *)pPacketContent)[23] == 1)
   {
   DbgPrint("ICMP被拦截!n");
   NdisFreeMemory(pPacketContent, 2000, 0);
   return NDIS_STATUS_NOT_ACCEPTED;
   }
   }
  if (IGMP == 1)
   {
   if(((char *)pPacketContent)[12] == 8 &&
   ((char *)pPacketContent)[13] == 0 &&
   ((char *)pPacketContent)[23] == 2)
   {
   DbgPrint("IGMP被拦截!n");
   NdisFreeMemory(pPacketContent, 2000, 0);
   return NDIS_STATUS_NOT_ACCEPTED;
   }
   }
  if (TCP == 1)
   {
  if(((char *)pPacketContent)[12] == 8 &&
   ((char *)pPacketContent)[13] == 0 &&
  ((char *)pPacketContent)[23] == 6)
   {
   DbgPrint("TCP被拦截!n");
   NdisFreeMemory(pPacketContent, 2000, 0);
  return ND

上一页  1 2 3 

Tags:基于 IMD 过滤

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接