LKM从数据包中查找tcp_sock

时间:2013-12-31 20:40:35

标签: sockets tcp linux-kernel kernel-module netfilter

我的目标是编写一个LKM(Linux内核模块),它拦截所有TCP数据包,查找tcp_sock结构,并根据某些条件,从tcp_sock结构中记录一些信息(例如:tcpsock-> snd_una)。

这就是我想要实现的目的:我在ubunutu上使用netfilter拦截(下面的代码),但有没有办法访问tcp_sock结构(在代码中查找注意)? / p>

我并不特别关注netfilter。请建议是否有任何其他方式来编写LKM来实现这一目标。它必须是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;
}

1 个答案:

答案 0 :(得分:0)

我能够通过查找inet哈希表(下面的代码片段)来实现它。我是这个例子中的服务器。确保在3次握手完成后进行查找。

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);