• 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程序在同一目录下。

    格式:
      device1:eth0
      device2:eth1
      device1ip:1.1.1.1
      device2ip:2.2.2.2
      device1nat:3.3.3.3
      device2nat:4.4.4.4
      fwmac1:00:0C:29:25:63:6E
      fwmac2:00:0C:29:25:63:78

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

      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

     
     
     
  • 相关阅读:
    zookeeper集群搭建2.7
    hadoop集群环境搭建
    Kettle(6.0) 参数方式连接数据库
    kettle数据同步的5中方案
    kettle 合并记录步骤中的 关键字段和 比较字段的说明
    KETTLE常见问题和优化
    Hbase与Oracle的比较
    EHCache
    hdu2014 青年歌手大奖赛_评委会打分【C++】
    hdu2013 蟠桃记【C++】
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3073483.html
Copyright © 2020-2023  润新知