netfilterフック
Linuxのnetfilterフック関数の作成
ソースファイル(exp_netfilter1.c)
/* * exp_netfilter1.c */ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/skbuff.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/ip.h> #include <linux/udp.h> #define DRIVER_AUTHOR "KWATA" #define DRIVER_DESC "netfilter experiment" static struct nf_hook_ops nfho; //---------------------------------- 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 "[NFE] hook_func"); return NF_ACCEPT; } //---------------------------------- static int __init nfe_init(void) { printk(KERN_INFO "[NFE] nfe_init\n"); nfho.hook = hook_func; nfho.hooknum = NF_INET_PRE_ROUTING; nfho.pf = PF_INET; nfho.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho); return 0; } //---------------------------------- static void __exit nfe_exit(void) { printk(KERN_INFO "[NFE] nfe_exit\n"); nf_unregister_hook(&nfho); } module_init(nfe_init); module_exit(nfe_exit); MODULE_LICENSE("GPLv3"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC);
obj-m := exp_netfilter1.o
シェルから以下のように叩く。
$ make -C /usr/src/kernels/linux-3.6.6 M=`pwd` modules
すると、exp_netfilter1.koというカーネルモジュールが出来る。
これをinsmodすればカーネルに組み込まれる。
$ insmod exp_netfilter1.ko
パケットが流れるたびに/var/log/messagesに出力される。
ここでは、単にフックされることの確認のみであり、実際フック関数に渡されるsk_buffの中身を見てどうのこうの処理することまではしていない。
※messagesの監視は
$ tail -f messages
で更新された情報もリアルタイムに表示される。
※ネットでググった例ではフック関数登録時のhooknumにNF_IP_PRE_ROUTING
を設定していたが、/include/linux/netfilter_ipv4.hに定義されているNF_IP_PRE_ROUTINGは#ifndef __KERNEL__で囲まれている。ビルド時に__KERNEL__は定義された状態にあるらしく、この囲まれたブロックは有効になっていない。そのため、ソースにNF_IP_PRE_ROUTINGを書くとコンパイル時に未定義エラーが発生する。
実際にはnetfilter_ipv4.hのNF_IP_PRE_ROUTINGではなく、netfilter.hのNF_INET_PRE_ROUTINGを使えばよいようである。