0

I am trying to write a kernel module that will dump all the HTTP packet data to dmesg. I registered a nf_hook in POST ROUTING (tried also hooking OUTPUT table), and printing all the packets which sport is 80 (HTTP responses)

I read the following post - Print TCP Packet Data

and really got it to work! but I have a problem, the kernel module is printing only the first line of the response - HTTP/1.0 200 OK without printing all the HTTP headers and HTML.

this is my hook function -

    struct iphdr *iph;          /* IPv4 header */
    struct tcphdr *tcph;        /* TCP header */
    u16 sport, dport;           /* Source and destination ports */
    u32 saddr, daddr;           /* Source and destination addresses */
    unsigned char *user_data;   /* TCP data begin pointer */
    unsigned char *tail;        /* TCP data end pointer */
    unsigned char *it;          /* TCP data iterator */

    /* Network packet is empty, seems like some problem occurred. Skip it */
    if (!skb)
        return NF_ACCEPT;

    iph = ip_hdr(skb);          /* get IP header */

    /* Skip if it's not TCP packet */
    if (iph->protocol != IPPROTO_TCP)
        return NF_ACCEPT;

    tcph = tcp_hdr(skb);        /* get TCP header */

    /* Convert network endianness to host endiannes */
    saddr = ntohl(iph->saddr);
    daddr = ntohl(iph->daddr);
    sport = ntohs(tcph->source);
    dport = ntohs(tcph->dest);

    /* Watch only port of interest */
    if (sport != PTCP_WATCH_PORT)
        return NF_ACCEPT;

    /* Calculate pointers for begin and end of TCP packet data */
    user_data = (unsigned char *)((unsigned char *)tcph + (tcph->doff * 4));
    tail = skb_tail_pointer(skb);

    /* ----- Print all needed information from received TCP packet ------ */

    /* Show only HTTP packets */
    if (user_data[0] != 'H' || user_data[1] != 'T' || user_data[2] != 'T' ||
            user_data[3] != 'P') {
        return NF_ACCEPT;
    }

    /* Print packet route */
    pr_debug("print_tcp: %pI4h:%d -> %pI4h:%d\n", &saddr, sport,
                              &daddr, dport);

    /* Print TCP packet data (payload) */
    pr_debug("print_tcp: data:\n");
    for (it = user_data; it != tail; ++it) {
        char c = *(char *)it;

        if (c == '\0')
            break;

        printk("%c", c);
    }
    printk("\n\n");

    return NF_ACCEPT;

I want to print the whole packet, not only the first row. why it's printing only the first row ? My guess is that there is some routing caching (like when using IPTABLES) , is there a way to disable the caching ?

Meir Tolpin
  • 325
  • 2
  • 13
  • Is there actually more data in the first frame? Did you check by capturing the network traffic? Because if for example I programmed a HTTP server, I would be perfectly fine in implementing it in such a way that I send the first line as soon as possible. – Cheatah Mar 31 '20 at 06:20
  • The server I am using is a python SimpleHTTPServer. I checked with wireshark and the packet really have a data and a headers But the additional data and headers are not shown in the `dmesg` – Meir Tolpin Mar 31 '20 at 07:51

1 Answers1

0

I have the same problem until closed my proxy client (like v2ray or shadowsocks), look likes the proxy client cached/simplify the http request data, you can try tcpdump to catch the http request data, there is only a line like: HTTP GET / 1.1.