How to Filter Network Packets using Netfilter–Part 2 Implement the Hook Function

This is a follow up of the previous blog: How to Filter Network Packets using Netfilter – Part 1 Netfilter Hooks. You should read the previous blog first in order to follow this tutorial.

The Hook Function Prototype

Once a hook function has registered with any of the 5 netfilter hooks, it’ will be called when a network packets go through the hook in the network stack. Recall the previous blog, the registered function is as below,

unsigned int hook_func_in(unsigned int hooknum, 

                struct sk_buff *skb,          

                const struct net_device *in, 

                const struct net_device *out,         

                int (*okfn)(struct sk_buff *))

hooknum indicates one of the 5 hook types (NF_INET_PRE_ROUTING, NF_INET_LOCAL_IN, NF_INET_FORWARD, NF_INET_LOCAL_OUT, NF_INET_POST_ROUTING) covered in previous blog.

sbk is a pointer to the network packet buffer, which is defined in /lib/modules/$(uname -r)/build/include/linux/skbuff.h. The details about this packet buffer is covered in next section.

in and out are two pointers to the net_device structure, which are what Linux kernel uses to describe network interface, as defined in /lib/modules/$(uname -r)/build/include/linux/netdevice.h. In the hook function, describes the network interface the packet pass through. Therefore, depending on the packets traversal, either in or out will be NULL.

okfn is a function pointer enables registering of a callback function triggered when all the functions registered with this hook returned NF_ACCEPT, thus “oking” the packets.

When a registered function is called, it can do one of the five things and return the corresponding value, as defined in netfilter.h,

NF_ACCEPT: let the packet pass.

NF_DROP: drop the packet.

NF_STOLEN: take the packet and don’t let the packet pass.

NF_QUEUE: queue the packet, usually for userspace handling.

NF_REPEAT: call the hook again.

Access the Network Packet Buffer

skb in the hook function enables one to access the network packet buffer and retrieve the needed information easily. Probably three most wanted information are the transport_header, network_header and mac_header fields defined in sk_buff.

The following functions are defined in skbuff.h to access these information,

static inline unsigned char *skb_mac_header(const struct sk_buff *skb);

static inline unsigned char *skb_network_header(const struct sk_buff *skb);

static inline unsigned char *skb_transport_header(const struct sk_buff *skb);

For example, if we want to get source and destination IP addresses of a packet caught in the hook function above, the code below can get it,

struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);

unsigned int src_ip = (unsigned int)ip_header->saddr;

unsigned int dest_ip = (unsigned int)ip_header->daddr;

One thing needs to mention is that skb_transport_header doesn’t always work as expected. This function works when the network packets are processed by certain functions of netfilter which is at the transport layer of netfilter implementation.

For example, we want to get the source and destination port of UDP packet.

When a packet goes out, it goes from application layer, to transport layer, then network layer, and so on. These functions are normally executed and skb_transport_header works well. Therefore, code below works,

struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb); 

struct udphdr *udp_header;

if (ip_header->protocol==17) {        

    udp_header = (struct udphdr *)skb_transport_header(skb);        

    src_port = (unsigned int)ntohs(udp_header->source);        

    dest_port = (unsigned int)ntohs(udp_header->dest);    

}

When a packet goes in from wire, it travels from physical layer, data link layer, network layer upwards, therefore it might not go through the functions defined in netfilter for skb_transport_header to work. The code above doesn’t work in this case, but there is a simple hack,

struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);    

struct udphdr *udp_header;

if (ip_header->protocol==17) {        

    udp_header = (struct udphdr *)(skb_transport_header(skb)+20);        

    src_port = (unsigned int)ntohs(udp_header->source);        

    dest_port = (unsigned int)ntohs(udp_header->dest);    

}

The skb_transport_header actually returns a pointer to the IP header, and the code skip

the IP header by +20 (the length of typical IP header).

A Kernel Module using Netfilter

Below is a kernel module source code, it blocks/unblocks network traffic according to the rules specified in add_a_test_rule() function. It serves as a template for the Linux firewall kernel module part.

#include <linux/module.h>

 

#include <linux/kernel.h>

 

#include <linux/proc_fs.h>

 

