当前位置:酷酷问答>生活百科>netfilter的实现及数据包的修改

netfilter的实现及数据包的修改

2024-10-22 10:30:21 编辑:zane 浏览量:555

netfilter的实现及数据包的修改

的有关信息介绍如下:

netfilter的实现及数据包的修改

通俗的说,netfilter的架构就是在整个网络流程的若干位置放置了一些检测点(HOOK),而在每个检测点上登记了一些处理函数进行处理(如包过滤,NAT等,甚至可以是 用户自定义的功能)。

IP层的五个HOOK点的位置如下图所示

enumnf_inet_hooks{

NF_INET_PRE_ROUTING,

NF_INET_LOCAL_IN,

NF_INET_FORWARD,

NF_INET_LOCAL_OUT,

NF_INET_POST_ROUTING,

NF_INET_NUMHOOKS

};

:NF_IP_PRE_ROUTING:刚刚进入网络层的数据包通过此点(刚刚进行完版本号,校验

和等检测), 目的地址转换在此点进行;

:NF_IP_LOCAL_IN:经路由查找后,送往本机的通过此检查点,INPUT包过滤在此点进行;

:NF_IP_FORWARD:要转发的包通过此检测点,FORWARD包过滤在此点进行;

:NF_IP_POST_ROUTING:所有马上便要通过网络设备出去的包通过此检测点,内置的源地址转换功能(包括地址伪装)在此点进行;

:NF_IP_LOCAL_OUT:本机进程发出的包通过此检测点,OUTPUT包过滤在此点进行。

首先,定义一个nf_hook_ops结构体,选定要挂取的钩子点

static struct nf_hook_ops nfho = {

.hook = my_hookfn,

.pf = PF_INET,

.hooknum = NF_INET_PRE_ROUTING,

.priority = NF_IP_PRI_FIRST,

.owner = THIS_MODULE,

};

第二步,写好my_hookfn这个hook函数,即要实现的功能(此处是将其接收包的源IP地址改成100.100.100.100.

unsigned int my_hookfn(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;

iph = ip_hdr(skb);

/* log the original src IP */

printk(KERN_INFO"src IP %pI4\n", &iph->saddr);

/* modify the packet's src IP */

iph->saddr = in_aton("100.100.100.100");

return NF_ACCEPT;

}

注册函数会把nf_hook_ops放入nf_hooks相应的位置中。

int nf_register_hook(struct nf_hook_ops *reg)

{

struct nf_hook_ops *elem;

int err;

err = mutex_lock_interruptible(&nf_hook_mutex);

if (err < 0)

return err;

list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {

if (reg->priority < elem->priority)

break;

}

list_add_rcu(®->list, elem->list.prev); /* 把netfilter实例添加到队列中 */

mutex_unlock(&nf_hook_mutex);

return 0;

}

注销函数

void nf_unregister_hook(struct nf_hook_ops *reg)

{

mutex_lock(&nf_hook_mutex);

list_del_rcu(®->list); /* 把netfilter实例从队列中删除 */

mutex_unlock(&nf_hook_mutex);

synchronize_net();

}

然后进行模块的注册与注销

static int __init http_init(void)

{

if (nf_register_hook(&nfho)) {

printk(KERN_ERR"nf_register_hook() failed\n");

return -1;

}

return 0;

}

static void __exit http_exit(void)

{

nf_unregister_hook(&nfho);

}

这是完整的源代码,并取名http.c

#include

#include

#include

#include

#include

#include

/**

* Hook function to be called.

* We modify the packet's src IP.

*/

unsigned int my_hookfn(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;

iph = ip_hdr(skb);

/* log the original src IP */

printk(KERN_INFO"src IP %pI4\n", &iph->saddr);

/* modify the packet's src IP */

iph->saddr = in_aton("100.100.100.100");

return NF_ACCEPT;

}

/* A netfilter instance to use */

static struct nf_hook_ops nfho = {

.hook = my_hookfn,

.pf = PF_INET,

.hooknum = NF_INET_PRE_ROUTING,

.priority = NF_IP_PRI_FIRST,

.owner = THIS_MODULE,

};

static int __init http_init(void)

{

if (nf_register_hook(&nfho)) {

printk(KERN_ERR"nf_register_hook() failed\n");

return -1;

}

return 0;

}

static void __exit http_exit(void)

{

nf_unregister_hook(&nfho);

}

module_init(http_init);

module_exit(http_exit);

MODULE_AUTHOR("flyking");

MODULE_LICENSE("GPL");

然后编写Makefile,此处是Makefile源码

ifneq ($(KERNELRELEASE),)

obj-m += http.o

else

PWD := $(shell pwd)

KVER := $(shell uname -r)

KDIR := /lib/modules/$(KVER)/build

default:

$(MAKE) -C $(KDIR) M=$(PWD) modules

all:

make -C $(KDIR) M=$(PWD) modules

clean:

rm -rf *.o *.mod.c *.ko *.symvers *.order *.makers

endif

编写好了http.c和Makefile,将其用动态模块的方式挂载在Linux系统内核。进行编译make,即可生成所需要的http.ko文件,如图所示

然后动态加载insmod这个模块,lsmod查看即可看来系统内有这个模块,如图所示

然后我们用wireshark抓了上百度的过程,就看到了我们的接收的包源地址被改成了100.100.100.100.

版权声明:文章由 酷酷问答 整理收集,来源于互联网或者用户投稿,如有侵权,请联系我们,我们会立即处理。如转载请保留本文链接:https://www.kukuwd.com/life/89768.html
热门文章