如何使用呼应netfilter的钩子在内核空间的包? [英] How to echo a packet in kernel space using netfilter hooks?

查看:177
本文介绍了如何使用呼应netfilter的钩子在内核空间的包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想回响在内核空间的包。我运行端口6000本机上的回显服务器。
现在客户另一台机器发送数据到回声服务器上运行。现在,我想做的就是回显数据包从内核空间了。我不想打扰与数据包中的服务器,它会悄悄地从内核空间的呼应。我是presenting我的$ C $以下CS:

I want to echo a packet in kernel space. I run an echo server on this machine with port 6000. Now a client runs on another machine sending data to the echo server. Now, what I want to do is to echo the packet back from the kernel space. I do not want to bother the server with the packet, and it will be echoed silently from the kernel space. I am presenting my codes below:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/crypto.h>
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <net/ip.h>
#include <net/udp.h>
#include <net/route.h>
#include <net/checksum.h>
#include <linux/netfilter_ipv4.h>

#define IP_HDR_LEN 20
#define UDP_HDR_LEN 8
#define TOT_HDR_LEN 28

static unsigned int pkt_echo_begin(unsigned int hooknum,
                        struct sk_buff *skb,
                        const struct net_device *in,
                        const struct net_device *out,
                        int (*okfn)(struct sk_buff *));

static struct nf_hook_ops pkt_echo_ops __read_mostly = {
    .pf = NFPROTO_IPV4,
    .priority = 1,
    .hooknum = NF_INET_PRE_ROUTING,
    .hook = pkt_echo_begin,
};

static int __init pkt_echo_init(void)
{
    printk(KERN_ALERT "\npkt_echo module started ...");
    return nf_register_hook(&pkt_echo_ops);
}

static void __exit pkt_echo_exit(void)
{
    nf_unregister_hook(&pkt_echo_ops);
    printk(KERN_ALERT "pkt_echo module stopped ...");
}

static unsigned int pkt_echo_begin (unsigned int hooknum,
                        struct sk_buff *skb,
                        const struct net_device *in,
                        const struct net_device *out,
                        int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph;
    struct udphdr *udph;
    unsigned char *data;

    unsigned char *temp;

    __u16 dst_port, src_port;
    int data_len;



    if (skb) {
        iph = (struct iphdr *) skb_header_pointer (skb, 0, 0, NULL);

        if (iph && iph->protocol &&(iph->protocol == IPPROTO_UDP)) {
            udph = (struct udphdr *) skb_header_pointer (skb, IP_HDR_LEN, 0, NULL);
            src_port = ntohs (udph->source);
            dst_port = ntohs (udph->dest);

            if (dst_port == 6000) {
                printk(KERN_ALERT "\nUDP packet goes in");

                data = (unsigned char *) skb_header_pointer (skb, TOT_HDR_LEN, 0, NULL);
                data_len = skb->len - TOT_HDR_LEN;

                struct sk_buff *newskb;
                struct iphdr *newiph;
                struct udphdr *newudph;
                unsigned char *newdata;
                unsigned int newdata_len;

                newskb = skb_copy(skb, GFP_ATOMIC);
                newiph = (struct iphdr *) skb_header_pointer (newskb, 0, 0, NULL);
                newudph = (struct udphdr *) skb_header_pointer (newskb, IP_HDR_LEN, 0, NULL);
                newdata = (unsigned char *) skb_header_pointer (newskb, TOT_HDR_LEN, 0, NULL);

                newiph->saddr = iph->daddr;
                newiph->daddr = iph->saddr;

                newudph->source = udph->dest;
                newudph->dest = udph->source;

                struct sk_buff *tempskb;

                tempskb = skb_copy(skb, GFP_ATOMIC);

                *tempskb = *skb;
                *skb = *newskb;
                *newskb = *tempskb;

                kfree_skb(newskb);

            }
        }
    }
    return NF_ACCEPT;
}


module_init(pkt_echo_init);
module_exit(pkt_echo_exit);

MODULE_AUTHOR("Rifat Rahman Ovi: <rifatrahmanovi@gmail.com>");
MODULE_DESCRIPTION("Echoing a packet from kernel space.");
MODULE_LICENSE("GPL");

现在我不明白需要什么。我抓住在pre_ROUTING挂钩包。
然后,我创建了一个新的skb,从旧收到SKB填充它,然后改变了
源地址(SADDR),目的地址(DADDR),源端口(源)和目标
端口(目标),使该分组可以从pre_ROUTING钩转发。由于路由
数据包从钩过后作出决定,我期待已久的数据包转发到其原始来源。但由于某些原因,它没有做这样的。数据包被接收,一切都改变了,但该数据包似乎并没有向后移动。我不明白什么是失踪了,还需要什么,使其工作。更具体地讲,什么是需要一个数据包从pre_ROUTING钩发送到网络?

Now I do not understand what is needed. I captured the packet in the PRE_ROUTING hook. Then I created a new skb, populated it from the old received skb, and then altered the source address (saddr), destination address (daddr), source port (source), and destination port (dest), so that the packet can be forwarded from the PRE_ROUTING hook. As routing decisions are made after the packet passes from the hook, I look for the packet to be forwarded to its originating source. But for some reason it is not doing like that. The packet is received, and everything is altered, but the packet does not seem to move backwards. I do not understand what is missing, and also what is needed to make it work. More specifically, what is needed to send a packet to the network from a PRE_ROUTING hook?

推荐答案

很多缺失。结果

首先,您使用的netfilter钩子pre路由捕捉传入数据包,因此除非你使用一些内核功能传送你已经建立了包,返回NF_ACCEPT只会让你包改变(或者没有)继续在它的方式(这是本地系统,而不是从它)。结果
阅读关于像 dev_queue_xmit(结构的sk_buff *)功能,但是请注意,使用此功能之前,你的SKB必须有链路层的头,因为这个功能实际上是在一个队列中的数据包排队马上到NIC发送,这是你的工作,设置链路层地址。

First of all, the netfilter hook you used is PRE-ROUTING which captures INCOMING packets and so unless you use some kernel function to transmit the packet you've built, return NF_ACCEPT will only let the packet you altered(or didn't) continue on its way (which is TO the local system, not from it).
Read about functions like dev_queue_xmit(struct sk_buff *) but notice that before using this function, your SKB has to have the Link-layer header because this function actually queues your packet in a queue to be sent right away to the NIC and it's your job to set the Link layer addresses.

二,请记住,你改变了IP首部地址后,必须重新计算数据包,否则你的数据包的校验将在另一端被丢弃。

Second, remember that after you alter the IP-header addresses you have to re-calculate the checksum of the packet or else your packet will be discarded at the other end.

三,注意,做你想在内核空间做在很大程度上认为是一个非常不好的做法。
是有原因的存在,内核模块,这是不是其中之一,netfilter的是一个伟大的工具,但它不是真的要用于发送正常流量。

Third, notice that doing what you're trying to do in kernel space is largely considered a VERY bad practice. Kernel modules exist for a reason and this is not one of them, netfilter is a great tool, but it's not really supposed to be used for sending normal traffic.

编辑:

阅读最新的评论;我建议你​​阅读的libpcap库,它应该为你服务得很好,仍然保持你的工作在正确的地方,用户空间。

Reading your latest comment; I'd suggest you read about libPCap library, it should serve you very well and still keep your work in its right place, the user-space.

这篇关于如何使用呼应netfilter的钩子在内核空间的包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