#include <linux/list.h>

 

#include <asm/uaccess.h>

 

#include <linux/udp.h>

 

#include <linux/tcp.h>

 

#include <linux/skbuff.h>

 

#include <linux/ip.h>

 

#include <linux/netfilter.h>

 

#include <linux/netfilter_ipv4.h>

 

 

 

MODULE_LICENSE("GPL");

 

MODULE_DESCRIPTION("linux-simple-firewall");

 

MODULE_AUTHOR("Liu Feipeng/roman10");

 

 

/*structure for firewall policies*/

 

struct mf_rule_desp {

 

    unsigned char in_out;

 

    char *src_ip;

 

    char *src_netmask;

 

    char *src_port;

 

    char *dest_ip;

 

    char *dest_netmask;

 

    char *dest_port;

 

    unsigned char proto;

 

    unsigned char action;

 

};

 

 

/*structure for firewall policies*/

 

struct mf_rule {

 

    unsigned char in_out;        //0: neither in nor out, 1: in, 2: out

 

    unsigned int src_ip;        //

 

    unsigned int src_netmask;        //

 

    unsigned int src_port;        //0~2^32

 

    unsigned int dest_ip;

 

    unsigned int dest_netmask;

 

    unsigned int dest_port;

 

    unsigned char proto;        //0: all, 1: tcp, 2: udp

 

    unsigned char action;        //0: for block, 1: for unblock

 

    struct list_head list;

 

};

 

static struct mf_rule policy_list;

 

 

 

//the structure used to register the function

 

static struct nf_hook_ops nfho;

 

static struct nf_hook_ops nfho_out;

 

unsigned int port_str_to_int(char *port_str) {

    unsigned int port = 0;    

    int i = 0;

    if (port_str==NULL) {

        return 0;

    } 

    while (port_str[i]!='') {

        port = port*10 + (port_str[i]-'0');

        ++i;

    }

    return port;

}

 

unsigned int ip_str_to_hl(char *ip_str) {

    /*convert the string to byte array first, e.g.: from "131.132.162.25" to [131][132][162][25]*/

    unsigned char ip_array[4];

    int i = 0;

    unsigned int ip = 0;

    if (ip_str==NULL) {

        return 0; 

    }

    memset(ip_array, 0, 4);

    while (ip_str[i]!='.') {

        ip_array[0] = ip_array[0]*10 + (ip_str[i++]-'0');

    }

    ++i;

    while (ip_str[i]!='.') {

        ip_array[1] = ip_array[1]*10 + (ip_str[i++]-'0');

    }

    ++i;

    while (ip_str[i]!='.') {

        ip_array[2] = ip_array[2]*10 + (ip_str[i++]-'0');

    }

    ++i;

    while (ip_str[i]!='') {

        ip_array[3] = ip_array[3]*10 + (ip_str[i++]-'0');

    }

    /*convert from byte array to host long integer format*/

    ip = (ip_array[0] << 24);

    ip = (ip | (ip_array[1] << 16));

    ip = (ip | (ip_array[2] << 8));

    ip = (ip | ip_array[3]);

    //printk(KERN_INFO "ip_str_to_hl convert %s to %un", ip_str, ip);

    return ip;

}

 

/*check the two input IP addresses, see if they match, only the first few bits (masked bits) are compared*/

 

bool check_ip(unsigned int ip, unsigned int ip_rule, unsigned int mask) {

 

    unsigned int tmp = ntohl(ip);    //network to host long

 

    int cmp_len = 32;

 

    int i = 0, j = 0;

 

    printk(KERN_INFO "compare ip: %u <=> %un", tmp, ip_rule);

 

    if (mask != 0) {

 

       //printk(KERN_INFO "deal with maskn");

 

       //printk(KERN_INFO "mask: %d.%d.%d.%dn", mask[0], mask[1], mask[2], mask[3]);

 

       cmp_len = 0;

 

       for (i = 0; i < 32; ++i) {

 

      if (mask & (1 << (32-1-i)))

 

         cmp_len++;

 

      else

 

         break;

 

       }

 

    }

    /*compare the two IP addresses for the first cmp_len bits*/

 

    for (i = 31, j = 0; j < cmp_len; --i, ++j) {

 

        if ((tmp & (1 << i)) != (ip_rule & (1 << i))) {

 

            printk(KERN_INFO "ip compare: %d bit doesn't matchn", (32-i));

 

            return false;

 

        }

 

    }

 

    return true;

 

}

 

