上篇中讲到了 netfilter的基本框架,现在 我写个 netfilter 框架下的module, 演示一下如何使用 netfilter module定制 自己的功能模块。 我个人使用的是linux 版本是3.13.5.不同的版本,内核可能会有差异,但是 总体是还是没有变化的。
netfilter 框架提供了 5个hook点。如下图
/* 这是hook点的定义, 对应于 上图中的NF_IP_xxxxx*/
enum nf_inet_hooks {
NF_INET_PRE_ROUTING,
NF_INET_LOCAL_IN,
NF_INET_FORWARD,
NF_INET_LOCAL_OUT,
NF_INET_POST_ROUTING,
NF_INET_NUMHOOKS
};
/*这是 协议的定义*/
enum {
NFPROTO_UNSPEC = 0,
NFPROTO_IPV4 = 2,
NFPROTO_ARP = 3,
NFPROTO_BRIDGE = 7,
NFPROTO_IPV6 = 10,
NFPROTO_DECNET = 12,
NFPROTO_NUMPROTO,
};
/*同一hook点上的module 优先级, 数值越小,优先级越高*/
enum nf_ip_hook_priorities {
NF_IP_PRI_FIRST = INT_MIN,
NF_IP_PRI_CONNTRACK_DEFRAG = -400,
NF_IP_PRI_RAW = -300,
NF_IP_PRI_SELINUX_FIRST = -225,
NF_IP_PRI_CONNTRACK = -200,
NF_IP_PRI_MANGLE = -150,
NF_IP_PRI_NAT_DST = -100,
NF_IP_PRI_FILTER = 0,
NF_IP_PRI_SECURITY = 50,
NF_IP_PRI_NAT_SRC = 100,
NF_IP_PRI_SELINUX_LAST = 225,
NF_IP_PRI_CONNTRACK_HELPER = 300,
NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
NF_IP_PRI_LAST = INT_MAX,
};
我们再看下 nf_hook_ops的定义。
struct nf_hook_ops {
struct list_head list;
/* User fills in from here down. */
nf_hookfn *hook; /*这里是 我们要定义处理的函数指针*/
struct module *owner;
void *priv;
u_int8_t pf; /*对应上图的协议NFPOTO_XXXXX*/
unsigned int hooknum; /*对应上图中的NF_INET_XXXXX*/
/* Hooks are ordered in ascending priority. */
int priority; /*优先级定义 , hook module并不是只有我们的module,所以用这个优先级安排模块的顺序。 对应上图NF_IP_PRI_XXXXX*/
};
/*nf_hookfn 的返回值类型*/
/* Responses from hook functions. */
#define NF_DROP 0
#define NF_ACCEPT 1
#define NF_STOLEN 2
#define NF_QUEUE 3
#define NF_REPEAT 4
#define NF_STOP 5
#define NF_MAX_VERDICT NF_STOP
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
static struct nf_hook_ops nfho; //struct holding set of hook function options
//function to be called by hook
static unsigned int hook_func(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
printk(KERN_INFO "get packet\n"); //dmesg 可以看到
return NF_ACCPET; //accept the packet
}
//Called when module loaded using 'insmod'
static int init_module()
{
nfho.hook = hook_func; //function to call when conditions below met
nfho.hooknum = NF_INET_PRE_ROUTING; //called right after packet recieved, first hook in Netfilter
nfho.pf = INETPROTO_IPV4; //IPV4 packets
nfho.priority = NF_IP_PRI_FIRST; //set to highest priority over all other hook functions
nf_register_hook(&nfho); //register hook
return 0; //return 0 for success
}
//Called when module unloaded using 'rmmod'
static void cleanup_module()
{
nf_unregister_hook(&nfho); //cleanup – unregister hook
}
module_init(init_module);
module_exit(cleanup_module);
这是 Makefile
ifneq ($(KERNELRELEASE),)
obj-m += xxxxxx.o /*对应的.c文件的名称*/
else
PWD := $(shell pwd);
KVER:= $(shell uname -r)
KDIR:=/lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf *.o *.mod.c *.ko
endif
这样 就可以了。然后编译执行 insmod xxx.ko 就可以了。 先到这里, 改天写一个比较完整的 带用户层管理的例子。