电脑上有两张网卡,自己实现监听到连接内网上那张网卡的数据包并抓取到。也分析出协议、数据等信息。但如何修改抓取包中的源IP地址,并把它转发到连接外网网卡上去啊?各位大虾给点建议提示撤

解决方案 »

  1.   

    winpcap 第三方驱动可以 如果你不做协议底层方面的 一般可以用HOOK
      

  2.   

    防火墙,传说中的防火墙!
    你是要编个缓冲服务器的程序么?
    这个东西,很商业的,但我敢保证,中国的CHACHE服务器水平全球领先。
    不过,请你先告诉我。
    1.你的两块网卡,是分别接在两个路由上么?
    2,你的两块网卡,分别绑定的是什么网关!
    这本身就是一个很细的问题。不是三言两语能说清的。
    况且,各种应用的包头也不一样
    现在假定,你所有的配置都是最理想的。
    还存在这的问题。
    你是想直接用VC自己开发一个抓包,读包,发包的类么?
    或是你想利用WINCAP二次开发?
    或者是你用SINNFER类的软件抓包,二次处理用用VC转发?
    请你说清楚,我才能知道你要的什么。
      

  3.   

    其实这两张网卡一张接在内网电脑上,另一张接在路由上。只是想把内网电脑上的所有数据包抓下来。然后修改IP包上的源IP地址,转发到外网网卡上。实现NAT功能。
    跟Windows服务器平台下的“路由与远程访问”功能一样。
    利用winsock,使内网网卡处于混合工作模式。可以抓到包的(UDP/TCP)。就是自己不知道怎么修改IP包中的源IP地址然后转发到外网网卡上。
      

  4.   

    还有一点补充(针对liyan提出的问题)。自己想做一个抓包,读包,发包的类。
      

  5.   

    用wincap很容易做到你说的功能!
      

  6.   

    这个问题我这两天也关心过,这个要使用原始套接字,但是XP已经拒绝发送这种修改后的套接字,所以只能使用winpcap 来开发
      

  7.   

    本帖最后由 VisualEleven 于 2010-09-19 21:12:34 编辑
      

  8.   

    本帖最后由 VisualEleven 于 2010-09-19 21:13:19 编辑
      

  9.   

     //读取第一个SN,SN1的(IP,Port),并给其发0号包
      if(getSNfromHostCache(fp,snIP[0],snPort[0])==0)
      {
       printf("[error]there is no SN in HostCache.txt!\n");
       return 0;
      }
      /*
      int sendNCPtoSNandRecvNCP(unsigned long int ip_SN,
       unsigned short int port_SN,
       char version,
       char dowhat,
       unsigned long int ip,
       unsigned short int port) 
      */ 
      ncp_send.dowhat=0; 
      ncp_send.ip=0; 
      ncp_send.port=0;  
      while(sendNCPtoSNandRecvNCP(snIP[0],snPort[0],ncp_send)==0)
      {
       if(getSNfromHostCache(fp,snIP[0],snPort[0])==0)
       {
        printf("[error]there is no more SN in HostCache.txt!\n");
        //此时应该从中心节点获取更新的SN列表
        //......
        printf("[error]check failed temporarily");
        return 0;
       }
      } 
      long ft=ftell(fp);
      in_addr_tmp.S_un.S_addr=snIP[0]; 
      printf("[info]SN1 ip=%s\tport=%d\n",inet_ntoa(in_addr_tmp),snPort[0]);
      //对比返回的(ip,port) ip_return port_return
      unsigned long int ip_return=((NCP *)buff)->ip;
      unsigned short int port_return=((NCP *)buff)->port;
      if(myPriIp==ip_return && myPriPort==port_return)
      {
       printf("[Reslut]public net\n"); 
       myNetType=0;
       ncp_send.dowhat=9; 
       ncp_send.ip=myPubIp=myPriIp; 
       ncp_send.port=myPubPort=myPriPort; 
       broadcastNatCheckResult(ncp_send);
       return 0;
      }
      //再读取一个SN,SN2的(IP,Port)
      int checkTime=N_CheckTime;
      while(checkTime>0 && !feof(fp))
      {
       if(getSNfromHostCache(fp,snIP[1],snPort[1])==0)
       {
        printf("[error]there is no more SN in HostCache.txt!\n");
        break;
       }  
       ncp_send.dowhat=1; 
       ncp_send.ip=snIP[1]; 
       ncp_send.port=snPort[1]; 
       if(sendNCPtoSNandRecvNCP(snIP[0],snPort[0],ncp_send)==1)
       {  
        printf("[Reslut]full cone nat\n");
        myNetType=1;
        ncp_send.dowhat=10; 
        ncp_send.ip=myPriIp; 
        ncp_send.port=myPriPort;
        myPubIp=ip_return;
        myPubPort=port_return;
        broadcastNatCheckResult(ncp_send);
        return 0;
       }  
       checkTime--;
      }
      printf("[Reslut]not full cone nat, checking is continued.\n");
      in_addr_tmp.S_un.S_addr=snIP[1]; 
      printf("[info]SN2 ip=%s\tport=%d\n",inet_ntoa(in_addr_tmp),snPort[1]);  
      //在hostcache中的SN1下再找一个SN3,给他发送2号包,让他返回client的ip和port
      fseek(fp,ft,0);
      if(getSNfromHostCache(fp,snIP[1],snPort[1])==0)
      {
       printf("[error]there is no SN in HostCache.txt!\n");
       return 0;
      }  
      ncp_send.dowhat=2; 
      ncp_send.ip=0; 
      ncp_send.port=0;  
      while(sendNCPtoSNandRecvNCP(snIP[1],snPort[1],ncp_send)==0)
      {
       if(getSNfromHostCache(fp,snIP[1],snPort[1])==0)
       {
        printf("[error]there is no more SN in HostCache.txt!\n");
        //此时应该从中心节点获取更新的SN列表
        //......
        printf("[error]check failed temporarily");
        return 0;
       }
      } 
      in_addr_tmp.S_un.S_addr=snIP[1]; 
      printf("[info]SN3 ip=%s\tport=%d\n",inet_ntoa(in_addr_tmp),snPort[1]);
      //对比返回的(ip,port) ip_return port_return
      unsigned long int ip_return1=((NCP *)buff)->ip;
      unsigned short int port_return1=((NCP *)buff)->port;
      if(ip_return1!=ip_return || port_return1!=port_return)
      {
       printf("[Reslut]symmetric nat\n");
       myNetType=2;
       ncp_send.dowhat=11; 
       ncp_send.ip=myPriIp; 
       ncp_send.port=myPriPort; 
       broadcastNatCheckResult(ncp_send);
       return 0;
      }  
      ncp_send.dowhat=3; 
      ncp_send.ip=0; 
      ncp_send.port=0;  
      if(sendNCPtoSNandRecvNCP(snIP[0],snPort[0],ncp_send)==1)
      {
       printf("[Reslut]Restricted Cone nat\n");
       myNetType=3;
       ncp_send.dowhat=12; 
       ncp_send.ip=myPriIp; 
       ncp_send.port=myPriPort; 
       myPubIp=ip_return;
       myPubPort=port_return;
       broadcastNatCheckResult(ncp_send);
       return 0;
      }
      printf("[Reslut]Port Restricted Cone nat\n");
      myNetType=4;
      ncp_send.dowhat=13; 
      ncp_send.ip=myPriIp; 
      ncp_send.port=myPriPort;
      myPubIp=ip_return;
      myPubPort=port_return;
      broadcastNatCheckResult(ncp_send);
      //以上检测网络类型结束,下面开始与某好友通讯
      printf("do you want to talk with someone? [Y]yes [N]no\n");
      scanf("%c",&ch);
      if(ch!='Y' && ch!='y')
       return 0;
      printf("which friend would you want to talk with? Input his id:\n");
      scanf("%d",&friendID);
      //从SN1获取friend网络类型列表
      ncp_send.dowhat=14; 
      ncp_send.ip=0; 
      ncp_send.port=0;
      ncp_send.id=friendID;
      if(sendNCPtoSNandRecvNIRP(snIP[0],snPort[0],ncp_send)==0)
      {  
       printf("[error]查询好友网络信息失败!\n");
       return 0;
      }
      switch(friendNetType)
      {
      case 9:
       break;
      case 10:
       break;
      case 11:
       break;
      case 12:
       break;
      case 13:
       break;
      default:
       break;
      }
     }
     ////////////////////////////////////////////////////////////////////
     //服务端程序入口
     /////////////////////////////////////////////////////////////////////
     else if(strcmp(argv[1],"-s")==0)
     {
      //创建另一个套接字
      SOCKET sServer1;
      if( (sServer1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
      {
       printf("获取SOCKET号失败!!!\n");
       return 0;
      }
      //绑定套接字和本机地址和端口  
      sn1_addr.sin_family=AF_INET;
      sn1_addr.sin_port=htons(PORT_SERVER_NATCHECK_1); 
      sn1_addr.sin_addr.s_addr =INADDR_ANY ;//inet_addr(getownIP());  //
      if(bind(sServer1, (struct sockaddr*)&sn1_addr, sizeof(sn1_addr)) < 0 )
      {
       printf("不能将服务器地址捆绑到SOCKET号上!!!\n");
       closesocket(sServer1); 
       return 0;
      }
      //////////////////
      //  循环队列natCheckRequestQueue初始化
      for(i=0;i<N_NatCheckRequestQueue-1;i++)
      {
       natCheckRequestQueue[i].next= & natCheckRequestQueue[i+1];
      }
      natCheckRequestQueue[N_NatCheckRequestQueue-1].next
       = & natCheckRequestQueue[0];
      h_NatCheckRequestQueue = & natCheckRequestQueue[0];
      t_NatCheckRequestQueue = & natCheckRequestQueue[0];
      //////////////////
      //  启动接受请求的服务线程 
      //  入口函数为:ThreadFunction_sn_get
      //  判断队列是否满,不满的条件下,先修改t,再写进t指向的单元
      //HANDLE thread_sn_get = (HANDLE)_beginthread(ThreadFunction_sn_get,0,NULL); 
      HANDLE thread_sn_get = (HANDLE)_beginthreadex(0,0,&ThreadFunction_sn_get,0,0,NULL);
      

  10.   


    我自己做了个比wincap好用的 底层接口,再回头看wincap简直没法用噢。
      

  11.   

    楼上的hst0a001能否共享给我参考呀。
      

  12.   

    winpcap是用来监听的,无法拦载,所以用winpcap是不能实现修改源IP的。只能自己开发驱动了
      

  13.   

    建议:
    用ndis驱动。效率高,并且不经过系统,所以不会影响到正常的协议栈。
    转发时注意网卡的顺序。
    如果需要NAT的话,自己还需维护映射表。以及校验和的换算。这个是最关键也是最复杂的地方!
      

  14.   

    这下麻烦大了。一直对这个NDIS不太懂。楼上myqoo大大能详细说一下维护映射表,以及校验和的换算方面的知识吗?因为我正是要做NAT功能。
      

  15.   

    要是利用NDIS开发驱动出来,转发时怎么选择网卡呢?面临实在有太多的问题了。各位网络达人出来发达一下自己的高见撤。
      

  16.   

    NAT属于ndis的中间层驱动,ddk中有个passsthru驱动的例子,在此基础上扩展即可。
    转发选择网卡不复杂,每个网卡都有个句柄,选择相应的收发就可以。计算校验和也不复杂。关键是NAT的算法比较复杂,因为多个内网ip共享一个外网ip,所以需要维护每个数据包的端口,来记录是哪个内网的ip。现在大多都是Cone型的NAT。不同类型的NAT算法各不相同。但必须遵循标准规则,否则P2P程序就无法使用了。
      

  17.   


    不给,坚决不给,我2007年一年,几乎没睡过安稳觉搞这东西,平均NDIS一天死机20次以上。另外myqoo正解,尽管NDIS已经玩烂的东西,但我发现真正搞透的没几个噢,不然wincap能坚持这么久一枝独秀?ndis 的Packet中两个关键的Struct,我是从英国网站发现,这玩意还是老外搞的透噢,国内吹牛皮的人太多了,真正明白的人,少之又少
      

  18.   

    本帖最后由 VisualEleven 于 2010-09-19 21:14:18 编辑
      

  19.   

    ndis驱动很简单啊。ddk中有个叫passthru的东西,我当初看了几天就基本清楚了。还有23L的解包有点复杂了。现在的网卡设备收到的包都是连续的,不用一个一个的连起来。早的时候网卡倒是一段一段的接收,数据放在不同的内存页里面。
      

  20.   

    嗯,虽然自己还不是懂得太多的WDM开发知识。但看起来hst0a001的23代码感觉很健壮。
    要深度发掘hst0a001经验,共享多些出来给我们学习下啊!嘿嘿~~~