Creating a simple 'hello world' Netfilter module
October 07, 2009
This is the second part of the series in creating a NetFilter module for Ubuntu 8.04 (running linux kernel 2.6.24-23). In it I’ll write a simple Netfilter module as a kernel module that simply drops all packets and logs dropped packets to /var/log/messages. In order to implement this we take the code for the kernel module we coded up in part 1, which we’ll add the relevant Netfilter logic to.
For an in-depth look at the structure of Netfilter and code upon which this article is based upon, check out http://www.linuxjournal.com/article/7184.
To create a simple Netfilter hook requires several steps. We write a function which we call hook_func
which is called whenever a packet comes in that meets the conditions of nf_hook_ops
. This function performs the appropriate logic, which in our case is to drop packets. We fill in the nf_hook_ops
structure which defines the particular Netfilter hook to target target, the priority of it (very important if you have multiple hooks), and gives the type of packet to target (in this case IPV4), and bind hook_func
to it.
In the previous entry we defined the methods init_module()
and cleanup_module()
. For the Netfilter module, init_module()
should now contain the code to set up the nf_hook_o
ps
structure and register the hook with Netfilter. In cleanup_module()
we put any code required to clean up. In this case, it corresponds to the code to unregister the hook from Netfilter.
We need to include several standard header files – if you have installed the linux-headers
package for your distribution this should be enough and this file should compile using the Makefile
we wrote in part 1 just fine.
Here is the complete code:
//‘Hello World’ netfilter hooks example //For any packet, we drop it, and log fact to /var/log/messages
#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 hookunsigned 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 "packet dropped\\n"); //log to var/log/messagesreturn NF\_DROP; //drops the packet}//Called when module loaded using 'insmod'int init\_module(){nfho.hook = hook\_func; //function to call when conditions below metnfho.hooknum = NF\_IP\_PRE\_ROUTING; //called right after packet recieved, first hook in Netfilternfho.pf = PF\_INET; //IPV4 packetsnfho.priority = NF\_IP\_PRI\_FIRST; //set to highest priority over all other hook functionsnf\_register\_hook(&nfho); //register hookreturn 0; //return 0 for success}//Called when module unloaded using 'rmmod'void cleanup\_module(){nf\_unregister\_hook(&nfho); //cleanup – unregister hook}
Now if you compile the module using the procedure described in part 1, and install the module using insmod
, you can test the module works by trying to ping, e.g. www.google.com. This will fail, because all packets are being dropped, and if you check /var/log/messages before and after you ping you should see appropriate “packet dropped” log messages on the end of the log file.
So we have a very simple and not very useful Netfilter module - next article I’ll extend the Netfilter module to access particular fields on the packet and act accordingly based on the protocol number. There have been some significant changes in kernel 2.6 in the way you access packet headers, which we will investigate then.