• Creating a simple ‘hello world’ Netfilter module

    by  • October 7, 2009 • kernel module, linux, networking • 12 Comments

    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.

    About

    .NET developer at thetrainline.com, previously web developer at MRM Meteorite. Awarded a PhD in misbehaviour detection in wireless ad-hoc networks.A keen C# ASP.net developer bridging the gap with APIs and JavaScript frameworks, one web app at a time.

    http://www.paulkiddie.com

    12 Responses to Creating a simple ‘hello world’ Netfilter module

    1. Pingback: Paul Kiddie’s Blog : Creating a “hello world” kernel module in linux

    2. Srudeep K
      October 29, 2009 at 6:08 pm

      Dear Paul,

      I went through your simple kernel module to drop all packets using netfilter hook. I have tried to access the packet headers and data using sk_buff structure. I have analyzed the kernel source code () and found out that there are three fields in the structure to access packet headers (transport_header, network_header and mac_header). I tried to extract source and destination IP addresses using network_header field. Unfortunately, I ended up with segmentation faults. Is there way to access packet data using sk_buff structure (like in kernel 2.4)? If so how can we get a pointer to packet data? How can we extract source and destination addresses? Please help me out….

      Best Regards,
      Srudeep K

    3. Pingback: Paul Kiddie’s Blog : Creating a Netfilter kernel module which filters UDP packets

    4. November 2, 2009 at 12:15 pm

      Hi Srudeep,

      I was just in the process of writing my next post which deals with that, now live. You can find it at http://www.paulkiddie.com/2009/11/creating-a-netfilter-kernel-module-which-filters-udp-packets/. Just requires some straighforward modifications to the hook_func function — hope it helps,

      Paul

    5. Pankaj Tanwar
      November 22, 2009 at 3:38 am

      Thanks Paul It’s just I was trying to find

    6. sunil shah
      October 18, 2010 at 3:05 pm

      to get rid of freezing problem change
      sk_buff **skb
      to
      sk_buff *skb

      and
      socc_buff = * skb to
      socc_buff = skb

    7. dporter
      June 30, 2011 at 8:05 pm

      Paul,
      Great post and just what I need.

      I’m trying to build this on a later kernel:
      Linux ubuntu 2.6.35-22-generic #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 i686 GNU/Linux

      I can get the first program to compile, but the 2nd which introduces netfilter doesnt work for me.
      I get this error:
      error: ‘NF_IP_PRE_ROUTING’ undeclared (first use in this function)

      Looking at the includes, this makes sense because that symbol in netfilter_ipv4.h is hidden behind an
      ifndef __KERNEL__
      And of course __KERNEL__ is defined so that makes NF_IP_PRE_ROUTING not defined.

      Am I doing something wrong? or is my kernel just too different?

      Thanks.

    8. driquet
      July 11, 2011 at 12:12 pm

      I just encounter the same error.
      I don’t think this header is build for kernel module.

      But, an :
      7 #undef __KERNEL__
      8 #include
      9 #define __KERNEL__
      has solved the problem.

      Is there any other solution that isn’t that dirty ?

    9. driquet
      July 11, 2011 at 12:23 pm

      To avoid that error, remplace :
      nfho.hooknum = NF_IP_PRE_ROUTING;
      by
      nfho.hooknum = NF_INET_PRE_ROUTING;
      .

    10. kasireddi
      November 7, 2011 at 8:35 am

      hi PAUL,

      i got probelm as NF_IP_PRE_ROUTING not defined.
      i resolved as above by changing
      nfho.hooknum = NF_IP_PRE_ROUTING;
      to
      nfho.hooknum = NF_INET_PRE_ROUTING;

      but if i do $sudo insmod firewall1.ko i got following

      insmod: error inserting ‘firewall1.ko’: -1 Invalid parameters

      how to resolve it ?? please help

    11. kasireddi
      November 7, 2011 at 9:41 am

      in $ dmesg
      nf_register_hook is unknown….. like this coming

      give me solution to overcome this . please .

    12. amiram cohen
      July 6, 2017 at 12:56 pm

      I`ve got this error:
      /home/ubuntu/Desktop/nf/drop.c:19:18: error: ‘NF_IP_PRE_ROUTING’ undeclared (first use in this function)

      My solution is to replace the line
      nfho.hooknum = NF_IP_PRE_ROUTING;

      with this:
      nfho.hooknum = 0; // NF_IP_PRE_ROUTING;

      `0` is the enum for NF_IP_PRE_ROUTING as described in /usr/src/linux-headers-XXXX/include/uapi/linux/netfilter_ipv4.h
      .

    Leave a Reply

    Your email address will not be published. Required fields are marked *