|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
您现在的位置: ChinaBeta.cn 中文IT资讯 >> 网盟学院 >> 编程类 >> 其它编程程序 >> 网管技术正文
推荐网管技术让我穿过那道"墙"! 畅游网络应…推荐网管技术主动防御!瑞星杀毒2008抢先评…
推荐网管技术速度超快 Discuz! 6.0.0试用手…推荐网管技术奇虎举证:各杀毒软件均报CNNIC…
推荐网管技术Google Earth 4.2加入繁体中文…推荐网管技术专业防护!瑞星防火墙2008测试…
推荐网管技术挂载RAR文件 从认识到爱上WinM…推荐网管技术让你冲浪随心所欲 如何访问被封…
推荐网管技术轻装上阵!江民杀毒软件2008速…推荐网管技术VMware Fusion苹果版全程图解(…
推荐网管技术VMware Fusion苹果版全程图解(…推荐网管技术从菜鸟出发!征服高清详细评测全…
推荐网管技术VS2008和ASP.NET 3.5使用之初体…推荐网管技术[多图]Ubuntu 7.04 初体验
推荐网管技术东风吹战鼓擂 下载软件你选谁?推荐网管技术若隐若现 Windows XP DirectX …
推荐网管技术GPRS上网全攻略推荐网管技术主流杀毒软件Vista兼容性横评
推荐网管技术基于IRF的网络管理和业务管理解…推荐网管技术83个美丽的Wordpress主题
推荐网管技术软交换网络中的关键路由技术详…推荐网管技术不只是换肤?Windows Mobile 6 …
推荐网管技术css教程–十步学会用css建站(全…推荐网管技术巧妙设置路由 预防网络频繁掉线
推荐网管技术打造网络管理七大绝技推荐网管技术CorelDRAW X3 Service Pack 2 …
推荐网管技术重温经典:回归 Live Messenger…推荐网管技术Oracle数据库补丁分类、安装及…
NAT在NDIS中间层驱动中的实现
Www.ChinaBeta.Cn 更新时间:2006-6-19 阅读次数:

【ChinaBeta.Cn 网盟学院】

4.3 对收到的数据包的过滤和转发
INT
PtReceivePacket(
    IN    NDIS_HANDLE            ProtocolBindingContext,
    IN    PNDIS_PACKET        Packet
    )
{
    ......

    
    PUCHAR       pPacketContent;
        PUCHAR       pBuf;
        UINT         BufLength;
        MDL          * pNext;
        UINT         i,j;
    BOOLEAN      transflag = FALSE;
    PNDIS_BUFFER MyBuffer;
    PIP_Header   pIPHeader;
    
    ......

    NdisDprAllocatePacket(&Status,
                           &MyPacket,
                           pAdapt->RecvPacketPoolHandle);

    if(Status == NDIS_STATUS_SUCCESS)
    {
        //add by thinking 06.6.3
        //把数据包内容从Packet拷贝到pPacketContent
        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;
        }
        if(pPacketContent[12] == 8 &&  pPacketContent[13] == 0 )  //is ip packet
        {
            ULONG netip;
            pIPHeader = (PIP_Header)(pPacketContent+14);
            netip = pIPHeader->ipSource & 0x00ffffff;
            //对收到的数据包进行过滤,只转发需要转发的包
            if(pIPHeader->ipDestination == first->inip && netip != first->reip)
            //如果目的地址是本主机,并且源IP不是本网段地址,则转发给内网主机
            {
                DbgPrint("\nTransInPacket...\n");
                for(j=0;j<=i;j++)
                    DbgPrint("%x ",pPacketContent[j]);
                //修改发给内网的数据包头
                transflag = TransIn(pPacketContent);
            }
            else if(pIPHeader->ipDestination != 0xffffffff &&
                (pIPHeader->ipDestination & 0x00ffffff) != first->reip &&
                netip == first->reip)
            //如果目的地址不是广播地址,而且是外网地址,源地址是内网IP,则转发给外网
            {
                DbgPrint("\nTransOutPacket...\n");
                for(j=0;j<=i;j++)
                    DbgPrint("%x ",pPacketContent[j]);
                //修改发给外网的数据包头
                transflag = TransOut(pPacketContent);
            }
        }

        if(!transflag)
        {
               //按照原来的方式往上提交    
               ......
        }
        else
        {
            //转发的一段关键代码
            NdisAllocateBuffer(&Status,&MyBuffer,pAdapt->SendPacketPoolHandle,pPacketContent,i);
            NdisChainBufferAtFront(MyPacket, MyBuffer);
            Resvd =(PRSVD)(MyPacket->ProtocolReserved);
            Resvd->OriginalPkt = MyPacket;
                MyPacket->Private.Head->Next = NULL;
            MyPacket->Private.Tail = NULL;
            NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);
            NdisReturnPackets(&Packet, 1);
            NdisSend(&Status,pAdapt->BindingHandle,MyPacket);
            if(Status != NDIS_STATUS_PENDING)
            {
                NdisUnchainBufferAtFront(MyPacket ,&MyBuffer); //从MyPacket中解除buffer
                NdisQueryBufferSafe(MyBuffer, &pPacketContent, &BufLength,32 );
                if(pPacketContent != NULL)
                    NdisFreeMemory(pPacketContent,BufLength, 0);
                NdisFreeBuffer(MyBuffer);
            }
            return 0;
        }
    ......
}

4.4 数据包头的修改
    根据具体情况修改数据包的IP包头,TCP包头,或者UDP包头,并且在修改的同时继续维护转发表,下面只给出TransIn的代码,TransOut与其原理相同.
BOOLEAN TransIn(PUCHAR pPacketContent) 
{
    PortNode * inmap;
    PIP_Header pIPHeader = (PIP_Header)(pPacketContent+14);
    USHORT iphdrlen = (pIPHeader->iphVerLen & 0x0f) * sizeof(ULONG);
    UCHAR checkbuff[2000] = {0};

    if(pIPHeader->ipProtocol == 6)
    {
        PTCP_Header pTCPHeader;
        USHORT tcphdrlen;
        pTCPHeader = (PTCP_Header)(pPacketContent+14 + iphdrlen);
        //tcphdrlen = ((pTCPHeader->dataoffset & 0xf0) >> 4) * sizeof(ULONG);
        tcphdrlen = htons(pIPHeader->ipLength) - iphdrlen;
        inmap = InMapping(pIPHeader->ipSource,pTCPHeader->sourcePort,
            pTCPHeader->destinationPort);
        if(inmap == NULL)
            return FALSE;

        //修改目的地址和目的端口,校验和
        pIPHeader->ipDestination = inmap->inip;
        pTCPHeader->destinationPort = inmap->inport;
        pIPHeader->ipChecksum = 0;
        pTCPHeader->checksum = 0;

        //填充TCP伪首部
        psdhdr.saddr = pIPHeader->ipSource;
        psdhdr.daddr = pIPHeader->ipDestination;
        psdhdr.len = htons(tcphdrlen);
        psdhdr.mbz = 0;
        psdhdr.proto = 6;

        //计算TCP首部校验和
        NdisMoveMemory(checkbuff,&psdhdr,sizeof(psdhdr));
        NdisMoveMemory(checkbuff+sizeof(psdhdr),pTCPHeader,tcphdrlen);
        pTCPHeader->checksum = CheckSum((USHORT *)checkbuff,sizeof(psdhdr)+tcphdrlen);

        //计算IP首部校验和
        pIPHeader->ipChecksum = CheckSum((USHORT *)pIPHeader,iphdrlen);

        return TRUE;
    }
    else if(pIPHeader->ipProtocol == 17)
    {
        PUDP_Header pUDPHeader;
        USHORT udplen;
        pUDPHeader = (PUDP_Header)(pPacketContent+14 + iphdrlen);
        udplen = htons(pUDPHeader->len);
        inmap = InMapping(pIPHeader->ipSource,pUDPHeader->sourcePort,
            pUDPHeader->destinationPort);
        if(inmap == NULL)
            return FALSE;

        //修改目的地址和目的端口,校验和
        pIPHeader->ipDestination = inmap->inip;
        pUDPHeader->destinationPort = inmap->inport;
        pIPHeader->ipChecksum = 0;
        pUDPHeader->checksum = 0;

        //填充UDP伪首部
        psdhdr.saddr = pIPHeader->ipSource;
        psdhdr.daddr = pIPHeader->ipDestination;
        psdhdr.len = pUDPHeader->len;
        psdhdr.mbz = 0;
        psdhdr.proto = 17;

        //计算UDP校验和,包括所有UDP数据
        NdisMoveMemory(checkbuff,&psdhdr,sizeof(psdhdr));
        NdisMoveMemory(checkbuff+sizeof(psdhdr),pUDPHeader,udplen);
        pUDPHeader->checksum = CheckSum((USHORT *)checkbuff,sizeof(psdhdr)+udplen);

        //计算IP首部校验和
        pIPHeader->ipChecksum = CheckSum((USHORT *)pIPHeader,iphdrlen);

        return TRUE;
    }
    else
        return FALSE;
}

5.小结
    本文简单介绍了传统NAT在中间层驱动中的实现,很多地方都可以进行改进.例如:校验和的计算可以采用差量计算法以减少计算延迟;转发表的维护可以采用树型结构(而不是本文中的链表)以减少转发表的查找时间;定时对转发表进行清理,释放长时间不用的端口,以节约系统资源;构建ARP机制,并动态维护相关主机的MAC地址;通过共享内存或者修改驱动对象的DispatchTable与用户层进行通信,从而动态调整驱动功能.

参考文献:
    RFC1631: The IP Network Address Translator (NAT)
    RFC2663: IP Network Address Translator (NAT) Terminology and Considerations
       Addylee "基于PassThru的NDIS中间层驱动程序扩展" http://www.xfocus.net/articles/200605/865.html
       Jesús O "开发Windows 2000/XP下的防火墙" http://www.vckbase.com/document/viewdoc/?id=1067 

上一页  [1] [2] 

Google

(责任编辑:hahack)

发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
热门文章 相关报道
普通网管技术 [软件应用]凤凰涅槃 驱动精灵2008归来 (01-03)最新网管技术
普通网管技术 [ASP|ASP.NET]为ASP.NET MVC框架添加AJAX支持 (01-02)最新网管技术
普通网管技术 [JSP|JAVA]从Java到Ruby:献给引路人的策略 (01-02)最新网管技术
普通网管技术 [PHP]PHP多文件上传实例 (01-02)最新网管技术
普通网管技术 [其它编程程序]QQ 静态截图完善实现之改造 CRec… (01-02)最新网管技术
普通网管技术 [其它编程程序]C++运算符重载转换运算符 (01-02)最新网管技术
普通网管技术 [其它编程程序]详细解析C++编写的ATM自动取款机… (01-02)最新网管技术
普通网管技术 [其它编程程序]C++中用vectors改进内存的再分配 (01-02)最新网管技术
普通网管技术 [其它编程程序]C++中的虚函数((((virtual funct… (01-02)最新网管技术
普通网管技术 [其它编程程序]C++中用函数模板实现和优化抽象操… (01-02)最新网管技术
没有相关网管技术
  网友评论内容:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
I D *
邮 箱
主 页
评 分 1分 2分 3分 4分 5分
评 论

关于我们  中国·国家信息产业部{粤ICP备06006652号}{陇ICP备06002562号}
版权所有:『AK网盟基地』站长:Hahack | QQ:80505955 | E-mail:Hahack@Gmail.com
Copyright (C) 2005-2007  akhack.org|chinabeta.cn All Rights Reserved