//the hook function itself: regsitered for filtering outgoing packets

 

unsigned int hook_func_out(unsigned int hooknum, struct sk_buff *skb, 

 

        const struct net_device *in, const struct net_device *out,

 

        int (*okfn)(struct sk_buff *)) {

 

   /*get src address, src netmask, src port, dest ip, dest netmask, dest port, protocol*/

 

   struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);

 

   struct udphdr *udp_header;

 

   struct tcphdr *tcp_header;

 

   struct list_head *p;

 

   struct mf_rule *a_rule;

 

   int i = 0;

 

   /**get src and dest ip addresses**/

 

   unsigned int src_ip = (unsigned int)ip_header->saddr;

 

   unsigned int dest_ip = (unsigned int)ip_header->daddr;

 

   unsigned int src_port = 0;

 

   unsigned int dest_port = 0;

 

   /***get src and dest port number***/

 

   if (ip_header->protocol==17) {

 

       udp_header = (struct udphdr *)skb_transport_header(skb);

 

       src_port = (unsigned int)ntohs(udp_header->source);

 

       dest_port = (unsigned int)ntohs(udp_header->dest);

 

   } else if (ip_header->protocol == 6) {

 

       tcp_header = (struct tcphdr *)skb_transport_header(skb);

 

       src_port = (unsigned int)ntohs(tcp_header->source);

 

       dest_port = (unsigned int)ntohs(tcp_header->dest);

 

   }

 

   printk(KERN_INFO "OUT packet info: src ip: %u, src port: %u; dest ip: %u, dest port: %u; proto: %un", src_ip, src_port, dest_ip, dest_port, ip_header->protocol); 

 

   //go through the firewall list and check if there is a match

 

   //in case there are multiple matches, take the first one

 

   list_for_each(p, &policy_list.list) {

 

       i++;

 

       a_rule = list_entry(p, struct mf_rule, list);

       printk(KERN_INFO "rule %d: a_rule->in_out = %u; a_rule->src_ip = %u; a_rule->src_netmask=%u; a_rule->src_port=%u; a_rule->dest_ip=%u; a_rule->dest_netmask=%u; a_rule->dest_port=%u; a_rule->proto=%u; a_rule->action=%un", i, a_rule->in_out, a_rule->src_ip, a_rule->src_netmask, a_rule->src_port, a_rule->dest_ip, a_rule->dest_netmask, a_rule->dest_port, a_rule->proto, a_rule->action);

 

       //if a rule doesn't specify as "out", skip it

 

       if (a_rule->in_out != 2) {

 

           printk(KERN_INFO "rule %d (a_rule->in_out: %u) not match: out packet, rule doesn't specify as outn", i, a_rule->in_out);

 

           continue;

 

       } else {

 

           //check the protocol

 

           if ((a_rule->proto==1) && (ip_header->protocol != 6)) {

 

               printk(KERN_INFO "rule %d not match: rule-TCP, packet->not TCPn", i);

 

               continue;

 

           } else if ((a_rule->proto==2) && (ip_header->protocol != 17)) {

 

               printk(KERN_INFO "rule %d not match: rule-UDP, packet->not UDPn", i);

 

               continue;

 

           }

 

           //check the ip address

 

           if (a_rule->src_ip==0) {

 

              //rule doesn't specify ip: match

 

           } else {

 

              if (!check_ip(src_ip, a_rule->src_ip, a_rule->src_netmask)) {

 

                  printk(KERN_INFO "rule %d not match: src ip mismatchn", i);

 

                  continue;

 

              }

 

           }

 

           if (a_rule->dest_ip == 0) {

 

               //rule doesn't specify ip: match

 

           } else {

 

               if (!check_ip(dest_ip, a_rule->dest_ip, a_rule->dest_netmask)) {

 

                   printk(KERN_INFO "rule %d not match: dest ip mismatchn", i);

 

                   continue;

 

               }

 

           }

 

           //check the port number

 

           if (a_rule->src_port==0) {

 

               //rule doesn't specify src port: match

 

           } else if (src_port!=a_rule->src_port) {

 

               printk(KERN_INFO "rule %d not match: src port dismatchn", i);

 

               continue;

 

           }

 

           if (a_rule->dest_port == 0) {

 

               //rule doens't specify dest port: match

 

           }

 

           else if (dest_port!=a_rule->dest_port) {

 

               printk(KERN_INFO "rule %d not match: dest port mismatchn", i);

 

               continue;

 

           }

 

           //a match is found: take action

 

           if (a_rule->action==0) {

 

               printk(KERN_INFO "a match is found: %d, drop the packetn", i);

 

              printk(KERN_INFO "---------------------------------------n");

 

               return NF_DROP;

 

           } else {

 

               printk(KERN_INFO "a match is found: %d, accept the packetn", i);

 

              printk(KERN_INFO "---------------------------------------n");

 

               return NF_ACCEPT;

 

           }

 

       }

 

   }

 

   printk(KERN_INFO "no matching is found, accept the packetn");

 

   printk(KERN_INFO "---------------------------------------n");

 

   return NF_ACCEPT;            

 

}

 

 

 

 

 

