Paul Kiddie

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 hook
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 "packet dropped\\n");                                             //log to var/log/messages
return NF\_DROP;                                                                   //drops the packet
}
//Called when module loaded using 'insmod'
int init\_module()
{
nfho.hook = hook\_func;                       //function to call when conditions below met
nfho.hooknum = NF\_IP\_PRE\_ROUTING;            //called right after packet recieved, first hook in Netfilter
nfho.pf = PF\_INET;                           //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'
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.


👋 I'm Paul Kiddie, a software engineer working in London. I'm currently working as a Principal Engineer at trainline.