在libnet(tcp包)中构建一个http包,请尽快帮助我们。我们被卡住!

时间:2010-05-31 10:00:24

标签: c

我们正在构建NAT程序,我们更改来自内部子网的每个数据包, 通过libnet函数更改它的源IP地址。(用libpcap捕获数据包,放入它 嗅探结构并使用libnet构建新数据包)

通过TCP,更改后的syn / ack数据包很好,当HTTP-GET请求到来时,我们可以通过wireshark看到校验和字段有错误。 所有其他字段与原始数据包完全相同。

有谁知道会导致这个问题的原因是什么? 其他数据包中的新校验和计算应该是.. 但在HTTP数据包中却没有......

3 个答案:

答案 0 :(得分:2)

现代以太网卡可以计算硬件中的校验和,因此TCP堆栈倾向于将作业卸载到卡上。因此,在Wireshark中校验和无效是很常见的。

附注:Wireshark中有一个选项可以验证校验和:

Edit
  Preferences
    Protocols
      TCP
        Validate the TCP checksum if possible

关闭它以阻止Wireshark唠叨你的校验和。

答案 1 :(得分:0)

这实际上是否会导致问题 - 即“校验和错误”的数据包是否被丢弃或处理错误?或者你只是担心“错误的校验和”通知?如果数据包处理正常,这可能只是校验和卸载,没什么可担心的。

Wireshark documentation说:

  

如果收到的校验和错误,Wireshark甚至看不到数据包,因为以太网硬件在内部丢弃数据包。

答案 2 :(得分:0)

嘿,以她的名义回答。 GET和ACK是分开的,是的,GET请求是完全发送的,这是根据数据包是由Firefox或Wget发送的事实来说的。我们不创建数据包,也不创建服务器的响应(也就是Apache)。

我们的代码只是在中间运行。除了客户端和服务器之外,我们还有第三台机器,所有这三台机器都是虚拟机(在VMWare服务器[NAT,Client = Ubuntu; Server = Fedora]中)。它有2个NIC(每个NIC相应地连接到每个子网),它的目标是更改源IP和源端口字段(在网络流量的两个方向上)。

感谢有关TCP校验和卸载的解释,这可能是由wireshark发生的,但在我看来并非如此,因为错误也出现在服务器端(如果这排除了可能性,那就不是100%肯定,想法?)。 如果我是对的,那可能是校验和不正确的原因?

以下是当前代码的链接: http://rapidshare.com/files/393704745/13.5.10.tar.gz

非常感谢, 特拉维夫。

如果这里的代码更好,那么你去吧:






#include "./main.h"


