无法使用内核模块中的 netfilter 挂钩解析 HTTP 数据包

问题描述 投票:0回答:1

我正在尝试使用内核模块中的 netfilter 挂钩来解析 HTTP 数据包。我在如何从 TCP 数据包打印数据上看到了这段代码片段,我对其进行了修改以使其构建。但是,即使我已成功加载内核模块,我也无法在

HTTP
中看到与
dmesg
相关的任何日志。

我已尝试调试该问题,但无法找出问题所在,有效负载与

HTTP
不匹配。我怀疑问题可能与
HTTP
数据包被结转有关TCP 和我没有正确处理 TCP 协议。

我正在使用的代码:

#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>

#define PTCP_WATCH_PORT 80 /* HTTP port */

static struct nf_hook_ops nfho;

static unsigned int ptcp_hook_func(const struct nf_hook_ops *ops,
                                   struct sk_buff *skb,
                                   const struct net_device *in,
                                   const struct net_device *out,
                                   int (*okfn)(struct sk_buff *))
{
    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')
    {
        // Control is reaching here always.
        return NF_ACCEPT;
    }

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

    /* Print TCP packet data (payload) */
    printk("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;
}

static int __init ptcp_init(void)
{
    int res;

    nfho.hook = (nf_hookfn *)ptcp_hook_func; /* hook function */
    nfho.hooknum = NF_INET_PRE_ROUTING;      /* received packets */
    nfho.pf = PF_INET;                       /* IPv4 */
    nfho.priority = NF_IP_PRI_FIRST;         /* max hook priority */

    res = nf_register_net_hook(&init_net,&nfho);
    if (res < 0)
    {
        printk("print_tcp: error in nf_register_hook()\n");
        return res;
    }

    printk("print_tcp: loaded\n");
    return 0;
}

static void __exit ptcp_exit(void)
{
    nf_unregister_net_hook(&init_net,&nfho);
    printk("print_tcp: unloaded\n");
}

module_init(ptcp_init);
module_exit(ptcp_exit);

MODULE_DESCRIPTION("Module for printing HTTP packet data");
MODULE_LICENSE("GPL");
c http network-programming kernel-module netfilter
1个回答
0
投票

您找到解决方案了吗? 我有同样的问题,我想记录 HTTP 标头,但这不起作用......

© www.soinside.com 2019 - 2024. All rights reserved.