//the hook function itself: registered for filtering incoming packets

 

unsigned int hook_func_in(unsigned int hooknum, struct sk_buff *skb, 

 

        const struct net_device *in, const struct net_device *out,

 

        int (*okfn)(struct sk_buff *)) {

 

   /*get src address, src netmask, src port, dest ip, dest netmask, dest port, protocol*/

 

   struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);

 

   struct udphdr *udp_header;

 

   struct tcphdr *tcp_header;

 

   struct list_head *p;

 

   struct mf_rule *a_rule;

 

   int i = 0;

 

   /**get src and dest ip addresses**/

 

   unsigned int src_ip = (unsigned int)ip_header->saddr;

 

   unsigned int dest_ip = (unsigned int)ip_header->daddr;

 

   unsigned int src_port = 0;

 

   unsigned int dest_port = 0;

 

   /***get src and dest port number***/

 

   if (ip_header->protocol==17) {

 

       udp_header = (struct udphdr *)(skb_transport_header(skb)+20);

 

       src_port = (unsigned int)ntohs(udp_header->source);

 

       dest_port = (unsigned int)ntohs(udp_header->dest);

 

   } else if (ip_header->protocol == 6) {

 

       tcp_header = (struct tcphdr *)(skb_transport_header(skb)+20);

 

       src_port = (unsigned int)ntohs(tcp_header->source);

 

       dest_port = (unsigned int)ntohs(tcp_header->dest);

 

   }

 

   printk(KERN_INFO "IN packet info: src ip: %u, src port: %u; dest ip: %u, dest port: %u; proto: %un", src_ip, src_port, dest_ip, dest_port, ip_header->protocol); 

 

   //go through the firewall list and check if there is a match

 

   //in case there are multiple matches, take the first one

 

   list_for_each(p, &policy_list.list) {

 

       i++;

 

       a_rule = list_entry(p, struct mf_rule, list);

printk(KERN_INFO "rule %d: a_rule->in_out = %u; a_rule->src_ip = %u; a_rule->src_netmask=%u; a_rule->src_port=%u; a_rule->dest_ip=%u; a_rule->dest_netmask=%u; a_rule->dest_port=%u; a_rule->proto=%u; a_rule->action=%un", i, a_rule->in_out, a_rule->src_ip, a_rule->src_netmask, a_rule->src_port, a_rule->dest_ip, a_rule->dest_netmask, a_rule->dest_port, a_rule->proto, a_rule->action);

 

       //if a rule doesn't specify as "in", skip it

 

       if (a_rule->in_out != 1) {

 

           printk(KERN_INFO "rule %d (a_rule->in_out:%u) not match: in packet, rule doesn't specify as inn", i, a_rule->in_out);

 

           continue;

 

       } else {

 

           //check the protocol

 

           if ((a_rule->proto==1) && (ip_header->protocol != 6)) {

 

               printk(KERN_INFO "rule %d not match: rule-TCP, packet->not TCPn", i);

 

               continue;

 

           } else if ((a_rule->proto==2) && (ip_header->protocol != 17)) {

 

               printk(KERN_INFO "rule %d not match: rule-UDP, packet->not UDPn", i);

 

               continue;

 

           }

 

           //check the ip address

 

           if (a_rule->src_ip==0) {

 

              //

 

           } else {

 

              if (!check_ip(src_ip, a_rule->src_ip, a_rule->src_netmask)) {

 

                  printk(KERN_INFO "rule %d not match: src ip mismatchn", i);

 

                  continue;

 

              }

 

           }

 

           if (a_rule->dest_ip == 0) {

 

               //

 

           } else {

 

               if (!check_ip(dest_ip, a_rule->dest_ip, a_rule->dest_netmask)) {

 

                  printk(KERN_INFO "rule %d not match: dest ip mismatchn", i);                  

 

                  continue;

 

               }

 

           }

 

           //check the port number

 

           if (a_rule->src_port==0) {

 

               //rule doesn't specify src port: match

 

           } else if (src_port!=a_rule->src_port) {

 

               printk(KERN_INFO "rule %d not match: src port mismatchn", i);

 

               continue;

 

           }

 

           if (a_rule->dest_port == 0) {

 

               //rule doens't specify dest port: match

 

           }

 

           else if (dest_port!=a_rule->dest_port) {

 

               printk(KERN_INFO "rule %d not match: dest port mismatchn", i);

 

               continue;

 

           }

 

           //a match is found: take action

 

           if (a_rule->action==0) {

 

               printk(KERN_INFO "a match is found: %d, drop the packetn", i);

 

               printk(KERN_INFO "---------------------------------------n");

 

               return NF_DROP;

 

           } else {

 

               printk(KERN_INFO "a match is found: %d, accept the packetn", i);

 

               printk(KERN_INFO "---------------------------------------n");

 

               return NF_ACCEPT;

 

           }

 

       }

 

   }

 

   printk(KERN_INFO "no matching is found, accept the packetn");

 

   printk(KERN_INFO "---------------------------------------n");

 

   return NF_ACCEPT;                

 

}

 