int main(int argc, char **argv)
{
    pcap_t *pcapInt, *pcapExt;                      /* pcap descriptor */
    u_char *intPacket, *extPacket;
    int i;
    struct pcap_pkthdr intPkthdr, extPkthdr;
    char errbuf[PCAP_ERRBUF_SIZE];
    struct bpf_program filter_code;
    bpf_u_int32 intLocalNet, intNetmask, extLocalNet;

    for(i=0;i to quit\n");

    /* read the configuration file and store it's data in an array */
    LIBXML_TEST_VERSION
    xmlNode *cur_node = xmlDocGetRootElement(xmlReadFile(((argv[1]) != NULL ? argv[1] : "conf.xml"), NULL, 0));
    strcpy(config.filter, "");

    XMLtoConf(cur_node);
    strcat(config.filter, " and not src host 192.168.191.137");
    printf("FILTER: %s\n", config.filter);


    /* get network number and mask associated with the internal capture device */
    if (pcap_lookupnet(config.intNIC, &intLocalNet, &intNetmask, errbuf) == -1) {
        fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
            config.intNIC, errbuf);
        intLocalNet = 0;
        intNetmask = 0;
    }

    /* open internal capture device */
    pcapInt = pcap_open_live(config.intNIC, SNAP_LEN, 1, 1000, errbuf);
    if (pcapInt == NULL) {
        fprintf(stderr, "Couldn't open device %s: %s\n", config.intNIC, errbuf);
        exit(EXIT_FAILURE);
    }
    /* open external capture device */
    pcapExt = pcap_open_live(config.extNIC, SNAP_LEN, 1, 1000, errbuf);
    if (pcapExt == NULL) {
        fprintf(stderr, "Couldn't open device %s: %s\n", config.extNIC, errbuf);
        exit(EXIT_FAILURE);
    }

    /* make sure we're capturing on an Ethernet device [2] */
    if (pcap_datalink(pcapInt) != DLT_EN10MB) {
        fprintf(stderr, "%s is not an Ethernet\n", config.intNIC);
        exit(EXIT_FAILURE);
    }
    if (pcap_datalink(pcapExt) != DLT_EN10MB) {
        fprintf(stderr, "%s is not an Ethernet\n", config.extNIC);
        exit(EXIT_FAILURE);
    }

    /* compile the internal filter expression */
    if (pcap_compile(pcapInt, &filter_code, config.filter, 1, intLocalNet) == -1) { //adsvfhakdhvkahdvkadh
        fprintf(stderr, "Couldn't parse filter %s: %s\n",
            argv[1], pcap_geterr(pcapInt));
        exit(EXIT_FAILURE);
    }
    /* compile the external filter expression */
    if (pcap_compile(pcapExt, &filter_code, NULL, 1, extLocalNet) == -1) { //adsvfhakdhvkahdvkadh
        fprintf(stderr, "Couldn't parse filter %s: %s\n",
            argv[1], pcap_geterr(pcapExt));
        exit(EXIT_FAILURE);
    }

    /* apply the compiled internal filter */
    if (pcap_setfilter(pcapInt, &filter_code) == -1) {
        fprintf(stderr, "Couldn't install filter %s: %s\n",
            argv[1], pcap_geterr(pcapInt));
        exit(EXIT_FAILURE);
    }
     //apply the compiled external filter 
    if (pcap_setfilter(pcapExt, &filter_code) == -1) {
        fprintf(stderr, "Couldn't install filter %s: %s\n",
            argv[1], pcap_geterr(pcapExt));
        exit(EXIT_FAILURE);
    }
    while (1 == 1)
    {     
        intPacket = (u_char*)pcap_next(pcapInt, &intPkthdr);
        extPacket = (u_char*)pcap_next(pcapExt, &extPkthdr);
        if (intPacket != NULL)
        {
            sniff(intPacket,0);
        } 
        if (extPacket != NULL)
        {
            sniff(extPacket,1);
        } 
    }

    printf("\nCapture complete.\n");
    /* cleanup */
    pcap_freecode(&filter_code);
    pcap_close(pcapInt);
    return (EXIT_SUCCESS);
}

int isStrBlank(unsigned char *s)
{
  if (!s || strcmp((char *)s, "") == 0) return 1;

  while(*s) {
    if ( (' ' != *s) && ('\n' != *s) && ('\r' != *s) && ('\t' != *s)) return 0;
    ++s;
  }
  return 1;
}

static void XMLtoConf(xmlNode* node)
{
     /*
     * this initialize the library and check potential ABI mismatches
     * between the version it was compiled for and the actual shared
     * library used.
     */
    LIBXML_TEST_VERSION
    xmlNode *cur_node = node;
    int i,flag=0;
    for (; cur_node; cur_node = cur_node->next) {
        if (cur_node->type == XML_ELEMENT_NODE) {
                //if (isStrBlank(cur_node->children->content) == 1) continue;

                if (strcmp((char *)cur_node->name, "subnet_address") == 0){
                    strcat(config.filter, "src net ");
                    strcat(config.filter,(char *)cur_node->children->content);
                }
                //printf("1: %s", config.filter);
                if (strcmp((char *)cur_node->name, "NIC") == 0){
                    if (strcmp((char *)cur_node->parent->name, "internal") == 0){
                        config.intNIC = strdup((char *)cur_node->children->content);
                    }
                    else{
                        config.extNIC = strdup((char *)cur_node->children->content);
                    }
                }
                for (i = 0; strncmp((char *)cur_node->name, "machine_", 8) == 0; i++){

                    strcat(config.filter, " and not");
                    strcat(config.filter, " src host ");
                    flag=1;
                    strcat(config.filter, (char *)cur_node->children->content);
                    cur_node = cur_node->next;
                }


        }
        XMLtoConf(cur_node->children);
    }
    /*
     *Free the global variables that may
     *have been allocated by the parser.
     */
    xmlCleanupParser();
    /*
     *  If device is NULL, that means the user did not specify one and is
     *  leaving it up libpcap to find one.
     */
}


