LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   [Need help] Remote server doesn't respond to modified SYNC TCP packet (https://www.linuxquestions.org/questions/programming-9/%5Bneed-help%5D-remote-server-doesnt-respond-to-modified-sync-tcp-packet-4175504904/)

android2009 05-13-2014 08:27 PM

[Need help] Remote server doesn't respond to modified SYNC TCP packet
 
I am trying to modify IP destination address for all outgoing packets. Currently trying this on VirtualBox Ubuntu guest (kernel version 3.8.0) on Windows 7.
In my program below I built a hash table to map fake ip addresses to real ip addresses (google, ncsu etc.), for example, 100.100.100.100 maps to google, 100.100.100.101 maps to something else.

From wireshark I can see the TCP SYNC packets were successfully modified and sent to google when I put 'http://100.100.100.100' in a web browser, also checksums of TCP and IP packets are correct calculated. However there is no [SYNC, ACK] packets coming back from google, neither does any error message. I also tried other servers they also don't respond.

Does anyone have idea what might be wrong here ? Any suggestion is well appreciated.


Code:


/* postRoute hook */
unsigned int out_hook(unsigned int hooknum,
                      struct sk_buff *skb,
                      const struct net_device *in,
                      const struct net_device *out,
                      int (*okfn)(struct sk_buff *)) {



   
    struct sk_buff *sock_buff;
    struct iphdr *ip_header;
    struct udphdr *udp_header;
    struct tcphdr *tcp_header;
    unsigned int udp_len;
    unsigned int tcp_len;
       
        printk(KERN_INFO "out_hook: entering function\n");

    if (!skb) {

        printk(KERN_INFO "out_hook: skb is NULL\n");

        return NF_ACCEPT;

    }

    if (!(skb->network_header)) {

        printk(KERN_INFO "out_hook: Error in networkheader\n");
        return NF_ACCEPT;

    }


    sock_buff = skb;
    printk(KERN_INFO "out_hook: Getting ip_header\n");

    /* Retrieve ip header */
    ip_header = ip_hdr(sock_buff);

    char source[16];
    snprintf(source, 16, "%pI4", &ip_header->daddr);
    printk(KERN_INFO "out_hook: ip address is %s\n", source);



    /* Handle udp protocol, only forward packets based on hashtable */
    if (ip_header->protocol == IPPROTO_UDP) {

        printk(KERN_INFO "out_hook: Handling udp packet\n");

        udp_header = udp_hdr(sock_buff);

   
        udp_len = sock_buff->len - (ip_header->ihl << 2);       

        printk(KERN_INFO "out_hook: old outgoing daddr %u\n", ip_header->daddr);
       
       
        unsigned int ret = search_fake_to_real_ip_table(ip_header->daddr);
        /* Check if ip_header->daddr is a fake address or not, if so, replace it with real address from hashtable */
        if (ret!=0)
        {

            char source[16];
            char dest[16];
            snprintf(source, 16, "%pI4", &ip_header->daddr);
            snprintf(dest, 16, "%pI4", &ret);

            printk(KERN_INFO "%s is mapping to %s\n", source,dest);
            /* Update hashtable for incoming packets */

            insert_real_to_fake_ip_table(ret, ip_header->daddr);

            /* Replace fake address with real address */
            ip_header->daddr = ret;
            printk(KERN_INFO "out_hook: new outgoing daddr %u\n", ip_header->daddr);

            /* If UDP checksum is enabled, need to re-calculate */
            if (udp_header->check) {

                printk(KERN_INFO "out_hook: old udp checksum %u\n", udp_header->check);
                udp_header->check = csum_tcpudp_magic(ip_header->saddr, ip_header->daddr, udp_len, IPPROTO_UDP,  csum_partial(udp_header, udp_len, 0));
                printk(KERN_INFO "out_hook: new udp checksum %u\n", udp_header->check);

            }

            /* Recaculate IP checksum */
            printk(KERN_INFO "out_hook: recalculating ip checksum %u\n", ip_header->check);
            ip_header->check = 0x000;
            ip_header->check = ip_fast_csum((unsigned char *)ip_header, ip_header->ihl);
            printk(KERN_INFO "out_hook: recalculated ip checksum %u\n", ip_header->check);

            return NF_ACCEPT;
        }
       
        return NF_ACCEPT;

    }



    /* Handle tcp protocol */
    else if (ip_header->protocol == IPPROTO_TCP) {


        printk(KERN_INFO "outhook: Handling tcp packet\n");
        tcp_header = tcp_hdr(sock_buff);  //tcp_header = (struct tcphdr *)((unsigned long int *)ip_header + ip_header->ihl);
        tcp_len = sock_buff->len - (ip_header->ihl << 2);

        unsigned int ret = search_fake_to_real_ip_table(ip_header->daddr);
        if (ret!=0)
        {


              char source[16];
            char dest[16];
            snprintf(source, 16, "%pI4", &ip_header->daddr);
            snprintf(dest, 16, "%pI4", &ret);

            printk(KERN_INFO "%s is mapping to %s\n", source,dest);
            /* Update hashtable for incoming packets */
            insert_real_to_fake_ip_table(ret, ip_header->daddr);

            /* Replace fake address with real address */
            ip_header->daddr = ret;
            printk(KERN_INFO "out_hook: new outgoing daddr %u\n", ip_header->daddr);

            /* New tcp checksum */
            if (tcp_header->check) {
                tcp_header->check = 0;
                tcp_header->check = csum_tcpudp_magic(ip_header->saddr, ip_header->daddr, tcp_len, IPPROTO_TCP, csum_partial((char *)tcp_header, tcp_len, 0));

            }

            printk(KERN_INFO "Recalculating tcp/ip checksum");
            /* New ip checksum */
            ip_header->check = 0x000;
            ip_header->check = ip_fast_csum((unsigned char *)ip_header, ip_header->ihl);

            return NF_ACCEPT;
        }

   
        return NF_ACCEPT;

    }

    /* Let go all other non-udp/tcp packets */

    else {

        return NF_ACCEPT;

    }

}


android2009 05-15-2014 09:02 PM

I kind figured out where the problem is but don't know how to resolve it.

The function ip_fast_csum((unsigned char *)ip_header, ip_header->ihl) used to calculate IP checksum doesn't return a correct value.

does anyone know which function should I use instead ?


All times are GMT -5. The time now is 08:55 PM.