void add_a_rule(struct mf_rule_desp* a_rule_desp) {

    struct mf_rule* a_rule;

    a_rule = kmalloc(sizeof(*a_rule), GFP_KERNEL);

    if (a_rule == NULL) {

        printk(KERN_INFO "error: cannot allocate memory for a_new_rulen");

        return;

    }

    a_rule->in_out = a_rule_desp->in_out;

    a_rule->src_ip = ip_str_to_hl(a_rule_desp->src_ip);

    a_rule->src_netmask = ip_str_to_hl(a_rule_desp->src_netmask);

    a_rule->src_port = port_str_to_int(a_rule_desp->src_port);

    a_rule->dest_ip = ip_str_to_hl(a_rule_desp->dest_ip);

    a_rule->dest_netmask = ip_str_to_hl(a_rule_desp->dest_netmask);

    a_rule->dest_port = port_str_to_int(a_rule_desp->dest_port);

    a_rule->proto = a_rule_desp->proto;

    a_rule->action = a_rule_desp->action;

    printk(KERN_INFO "add_a_rule: in_out=%u, src_ip=%u, src_netmask=%u, src_port=%u, dest_ip=%u, dest_netmask=%u, dest_port=%u, proto=%u, action=%un", a_rule->in_out, a_rule->src_ip, a_rule->src_netmask, a_rule->src_port, a_rule->dest_ip, a_rule->dest_netmask, a_rule->dest_port, a_rule->proto, a_rule->action);

    INIT_LIST_HEAD(&(a_rule->list));

    list_add_tail(&(a_rule->list), &(policy_list.list));

}

 

