好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

pplayer【linux环境下】

pplayer【linux环境下】

pplayer【linux环境下】

【博客园原创】 http://www.cnblogs.com/baiyan/archive/2013/05/10/pplayer.html

pplayer(packet player)是我写的一款小工具,支持主流协议,专门用来测试IPS和防火墙设备,经长时间验证,简单可靠,故发布。

程序的原理很简单,首先加载pcap包中的数据包,保存在内存中,然后在回放环境中回放数据包。

拓扑:

 

原理:

  防火墙的两个网卡和linux pc的两个网卡分别对接形成环路,pplayer程序运行在linux pc中。

  1,加载pcap文件中网路数据包,识别出数据包发送方向(client to server or server to client)

  2,修改数据包内容(源/目的ip地址,校验和)

  3,按顺序发送数据包,同时接收数据包

  4,打印log,提示发送和接收情况,回放完毕。

使用方法:

  pplayer -f  filename  [ -t  time ] | [-m] | [-v  ipversion ] | [-p  portnum ] 

可用参数:

  -f:  必选,参数是pcap文件名。

  -t:  可选,参数是等待接收一个已发送的数据报的时间;如不选默认30(微秒)。

  -m: 可选,理想情况下pcap包中只包含两个ip地址的数据包,但是如果存在第3方或3个以上ip地址,就形成了若干的回放关系。

    默认情况下,只选择数据包数量最多得一对ip进行回放。如需回放其他ip对的数据包,需要使用-m参数,会以ip对为顺序来回放数据包。

  -v: 可选,4或6, 回放IPV4/6数据包, 默认4. 

  -p: 可选,选择只回放指定端口的数据包,例如,指定回访HTTP包, -p 80。

  另外pplayer支持nat环境回放,使用方法见下面配置文件。

举例:

  1,./pplayer -f http.pcap(回放http.pcap的数据包)

  2, ./pplayer -f http.pcap -v 6 (回放http.pcap的数据包,数据包格式是ipv6)

  3,./pplayer -f http.pcap -v 6 -t 50 (回放http.pcap的数据包,数据包格式是ipv6, 每个数据包的等待接收时间设为50微秒)


配置文件:

  配置名是conf,和pplayer程序在同一目录下。

注:冒号后面紧接内容,不能有空格或换行

  1.device1和device2表示linxu pc的两个网卡

  2.device1ip和device2ip表示linux pc的两个网卡的ip地址

  3.device1nat和device2nat是用来支持nat环境回放的。

    例如:设备1的ip是1.1.1.1,设备1处于nat环境,转换后的ip是3.3.3.3;

    设备2的ip是2.2.2.2,设备2处于nat环境,转换后的ip是4.4.4.4;

    如果设备不处于nat环境之中,对应的nat配置项填0.0.0.0(ipv6的填::)

并发/批量回放:

  目前pplayer只支持一次回放一个IP对,一次只能回放一个pcap文件,不支持并发和批量回放这两种功能, 后续我可能会以shell脚本调用pplayer的方式实现

  这两个功能。

核心代码:

  