void sniff(const u_char *packet , int flag)
{
    int i,x,tcpOpen=0;
    int protocol=-1; // 0- tcp, 1- udp, 2 -icmp
    tcp = (struct sniff_tcp*)(packet + 34); //skipping the ethernet and IP layers
    udp = (struct sniff_udp *)(packet + 34); //skipping the ethernet and IP layers
    ip = (struct sniff_ip *)(packet + SIZE_ETHERNET);
    icmp = (struct sniff_icmp *)(packet+ 34);
    ether = (struct sniff_ethernet *)(packet);

    printf("/n1--%d/n",IP_HL(ip)*4);
    //if(ntohs(tcp->th_sport) == 80 || ntohs(tcp->th_dport) == 80)
        //{

        if(ip->ip_p==IP_TYPE_TCP )
        {
            protocol = 0;
            payload_s = ntohs(ip->ip_len) - TH_OFF(tcp)*4 - IP_HL(ip)*4;

            if (payload_s)
                payload = (char* )(packet + SIZE_ETHERNET + TH_OFF(tcp)*4 + IP_HL(ip)*4);
            else
                payload = NULL;

        }
        else if(ip->ip_p == IP_TYPE_UDP){
            protocol = 1;
            payload_s = ntohs(ip->ip_len) - ntohs(udp->udp_len) - IP_HL(ip)*4;

            if (payload_s)
                payload = (char* )(packet + SIZE_ETHERNET + ntohs(udp->udp_len) + IP_HL(ip)*4);
            else
                payload = NULL;
        }
        else if(ip->ip_p == IP_TYPE_ICMP)
        {
            protocol = 2;
            payload_s = ntohs(ip->ip_len) - 8 - IP_HL(ip)*4;

            if (payload_s)
                payload = (char* )(packet + SIZE_ETHERNET + 8 + IP_HL(ip)*4);
            else
                payload = NULL;
        }   


            if(flag == 0)// we got a packet from the internal
            {
                if( ip->ip_p == IP_TYPE_TCP)
                {
                    for(i=0;iip_p)
                                if(nTable[i].ip_src.s_addr == ip->ip_src.s_addr)
                                    if(nTable[i].ip_dst.s_addr == ip->ip_dst.s_addr)
                                        if(ntohs(nTable[i].srcPort) == ntohs(tcp->th_sport))
                                            if(ntohs(nTable[i].dstPort) == ntohs(tcp->th_dport))
                                            {
                                                printf("we are in an open connection \n");
                                                changeSrcPacket(packet ,(i+2000)%8000 ,protocol);
                                                tcpOpen = 1;
                                                break;
                                            }
                    }           
                }
                if(tcpOpen == 0)
                {
                    for(i=0;iip_p == IP_TYPE_UDP ||ip->ip_p == IP_TYPE_TCP    )
                        {
                            if(nTable[i].free==0)
                            {
                                nTable[i].free=1;
                                nTable[i].ip_src = ip->ip_src;
                                nTable[i].ip_dst = ip->ip_dst;
                                nTable[i].srcPort = tcp->th_sport;
                                nTable[i].dstPort = tcp->th_dport;
                                nTable[i].protocol = ip->ip_p;
                                //printf("index : %d  ipsrc : %s  srcport : %d\n",i,inet_ntoa(nTable[i].ip_src),ntohs(nTable[i].srcPort));
                                ////////////change packet and send it with the src ip of the nat machine 
                                ///////////and the src port is (i+2000)%8000
                                changeSrcPacket(packet ,(i+2000)%8000 ,protocol);
                                break;
                            }
                        }
                        else
                        {
                            if(icmpTable[i].free == 0)
                            {
                                icmpTable[i].free=1;
                                icmpTable[i].ip_src = ip->ip_src;
                                icmpTable[i].ip_dst = ip->ip_dst;
                                icmpTable[i].protocol = ip->ip_p;
                                icmpTable[i].icmp_type = icmp->icmp_type;
                                icmpTable[i].icmp_id1 = icmp->icmp_id1;
                                changeSrcPacket(packet ,-1 ,protocol);
                                break;
                            }
                        }
                    }
                }
            }
            else // flag = 1
            {
            // we got a packet from the external. we want to send it to the right 
            // place in the internal

            //nTable[(tcp->th_dport-2000)%8000];

            //printf("dst: %d , src: %d \n",ntohs(tcp->th_dport),ntohs(tcp->th_sport));

                if(ip->ip_p== IP_TYPE_ICMP)
                {
                    changeDstPacket (packet,-1,protocol);
                }
                else
                {
                    for(x=0;xip_p == IP_TYPE_TCP)
                        {
                            if(((int)(ntohs(tcp->th_dport))-2000)%8000 == x && nTable[x].free == 1)
                            {
                                changeDstPacket (packet,x,protocol);
                                break;
                            }
                        }
                        else
                        {
                            if(((int)(ntohs(udp->udp_destport))-2000)%8000 == x && nTable[x].free == 1)
                            {
                                changeDstPacket (packet,x,protocol);
                                break;
                            }

                        }
                    }   
                }       
            // we create a packet with thw same src ip and port as we got
            // and only the dst port and ip will be the ones that are 
            //saved in nTable[(tcp->th_dport-2000)%8000]
            // now if it is in udp we will put 0 in nTable[(tcp->th_dport-2000)%8000].free


            }

}