void add_a_test_rule(void) {

    struct mf_rule_desp a_test_rule;

    printk(KERN_INFO "add_a_test_rulen");

    a_test_rule.in_out = 2;

    //a_test_rule.src_ip = (char *)kmalloc(6, GFP_KERNEL);

    //a_test_rule.src_ip = "137.132.165.27";

    //a_test_rule.src_ip = NULL;

    a_test_rule.src_ip = (char *)kmalloc(16, GFP_KERNEL);

    strcpy(a_test_rule.src_ip, "10.0.2.15");   //change 10.0.2.15 to your own IP

    //a_test_rule.src_netmask = NULL;

    a_test_rule.src_netmask = (char *)kmalloc(16, GFP_KERNEL);

    strcpy(a_test_rule.src_netmask, "255.255.255.255");

    a_test_rule.src_port = NULL;

    //a_test_rule.dest_ip = (char *)kmalloc(16, GFP_KERNEL);

    //strcpy(a_test_rule.dest_ip, "137.132.165.25");

    a_test_rule.dest_ip = NULL;

    //a_test_rule.dest_netmask = (char *)kmalloc(16, GFP_KERNEL);

    //strcpy(a_test_rule.dest_netmask, "255.255.255.0");

    a_test_rule.dest_netmask = NULL;

    //a_test_rule.dest_port = "9000";

    a_test_rule.dest_port = NULL;

    a_test_rule.proto = 6;

    a_test_rule.action = 0;

    add_a_rule(&a_test_rule);

}

 

 

 

void delete_a_rule(int num) {

 

    int i = 0;

 

    struct list_head *p, *q;

 

    struct mf_rule *a_rule;

 

    printk(KERN_INFO "delete a rule: %dn", num);

 

    list_for_each_safe(p, q, &policy_list.list) {

 

        ++i;

 

        if (i == num) {

 

            a_rule = list_entry(p, struct mf_rule, list);

 

            list_del(p);

 

            kfree(a_rule);

 

            return;

 

        }

 

    }

 

}

 

 

 

/* Initialization routine */

 

int init_module() {

    printk(KERN_INFO "initialize kernel modulen");

 

    INIT_LIST_HEAD(&(policy_list.list));

 

    /* Fill in the hook structure for incoming packet hook*/

 

    nfho.hook = hook_func_in;

 

    nfho.hooknum = NF_INET_LOCAL_IN;

 

    nfho.pf = PF_INET;

 

    nfho.priority = NF_IP_PRI_FIRST;

 

    nf_register_hook(&nfho);         // Register the hook

 

    /* Fill in the hook structure for outgoing packet hook*/

 

    nfho_out.hook = hook_func_out;

 

    nfho_out.hooknum = NF_INET_LOCAL_OUT;

 

    nfho_out.pf = PF_INET;

 

    nfho_out.priority = NF_IP_PRI_FIRST;

 

    nf_register_hook(&nfho_out);    // Register the hook

    /*this part of code is for testing purpose*/

    add_a_test_rule();

 

    return 0;

 

}

 

 

 

/* Cleanup routine */

 

void cleanup_module() {

 

    struct list_head *p, *q;

 

    struct mf_rule *a_rule;

 

    nf_unregister_hook(&nfho);

 

    nf_unregister_hook(&nfho_out);

 

    printk(KERN_INFO "free policy listn");

 

    list_for_each_safe(p, q, &policy_list.list) {

 

        printk(KERN_INFO "free onen");

 

        a_rule = list_entry(p, struct mf_rule, list);

 

        list_del(p);

 

        kfree(a_rule);

 

    }

 

    printk(KERN_INFO "kernel module unloaded.n");

 

}

To compile the kernel module, using the following makefile (suppose you save the file to netfilter.c),

obj-m += netfilter.o

all:

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

To insert the kernel module and remove the kernel module,

sudo insmod netfilter.ko

sudo rmmod netfilter

Note:

This post is part of the tutorial: How to write a Linux Firewall in Less than 1000 Lines

Part 1: Overview

Part 2: Command Line Arguments Parsing in glibc

Part 3.1: Linux Kernel Module Basics and Hello World

Part 3.2: Linux Kernel Programming – Linked List

Part 3.3 Linux Kernel Programming – Memory Allocation

Part 4.1: How to Filter Network Packets using Netfilter – Part 1 Netfilter Hooks

Part 4.2 How to Filter Network Packets using Netfilter – Part 2 Implement the Hook Function

Part 5: Linux procfs Virtual File System

