Linux下使用netfilter进行IP包解析

来源:互联网 发布:阿里云主机登录密码 编辑:程序博客网 时间:2024/05/16 09:00

一.netfilter

最近因为工作的原因,要用到netfilter进行IP包的解析和过滤,所以对netfilter进行了一些了解,目前网上比较容易搜索到的应该是这两篇文章http://alexanderlaw.blog.hexun.com/8960896_d.html,《Linux netfilter 源码解析》,

https://www.ibm.com/developerworks/cn/linux/l-ntflt/,《Linux Netfilter实现机制和扩展技术》

这两篇文章对于Linux netfilter进行了一个详细的介绍,第一篇还对其源码进行了剖析,至于其具体实现,网上也能够找到一些例子,但是问题在于,那些例子大部分都是基于老版本的linux kernel,而在2.6以上的linux内核中,关于netfilter的变动是巨大的,整个变化主要体现在skubuff.h这个头文件中,2.6以上的linux内核抛弃了以前的那种union的方式,老版本中的nh不再存在。至于更加详细的内容变化,可以直接去Google,我就不再赘述了。

另外一个需要注意的是,很多网上的例子程序给的接口是这样的

static unsigned int sample(unsigned int hooknum,struct sk_buff ** skb,const struct net_device *in,const struct net_device *out,int (*okfn) (struct sk_buff *)){ return NF_ACCEPT;}

而实际上使用的接口应该是

static unsigned int sample(unsigned int hooknum,struct sk_buff * skb,const struct net_device *in,const struct net_device *out,int (*okfn) (struct sk_buff *)){ return NF_ACCEPT;}

请注意,不是sk_buff **,而是sk_buf*,这个问题我没弄清楚是别人的代码贴的有问题,还是因为内核版本不同造成的,但是请大家注意一下。


二.示例源码

#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/types.h>#include <linux/netdevice.h>#include <linux/skbuff.h>#include <linux/netfilter_ipv4.h>#include <linux/inet.h>#include <linux/in.h>#include <linux/ip.h>MODULE_LICENSE("GPL");#define NIPQUAD(addr) \  ((unsigned char *)&addr)[0], \  ((unsigned char *)&addr)[1], \  ((unsigned char *)&addr)[2], \  ((unsigned char *)&addr)[3]static unsigned int sample(unsigned int hooknum,struct sk_buff * skb,const struct net_device *in,const struct net_device *out,int (*okfn) (struct sk_buff *)){    __be32 sip,dip; if(skb){   struct sk_buff *sb = NULL;   sb = skb;   struct iphdr *iph;   iph  = ip_hdr(sb);   sip = iph->saddr;   dip = iph->daddr;   printk("Packet for source address: %d.%d.%d.%d\n destination address: %d.%d.%d.%d\n ", NIPQUAD(sip), NIPQUAD(dip));} return NF_ACCEPT;} struct nf_hook_ops sample_ops = {   .list =  {NULL,NULL},   .hook = sample,   .pf = PF_INET,   .hooknum = NF_INET_PRE_ROUTING,   .priority = NF_IP_PRI_FILTER+2 };static int __init sample_init(void) {  nf_register_hook(&sample_ops);  return 0;}static void __exit sample_exit(void) {  nf_unregister_hook(&sample_ops);} module_init(sample_init); module_exit(sample_exit);  MODULE_AUTHOR("chenkangrui"); MODULE_DESCRIPTION("sample");

netfilter模块所linux系统的一部分,所以为netfilter添加hook,其实所linux内核编程,所以需要用到linux内核态的头文件。

根据sample_ops可以看到,我在NF_INET_PRE_ROUTING(老版本这个变量是NF_IP_PRE_ROUTING,哎,真是DT啊)这个位置添加了一个hook,处理函数是sample(sample的功能是将所有能够截获的IP包的源IP和目标IP给打印出来)。

另外就是,NIPQUAD这个宏在新版本中被取消了,需要自己手动定义下。


三.编译和加载

我是在ubuntu上进行编译的

obj-m := sample.oKERNELBUILD :=/lib/modules/$(shell uname -r)/builddefault:make -C $(KERNELBUILD) M=$(shell pwd) modulesclean:rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers .tmp_versions

这是我使用的Makefile,需要注意的是,因为编译内核模块需要使用内核中的头文件,所以需要

sudo make

编译完成之后,将.ko文件加载到内核中就可以了

sudo insmod ./sample.ko

内核模块的输出printk不是直接打印到系统终端的,而是在系统日志中

你可以使用

dmesg

或者直接去/var/log/目录下查看syslog文件


原创粉丝点击