void changeSrcPacket(const u_char *packet , int srcPort, int protocol)
{
    libnet_t *l;
    libnet_ptag_t ipv, ptag, popt,icmp;
    char errbuf[LIBNET_ERRBUF_SIZE];
    uint32_t nat_adder;

     size_t ip_hlen=IP_HL(ip)*4;
     size_t ip_len=ntohs(ip->ip_len);

    size_t tcp_len = ip_len - ip_hlen;

    printf("\n%d %d %d %d",IP_HL(ip),ip_hlen,ip_len,tcp_len);


    icmp = ptag = ipv = LIBNET_PTAG_INITIALIZER;


     nat_adder = libnet_name2addr4(l,"192.168.191.137",LIBNET_DONT_RESOLVE);

     l = libnet_init(LIBNET_RAW4,config.extNIC, errbuf);

     if(protocol == 0)//TCP
     {

         if(TH_OFF(tcp)*4 > TCP_HEADER_SIZE)
         {
                options = (char*)packet + 54;
                options_s = TH_OFF(tcp)*4 - TCP_HEADER_SIZE;
                popt = libnet_build_tcp_options((u_int8_t*)options,options_s, l,0);     
         }

         ptag = libnet_build_tcp(
          srcPort, // source port
          ntohs(tcp->th_dport), // dest port
          htonl(tcp->th_seq), // sequence number
          ntohl(tcp->th_ack), // ack number
          tcp->th_flags, // flags
          ntohs(tcp->th_win), // window size
          0, // checksum
          ntohs(tcp->th_urp), // urg ptr
          TH_OFF(tcp)*4, // total length of the TCP packet
          (u_int8_t*)payload, // response
          payload_s, // response_length
          l, // libnet_t pointer
          ptag // ptag
          );


          printf("%d, %d, %d, %d, %d\n", TH_OFF(tcp)*4, IP_HL(ip)*4, payload_s, ntohs(ip->ip_len),TH_OFF(tcp)*4);
            if(ptag==-1)
             {
                fprintf(stderr, "Error building TCP header: %s\n",libnet_geterror(l));
                exit(1);
             }

    if (libnet_do_checksum(l, (u_int8_t*)ip,IPPROTO_TCP, TH_OFF(tcp)*4) udp_destport), /* destination port */
                udp->udp_len, /* packet length */
                0, /* checksum */
                (u_int8_t*)payload, /* payload */
                payload_s, /* payload size */
                l, /* libnet handle */
                ptag); /* libnet id */

          if(ptag==-1)
          {
             fprintf(stderr, "Error building UDP header: %s\n",libnet_geterror(l));
             exit(1);
          }

     }

   // if(protocol == 2)//ICMP
     //{
        ///add functions of icmp
     // icmp = libnet_build_icmpv4_echo(
        //ICMP_ECHO, /* type */
        //0, /* code */
        //0, /* checksum */
        //icmp->icmp_id1, /* id */
        //icmp->icmp_seq1, /* sequence number */
        //payload, /* payload */
        //payload_s, /* payload size */
        //l, /* libnet context */
        //icmp); /* ptag */

        //if (icmp == -1)
        //{
        //  fprintf(stderr, "Can't build ICMP header: %s\n",
        //  libnet_geterror(l));

        //}
    // }


       ipv = libnet_build_ipv4(
                                                /* total length */
                   ntohs(ip->ip_len),
                    ip->ip_tos,                          /* type of service */
                    ntohs(ip->ip_id),                        /* identification */
                    ntohs(ip->ip_off),                          /* fragmentation */
                    ip->ip_ttl,                         /* time to live */
                    ip->ip_p,                /* protocol */
                    0,                          /* checksum */
                    nat_adder,                     /* (Nat) source */
                    ip->ip_dst.s_addr,                     /* destination */
                   NULL,                       /* payload */
                   0,                          /* payload size */
                    l,                          /* libnet handle */
                    0);                         /* ptag */

        if(ipv == -1)
        {
            fprintf(stderr,"Error building IP header: %s\n", libnet_geterror(l));
            exit(1);
        }

        /*if (libnet_do_checksum(l, (u_int8_t*)l, IPPROTO_IP, ntohs(ip->ip_len) + payload_s) th_flags == 0x01)
            {
                nTable[index].fin++;
            }
            if(tcp->th_flags == 0x11 && nTable[index].fin == 1)
            {
                nTable[index].fin++;
            }
            if(tcp->th_flags == 0x10 && nTable[index].fin == 2)
            {
                nTable[index].free = 0; 
                nTable[index].fin = 0;
            }
        }


         // Fix IP header checksum
  //  ip->ip_sum = 0;
    if (libnet_do_checksum(l, (u_int8_t*)ip,IPPROTO_IP, IP_HL(ip)*4) th_sport),ntohs(nTable[index].srcPort));
    printf("src ip : %s    dst ip: %s\n",inet_ntoa(ip->ip_src), inet_ntoa(nTable[index].ip_src));

    ptag = ipv = LIBNET_PTAG_INITIALIZER;

    if(protocol == 0 || protocol == 1) // udp or tcp
    {

        if(nTable[index].free == 1)
        {
            l = libnet_init(LIBNET_RAW4,config.intNIC, errbuf);

            if(protocol == 0 ) //TCP
            {

                if(TH_OFF(tcp)*4 > TCP_HEADER_SIZE)
                {
                     options = (char*)packet + 54;
                     options_s = TH_OFF(tcp)*4 - TCP_HEADER_SIZE;
                     popt = libnet_build_tcp_options((u_int8_t*)options,options_s, l,0);

                }

                  ptag = libnet_build_tcp(
                  ntohs(tcp->th_sport), // source port
                  ntohs(nTable[index].srcPort), // dest port
                  ntohl(tcp->th_seq), // sequence number
                  ntohl(tcp->th_ack), // ack number
                  tcp->th_flags, // flags
                  ntohs(tcp->th_win), // window size
                  0, // checksum
                  ntohs(tcp->th_urp), // urg ptr
                  TH_OFF(tcp)*4, // total length of the TCP packet
                  (u_int8_t*)payload, // response
                  payload_s, // response_length
                  l, // libnet_t pointer
                  ptag // ptag
                  );

                  if(ptag==-1)
                  {
                    fprintf(stderr, "Error building TCP header: %s\n",libnet_geterror(l));
                    exit(1);
                  }
            }

            if(protocol == 1)// UDP
            {
                ptag = libnet_build_udp(
                    ntohs(udp->udp_srcport), /* source port */
                    ntohs(nTable[index].srcPort), /* destination port */
                    udp->udp_len, /* packet length */
                    0, /* checksum */
                    (u_int8_t*)payload, /* payload */
                    payload_s, /* payload size */
                    l, /* libnet handle */
                    ptag); /* libnet id */

                if(ptag==-1)
                {
                    fprintf(stderr, "Error building UDP header: %s\n",libnet_geterror(l));
                    exit(1);
                }
            }
        }
    }
    if(protocol == 2) // ICMP
    {
        for(i=0;i icmp_type)
                    if(icmpTable[i].ip_dst.s_addr == ip->ip_src.s_addr)
                        if(icmpTable[i].icmp_id1 == icmp->icmp_id1)
                        {
                            index = i;
                            break;
                        }

        }

        ///add functions of icmp

    }

              ipv = libnet_build_ipv4(
                                                        /* total length */
                            ntohs(ip->ip_len),
                            ip->ip_tos,                          /* type of service */
                            ntohs(ip->ip_id),                        /* identification */
                            ntohs(ip->ip_off),                          /* fragmentation */
                            ip->ip_ttl,                         /* time to live */
                            ip->ip_p,                /* protocol */
                           0,                           /* checksum */
                            ip->ip_src.s_addr,                     /* (Nat) source */
                            nTable[index].ip_src.s_addr,                     /* destination */
                            NULL,                       /* payload */
                            0,                          /* payload size */
                            l,                          /* libnet handle */
                            0);                          /* ptag */
               if(ipv == -1)
              {
                fprintf(stderr,"Error building IP header: %s\n", libnet_geterror(l));
                exit(1);
              }   

            /*if (libnet_do_checksum(l, (u_int8_t*)l, IPPROTO_IP, ntohs(ip->ip_len) + payload_s) th_flags == 0x01)
                    {
                        nTable[index].fin++;
                    }
                    if(tcp->th_flags == 0x11 && nTable[index].fin == 1)
                    {
                        nTable[index].fin++;
                    }
                    if(tcp->th_flags == 0x10 && nTable[index].fin == 2)
                    {
                        nTable[index].free = 0; 
                        nTable[index].fin = 0;
                    }
                }
                else
                {
                    nTable[index].free = 0; 
                    nTable[index].fin = 0;
                }
            }


            if ( libnet_write(l) == -1 )
                      fprintf(stderr, "Error writing packet: %s\n",libnet_geterror(l));
            libnet_destroy(l);

}