Вопрос

My goal is to write a LKM (Linux Kernel Module) which intercepts all TCP packets, lookups tcp_sock structure and based on some conditions, logs some information from tcp_sock structure (ex: tcpsock->snd_una).

This is how I am trying to achieve this: I am intercepting using netfilter on ubunutu (code below) but is there a way to access tcp_sock structure (look for NOTE in the code)?

I am not particular about netfilter. Please suggest if there is any other way of writing LKM to achieve this. It has to be a LKM.

unsigned int ip_packets_hook_func(unsigned int hooknum, 
            struct sk_buff *skb, 
            const struct net_device *in, 
            const struct net_device *out, 
            int (*okfn)(struct sk_buff *)) 
{
    struct iphdr *ipp = (struct iphdr *)skb_network_header(skb);
    struct tcphdr *tcp_hdr;
    struct tcp_sock *tcpsock;

    if (!skb) {
      return NF_ACCEPT;
    }

    if (ipp->protocol == IPPROTO_TCP ) { // Incomming packet is TCP
        tcp_hdr = (struct tcphdr *) ((__u32 *)ipp + ipp->ihl);
        tcpsock = (struct tcp_sock *) skb->sk;

        if(ntohs(tcp_hdr->dest) != INTERESTED_PORT) {
            return NF_ACCEPT;
        }

        printk("TCP ports: source: %d, dest: %d \n", ntohs(tcp_hdr->source),
                       ntohs(tcp_hdr->dest));

        if(tcp_hdr->syn || tcp_hdr->fin || tcp_hdr->rst) {
               printk("Flag: %s %s %s\n", tcp_hdr->syn? "SYN" : "",
                                          tcp_hdr->fin? "FIN" : "",
                                          tcp_hdr->rst? "RST" : "");
               return NF_ACCEPT;
        }

        // **NOTE**
        // skb->sk is NULL at this point. 
        // Get tcp_sock for this connection.
    } else {
        printk("Its not TCP\n");
    }

    return NF_ACCEPT;
}
Это было полезно?

Решение

I was able to achieve it by looking up inet hashtables (code snippet below). I am the server in this example. Make sure you lookup after 3 way handshake is complete.

const struct iphdr *iph;
const struct tcphdr *th;
struct sock *sk = NULL;
struct tcp_sock *tp;

.
.
.
.

sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
                                   iph->saddr, th->source,
                                   iph->daddr, ntohs(th->dest),
                                   skb->skb_iif);

// Sanity checks here.

tp = tcp_sk(sk);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top