Part 6: Put Everything Together

References:

The Netfilter Architecture of Linux 2.4: http://www.6test.edu.cn/~lujx/linux_networking/0131777203_ch19lev1sec3.html

6 thoughts on “How to Filter Network Packets using Netfilter–Part 2 Implement the Hook Function”

  1. Hi,
    There’s an error in some of your code samples, the share tools replace the end of the code, can you solve it plz ?

  2. Is there an example about how to implement NF_QUEUE or NF_STOLEN as most of the blogs give samples about DROP and ACCEPT?

  3. I want to write a kernel module to detect and drop TELNET traffic( comming to port 23).. I have written the following code but it is not working.. pls help

    #define __KERNEL__
    #define MODULE
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    static struct nf_hook_ops netfilter_ops;
    static unsigned char *ip_address = “xC0xA8x03x7c”;
    static char *interface = “lo”;
    unsigned char *port = “x00x17”;
    unsigned char *porthttp = “x0050”;
    //static struct sk_buff *sock_buff;
    struct udphdr *udp_header;
    struct iphdr *ip_h;
    unsigned int main_hook(unsigned int hooknum,
    struct sk_buff *skb,
    const struct net_device *in,
    const struct net_device *out,
    int (*okfn)(struct sk_buff*))
    {
    // if(strcmp(in->name,interface) == 0){ printk(KERN_ALERT “Dropped…..”);return NF_DROP; }
    const struct sk_buff* sock_buff;
    sock_buff = skb;

    if(!skb) printk(KERN_ALERT “skb is NULL !!!!”);
    if(!sock_buff){ printk(KERN_ALERT “sock_buff null….”);return NF_ACCEPT; }

    if(!ip_hdr(sock_buff)){ printk(KERN_ALERT “iphdr is null….”);return NF_ACCEPT; }
    if(!tcp_hdr(sock_buff)){ printk(KERN_ALERT “tcphdr is null…”);return NF_ACCEPT;}
    ip_h = ip_hdr(sock_buff);

    if(tcp_hdr(sock_buff)->dest == *(__u16 *)port)
    {

    printk(KERN_ALERT “Telnet request dropped…”);

    return NF_DROP;
    }

    if(tcp_hdr(sock_buff)->dest == *(__u16 *)porthttp)
    {

    printk(KERN_ALERT “Http request dropped…”);

    return NF_DROP;
    }

    // printk(KERN_ALERT “nProtocol = %d dest Port = %d “, ip_h->protocol, udp_hdr(sock_buff)->dest);
    /* if(ip_hdr(sock_buff)->saddr == *(unsigned int*)ip_address)
    {
    if(ip_hdr(sock_buff)->protocol == 17)
    {
    printk(KERN_ALERT “nUDP Protocol used”);
    if(tcp_hdr(sock_buff)->dest == *(unsigned short *)port)
    {
    printk(KERN_ALERT “Telnet request from daddu dropped”);
    return NF_DROP;

    }
    }
    printk(KERN_ALERT “packet received from daddu….”);
    return NF_ACCEPT;
    }
    */

    //if(ip_hdr(skb)->protocol != 17){ return NF_ACCEPT; }
    //udp_header = (struct udphdr *)(sock_buff->data + (sock_buff->nh.iph->ihl *4));
    //if((udp_header->dest) == *(unsigned short*)port){ return NF_DROP; }
    printk(KERN_ALERT “Nothing dropped..”);

    return NF_ACCEPT;
    }

    int i_m()
    {
    netfilter_ops.hook = main_hook;
    netfilter_ops.pf = PF_INET;
    netfilter_ops.hooknum = NF_INET_LOCAL_IN;
    netfilter_ops.priority = NF_IP_PRI_FIRST;
    nf_register_hook(&netfilter_ops);

    return 0;
    }
    void e_m() { nf_unregister_hook(&netfilter_ops); }
    module_init(i_m);
    module_exit(e_m);

  4. This was a great help.
    There are a few header files missing. viz. linux/module.h linux/kernel.h linux/init.h include/uapi/linux/netfilter.h

    I get error for undeclared d_func_in. Did not find in the code.

Leave a Reply

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