View Code

 void  LoadPacket ( const   struct  pcap_pkthdr *pcap_hdr, Trace *trace, Flow *flow,  const  u_char * data,  int   pkt_id)
{
    Packet  *pkt =  NULL;
      struct  ether_header *ph =  NULL;
      struct  iphdr *iph =  NULL;
      struct  ip6_hdr *iph6 =  NULL;
      struct  tcphdr *tcph =  NULL;
      struct  udphdr *udph =  NULL;
      if  (flow->pkt_cap ==  0  ) {
        flow ->pkt_cap =  64  ;
        flow ->pkt = calloc( 64 ,  sizeof  (Packet));
    }   else   if  (flow->pkt_num == flow-> pkt_cap) {
        flow ->pkt_cap +=  64  ;
        flow ->pkt = realloc(flow->pkt, (flow->pkt_cap) *  sizeof  (Packet));
    }
    pkt  = &flow->pkt[flow-> pkt_num]; 
    pkt ->id =  pkt_id;
      if  (my_file.ipversion ==  4  ) {
        iph  = ( struct  iphdr *)(data +  ETH_HLEN);
          int  offset = (iph->ihl <<  2 ) +  ETH_HLEN;
        tcph  = ( struct  tcphdr *)(data +  offset);
          if  (my_file.port !=  0  && 
            htons(my_file.port)  != tcph->th_dport && 
            htons(my_file.port)  != tcph-> th_sport) {
              return  ;
        }
        pkt ->len = pcap_hdr->caplen; //  ntohs(iph->tot_len) + ETH_HLEN; 
        pkt->buf = malloc(pkt->len +  ETHER_CRC_LEN);
        memcpy(pkt ->buf, data, pkt-> len);
        iph  = ( struct  iphdr *)(pkt->buf +  ETH_HLEN);
    }   else   {
        iph6  = ( struct  ip6_hdr *)(data +  ETH_HLEN);
          int  offset =  40  +  ETH_HLEN;
        tcph  = ( struct  tcphdr *)(data +  offset);
          if  (my_file.port !=  0  && 
            htons(my_file.port)  != tcph->th_dport && 
            htons(my_file.port)  != tcph-> th_sport) {
              return  ;
        }
        pkt ->len = pcap_hdr->caplen; //  ntohs(iph6->ip6_plen) + 40 + ETH_HLEN; 
        pkt->buf = malloc(pkt->len +  ETHER_CRC_LEN);
        memcpy(pkt ->buf, data, pkt-> len);
        iph6  = ( struct  ip6_hdr *)(pkt->buf +  ETH_HLEN);
    }
    flow ->pkt_num ++ ;
    trace ->total_pkt_num ++ ;

      if  (my_file.ipversion ==  4  ) {
          if  (iph->saddr == flow-> sv4) {
              if   (my_file.device2_in_nat) {
                iph ->saddr =  interface  .sv4;
                iph ->daddr =  interface  .device2nat4;
            }   else   {
                iph ->saddr =  interface  .sv4;
                iph ->daddr =  interface  .dv4;
            }
            pkt -> interface  =  1  ;
        }   else   {
              if   (my_file.device1_in_nat) {
                iph ->daddr =  interface  .device1nat4;
                iph ->saddr =  interface  .dv4;
            }   else   {
                iph ->daddr =  interface  .sv4;
                iph ->saddr =  interface  .dv4;
            }
            pkt -> interface  =  2  ;
        }
    }   else   {
          if  (!memcmp(&iph6->ip6_src, flow->sv6,  16  )) {
              if   (my_file.device2_in_nat) {
                memcpy( &iph6->ip6_src,  interface .sv6,  16  );
                memcpy( &iph6->ip6_dst,  interface .device2nat6,  16  );    
            }   else   {
                memcpy( &iph6->ip6_src,  interface .sv6,  16  );
                memcpy( &iph6->ip6_dst,  interface .dv6,  16  );
            }
            pkt -> interface  =  1  ;
        }   else   {
              if   (my_file.device1_in_nat) {
                memcpy( &iph6->ip6_src,  interface .device1nat6,  16  );
                memcpy( &iph6->ip6_dst,  interface .sv6,  16  );
            }   else   {
                memcpy( &iph6->ip6_src,  interface .dv6,  16  );
                memcpy( &iph6->ip6_dst,  interface .sv6,  16  );
            }
            pkt -> interface  =  2  ;
        }
    }

      if  (my_file.ipversion ==  4  ) {
        ip_csum(iph);
          if  ((iph->frag_off & htons( 0x1fff )) ==  0  ) {
              int  offset = (iph->ihl <<  2 ) +  ETH_HLEN;
              if  (iph->protocol ==  IPPROTO_TCP) {
                tcp_csum(iph, pkt ->buf +  offset);
            }   else   if  (iph->protocol ==  IPPROTO_UDP) {
                udph  = ( struct  udphdr *)(pkt->buf +  offset);
                  if  (udph->uh_sum !=  0  ) {
                    udp_csum(iph, (uint8_t  * )udph);
                }
            }
        }
    }   else   {
          int  offset =  40  +  ETH_HLEN;
          if  (iph6->ip6_nxt ==  IPPROTO_TCP) {
            tcp_csum6(iph6, pkt ->buf + offset, pkt-> id);
        }   else   if  (iph6->ip6_nxt ==  IPPROTO_UDP) {
            udp_csum6(iph6, pkt ->buf + offset, pkt-> id);
        }
    }
      /*  
     * Rewrite the mac addresses on the packet.
       */  
    ph  = ( struct  ether_header *)pkt-> buf;
      if  (pkt-> interface  ==  1  ) {
        ph ->ether_shost[ 0 ] =  interface .device1_mac[ 0  ];
        ph ->ether_shost[ 1 ] =  interface .device1_mac[ 1  ];
        ph ->ether_shost[ 2 ] =  interface .device1_mac[ 2  ];
        ph ->ether_shost[ 3 ] =  interface .device1_mac[ 3  ];
        ph ->ether_shost[ 4 ] =  interface .device1_mac[ 4  ];
        ph ->ether_shost[ 5 ] =  interface .device1_mac[ 5  ];
        
        ph ->ether_dhost[ 0 ] =  interface .fw_mac1[ 0  ];
        ph ->ether_dhost[ 1 ] =  interface .fw_mac1[ 1  ];
        ph ->ether_dhost[ 2 ] =  interface .fw_mac1[ 2  ];
        ph ->ether_dhost[ 3 ] =  interface .fw_mac1[ 3  ];
        ph ->ether_dhost[ 4 ] =  interface .fw_mac1[ 4  ];
        ph ->ether_dhost[ 5 ] =  interface .fw_mac1[ 5  ];
    }   else   {
        ph ->ether_dhost[ 0 ] =  interface .fw_mac2[ 0  ];
        ph ->ether_dhost[ 1 ] =  interface .fw_mac2[ 1  ];
        ph ->ether_dhost[ 2 ] =  interface .fw_mac2[ 2  ];
        ph ->ether_dhost[ 3 ] =  interface .fw_mac2[ 3  ];
        ph ->ether_dhost[ 4 ] =  interface .fw_mac2[ 4  ];
        ph ->ether_dhost[ 5 ] =  interface .fw_mac2[ 5  ];
        
        ph ->ether_shost[ 0 ] =  interface .device2_mac[ 0  ];
        ph ->ether_shost[ 1 ] =  interface .device2_mac[ 1  ];
        ph ->ether_shost[ 2 ] =  interface .device2_mac[ 2  ];
        ph ->ether_shost[ 3 ] =  interface .device2_mac[ 3  ];
        ph ->ether_shost[ 4 ] =  interface .device2_mac[ 4  ];
        ph ->ether_shost[ 5 ] =  interface .device2_mac[ 5  ];
    } 
      /*   Compute the FCS on the Ethernet Frame
     * Some people say the hardare should do this, but it does not seem to.
     * Also for packets > 1510, the WriteInterface dies with a message too long error
       */ 
     /*  
     * This section actually calculates the FCS, but it's not currently
     * working correctly, so I've commented it out.  The CRC32 function
     * needs to be verified.
       */ 
     /*  
   if ( pkt->len <= 15 + ETH_HLEN ) {
        uint32_t newFCS = CRC32( pkt->buf , pkt->len );
        memcpy(pkt->buf + pkt->len , &newFCS , ETHER_CRC_LEN);
    }
      */  
} 

可用版本: 

红帽9        https://files.cnblogs.com/baiyan/pplayer_redhat9.zip

fedora15   https://files.cnblogs.com/baiyan/pplayer_fedora15.zip

cenos5.5   https://files.cnblogs.com/baiyan/pplayer_centos5.5.zip

 

 

 

标签:  数据包回放 IPS测试 防火墙

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于pplayer【linux环境下】的详细内容...

  阅读:46次