Roll Your Own Firewall with Netfilter

How to create a micro-firewall with kernel modules and packet filtering.

Every self-respecting Linux guru should be familiar with firewalls and how to install and configure them. With this in mind, Linux gurus also should be curious about how firewalls function and how to build a firewall of his or her own. Explaining exactly these two things is the goal of this article. Here, we attempt to write a firewall in less than 60 lines of C code. As impossible as this may sound, it actually is quite simple to do using the power of Linux kernel modules and Netfilter.

Netfilter is a packet filtering subsystem in the Linux kernel stack and has been there since kernel 2.4.x. Netfilter's core consists of five hook functions declared in linux/netfilter_ipv4.h. Although these functions are for IPv4, they aren't much different from those used in the IPv6 counterpart. The hooks are used to analyze packets in various locations on the network stack. This situation is depicted below:

  [INPUT]--->[1]--->[ROUTE]--->[3]--->[4]--->[OUTPUT]
                       |            ^
                       |            |
                       |         [ROUTE]
                       v            |
                      [2]          [5]
                       |            ^
                       |            |
                       v            |
                    [INPUT*]    [OUTPUT*]
[1]  NF_IP_PRE_ROUTING
[2]  NF_IP_LOCAL_IN
[3]  NF_IP_FORWARD
[4]  NF_IP_POST_ROUTING
[5]  NF_IP_LOCAL_OUT
[*]  Network Stack       
 

NF_IP_PRE_ROUTING is called right after the packet has been received. This is the hook we are most interested in for our micro-firewall. NF_IP_LOCAL_IN is used for packets that are destined for the network stack and thus has not been forwarded. NF_IP_FORWARD is for packets not addressed to us but that should be forwarded. NF_IP_POST_ROUTING is for packets that have been routed and are ready to leave, and NF_IP_LOCAL_OUT is for packets sent out from our own network stack. Each function has a chance to mangle or do what it wishes with the packets, but it eventually has to return a Netfilter code. Here are the codes that can be returned and what they mean:

  • NF_ACCEPT: accept the packet (continue network stack trip)

  • NF_DROP: drop the packet (don't continue trip)

  • NF_REPEAT: repeat the hook function

  • NF_STOLEN: hook steals the packet (don't continue trip)

  • NF_QUEUE: queue the packet to userspace

After we write our hook function, we have to register its options with the nf_hook_ops struct located in linux/netfilter.h.

struct nf_hook_ops
{
        struct list_head list;
        nf_hookfn *hook;
        int pf;
        int hooknum;
        int priority;
};

The first thing we see in the struct is the list_head struct, which is used to keep a linked list of hooks, but it's not necessary for our firewall. The nf_hookfn* struct member is the name of the hook function that we define. The pf integer member is used to identify the protocol family; it's PF_INET for IPv4. The next field is the hooknum int, and this is for the hook we want to use. The last field is the priority int. The priorities are specified in linux/netfilter_ipv4.h, but for our situation we want NF_IP_PRI_FIRST.

That's enough theory. No one has learned anything from theory alone, so let's learn by crawling into the trenches and writing our first module. Our module should block all traffic in and out of the network stack and should use the NF_IP_PRE_ROUTING and NF_IP_POST_ROUTING hooks. We start by defining our hook function and registering the nf_hook_ops structs in init_module(). Finally, we unregister the hooks in cleanup().

#define __KERNEL__
#define MODULE
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
static struct nf_hook_ops netfilter_ops_in; /* NF_IP_PRE_ROUTING */
static struct nf_hook_ops netfilter_ops_out; /* NF_IP_POST_ROUTING */
/* Function prototype in <linux/netfilter> */
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*))
{
return NF_DROP; /* Drop ALL Packets */
}
int init_module()
{
        netfilter_ops_in.hook                   =       main_hook;
        netfilter_ops_in.pf                     =       PF_INET;
        netfilter_ops_in.hooknum                =       NF_IP_PRE_ROUTING;
        netfilter_ops_in.priority               =       NF_IP_PRI_FIRST;
        netfilter_ops_out.hook                  =       main_hook;
        netfilter_ops_out.pf                    =       PF_INET;
        netfilter_ops_out.hooknum               =       NF_IP_POST_ROUTING;
        netfilter_ops_out.priority              =       NF_IP_PRI_FIRST;
        nf_register_hook(&netfilter_ops_in); /* register NF_IP_PRE_ROUTING hook */
        nf_register_hook(&netfilter_ops_out); /* register NF_IP_POST_ROUTING hook */
return 0;
}
void cleanup()
{
nf_unregister_hook(&netfilter_ops_in); /*unregister NF_IP_PRE_ROUTING hook*/
nf_unregister_hook(&netfilter_ops_out); /*unregister NF_IP_POST_ROUTING hook*/
}

Let's walk through the code. We start with the regular #define and #include statements and declare our two nf_hook_ops structs, one for what comes in and one for what goes out. We then see our hook function, which passes a few important parameters. The first, hooknum, is a hooktype we already have covered. The second is a pointer to a pointer to a socket kernel buffer. The next two are netdevice pointers; we'll use these later to block and filter interfaces. The last parameter is a pointer to a function that takes in an sk_buff. With that in place, all we do in the hook function is drop all packets by returning NF_DROP.

Inside init_module(), we fill in the nf_hook_ops structs and then formally register the hooks with nf_register_hook(). In cleanup(), all we do is unregister the two hooks with nf_unregister_hook(). To get the module working, compile and load it with the following commands, assuming the source file is called drop.c:

$>cc -c drop.c
$>insmod drop.o

Once the module is up and running, open Ethereal or an equivalent program and watch the packets not come in. To unload the module, issue the command $>rmmod drop.

Now we move on to our main project, called micro-firewall. The firewall is going to filter packets based on IP address, interface and TCP/UDP protocol and/or port. The firewall is a kernel module and is less than 60 lines of code in length. Let's look at the code first then review it:

#define __KERNEL__
#define MODULE
#include <linux/ip.h>             
#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/netdevice.h>      
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h> 
#include <linux/skbuff.h>         
#include <linux/udp.h>                    
static struct nf_hook_ops netfilter_ops;                        
static unsigned char *ip_address = "\xC0\xA8\x00\x01"; 
static char *interface = "lo";                          
unsigned char *port = "\x00\x17";                       
struct sk_buff *sock_buff;                              
struct udphdr *udp_header;                              
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){ return NF_DROP; }     
        
  sock_buff = *skb;
  if(!sock_buff){ return NF_ACCEPT; }                   
  if(!(sock_buff->nh.iph)){ return NF_ACCEPT; }              
  if(sock_buff->nh.iph->saddr == *(unsigned int*)ip_address){ return NF_DROP; }
                
  
if(sock_buff->nh.iph->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; }
return NF_ACCEPT;
}
int init_module()
{
        netfilter_ops.hook              =       main_hook;
        netfilter_ops.pf                =       PF_INET;        
        netfilter_ops.hooknum           =       NF_IP_PRE_ROUTING;
        netfilter_ops.priority          =       NF_IP_PRI_FIRST;
        nf_register_hook(&netfilter_ops);
        
return 0;
}
void cleanup_module() { nf_unregister_hook(&netfilter_ops); }

We start with the #define and #include statements. Next, we declare an nf_hook_ops and an IP address (192.168.0.1) in network byte order. We also declare a char* called "lo" for the loopback interface, which we want to block. We also declare a char* for port 23, the telnet port. The last globals are a pointer to a socket kernel buffer and a pointer to a UDP header.

The hook function is where we do the real work. In our first statement, we compare the name of the device the packet came from to our char* interface. If the device is the loopback device, we return NF_DROP. In other words, we drop the packet. That's all that is involved with filtering by interface. We easily could have filtered packets from the Ethernet device by replacing <coe>lo with eth0 in the char* interface declaration.

Next, we filter by IP address and use the sk_buff to check for an IP address. We first check to see if we have a valid sk_buff, then we validate the IP packet, and finally we compare IP addresses.

Our last filtering technique is by protocol and/or port. Here we decide to filter by UDP port. First we check to see if we have a valid UDP packet. If we do, we copy the packet's UDP struct to our own. Finally, we compare the packet's UDP port with port 23 (telnet). If all else fails, the hook function returns NF_ACCEPT and the packet goes on its merry way through the network stack. Compile and load the firewall with the following commands:

$>cc -c firewall.c
$>insmod firewall.o

Once again, fire up Ethereal and see if the rules in the firewall holds. The packet filtering we did is straight-forward, and the possibilities are endless if you use your imagination. Unload the module with $>rmmod firewall, and things go back to normal.

We've taken a magical trip through the world of Netfilter, and what we got is our micro-firewall. Many possibilities for Netfilter exist, not only with firewalls but for many other useful network tools.

Victor Castro can be reached via his Web site.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

problem with nf

fr4nkissimo's picture

i have a problem, first i show you the code:

unsigned int hook_post_routing( unsigned int hooknum,
struct sk_buff **skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
sock_buff = *skb;
printk(KERN_ALERT " - Sent new packet %p, %p\n", skb, *skb);

return NF_ACCEPT;}

i don't understand why the second value is always 00000000, shouldn't it change value at any time a packet goes?

Ran into Errors.... Please Help...!!

Chinmay's picture

Hi All, I was trying to run this code on Ubuntu 8.04(Kernel : 2.6.24) and I ran into some problems. I was not getting many errors and so I went on and made a Makefile as suggested. But still its showing some errors. As I m new to Linux, I don know much about what these errors say. Can you all please help me out ?

Here is the Makefile I made :

KERNELDIR = /usr/src/linux-headers-2.6.24-16/
KERNEL_SOURCES := $(KERNDIR)
KERNEL_HEADERS := -I$(KERNEL_SOURCES)/include
obj-m := a.o
EXTRA_CFLAGS += -Os
MODULE_NAME := FIRST
all: *

Here are the Errors I am receiving :

chinmay@ubuntu804desktop:~$ make -C /usr/src/linux-headers-2.6.24-16 SUBDIRS=$PWD modules
make: Entering directory `/usr/src/linux-headers-2.6.24-16'

ERROR: Kernel configuration is invalid.
include/linux/autoconf.h or include/config/auto.conf are missing.
Run 'make oldconfig && make prepare' on kernel src to fix it.

WARNING: Symbol version dump /usr/src/linux-headers-2.6.24-16/Module.symvers
is missing; modules will have no dependencies and modversions.

make[1]: *** No rule to make target `/home/chinmay/a.c', needed by `/home/chinmay/a.o'. Stop.
make: *** [_module_/home/chinmay] Error 2
make: Leaving directory `/usr/src/linux-headers-2.6.24-16'
chinmay@ubuntu804desktop:~$

And here are the errors I was receiving before I made the Makefile :

chinmay@ubuntu804desktop:~$ cc f_m_c.c
f_m_c.c:4:26: error: linux/kernel.h: No such file or directory
f_m_c.c:5:26: error: linux/module.h: No such file or directory
f_m_c.c:6:29: error: linux/netfilter.h: No such file or directory
f_m_c.c:7:34: error: linux/netfilter_ipv4.h: No such file or directory
f_m_c.c:15: warning: ‘struct net_device’ declared inside parameter list
f_m_c.c:15: warning: its scope is only this definition or declaration, which is probably not what you want
f_m_c.c:15: warning: ‘struct sk_buff’ declared inside parameter list
f_m_c.c: In function ‘main_hook’:
f_m_c.c:17: error: ‘NF_DROP’ undeclared (first use in this function)
f_m_c.c:17: error: (Each undeclared identifier is reported only once
f_m_c.c:17: error: for each function it appears in.)
f_m_c.c: In function ‘init_module’:
f_m_c.c:21: error: invalid use of undefined type ‘struct nf_hook_ops’
f_m_c.c:22: error: invalid use of undefined type ‘struct nf_hook_ops’
f_m_c.c:22: error: ‘PF_INET’ undeclared (first use in this function)
f_m_c.c:23: error: invalid use of undefined type ‘struct nf_hook_ops’
f_m_c.c:23: error: ‘NF_IP_PRE_ROUTING’ undeclared (first use in this function)
f_m_c.c:24: error: invalid use of undefined type ‘struct nf_hook_ops’
f_m_c.c:24: error: ‘NF_IP_PRI_FIRST’ undeclared (first use in this function)
f_m_c.c:25: error: invalid use of undefined type ‘struct nf_hook_ops’
f_m_c.c:26: error: invalid use of undefined type ‘struct nf_hook_ops’
f_m_c.c:27: error: invalid use of undefined type ‘struct nf_hook_ops’
f_m_c.c:27: error: ‘NF_IP_POST_ROUTING’ undeclared (first use in this function)
f_m_c.c:28: error: invalid use of undefined type ‘struct nf_hook_ops’

Please help me out...!!!

Plagiarism

Anonymous's picture

ERROR: Removing 'drop': Device or resource busy

Michael's picture

Why I cannot rmmod the module.
After type rmmod, is said "ERROR: Removing 'drop': Device or resource busy"
Does it has other method to remove without reboot the PC.

You need to add module entry

Anonymous's picture

You need to add module entry points which will allow kernel to load or unload module. I wrote this:


module_init(fwall_init);
module_exit(fwall_exit);

fwall_init and fwall_exit - procedures that was in this article which doing all firewall work.

Without module_init and module_exit kernel does'nt know how to unload the module and module became permanent.

Hope it'll be useful. Sorry for my english :)

Roll your own firewall using Iptables

Ashish's picture

I need to build a firewall using the netfilters IP tables code. Anyone has a simple firewall for understanding purposes or kindly recommend a book.

Roll your own firewall using Iptables

Ashish's picture

I need to build a firewall using the netfilters IP tables code. Anyone has a simple firewall for understanding purposes or kindly recommend a book.

Roll your own firewall using Iptables

Ashish's picture

I need to build a firewall using the netfilters IP tables code. Anyone has a simple firewall for understanding purposes or kindly recommend a book.

Problem with sample code

Anonymous's picture

Hi,
I tried using the sample code for the netfilter hooks but i seem to be having some problems.I was able to compile and install the module on a Suse Linux 9.0 Kernel version 2.4.21 I was able to check the status using netfilter also.But when i tried rmmod module my whole system just stopped responding as in i think it just hung and i had to reboot ...i tried several times but kept having the same problem.Could u please lemme know if there is a problem in the code or is it on my side.This only happens when i use the command rmmod modulename.
thanx in advance

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

I tried building the simplistic module that drops all traffic, and it does seem to work. Also, when I try to ping myself while the module is active, ping returns "operation not permitted". Now the interesting part: after I rmmod the module, I again try to ping myself, and this time I get a kernel panic (repeatably). Is something not getting unregistered correctly?

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

figured it out. in the code, the function is "cleanup", but it should be "cleanup_module". It works as expected with that change. Good-o. :-)

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

The 60 lines firewall example:
Im having truble with this example, i want this to filter for example only one ip in telnet port, but when i change the interface this filter all eth0 ips, not only the ip i especified.
Please i really need to change this.
Thanx and excuse my english.

Roll Your Own Firewall with Netfilter

Prabha's picture

The 60 lines firewall example:

I'm having trouble with this example,

I altered the code for IP address from 192.168.0.1 to 192.168.2.55
and followed the steps as mentioned in the linux journal.

I'm using RedHat Linux 9.0 with kernel version 2.4.20-8

I'm getting the following errors.

In file included from /usr/include/linux/fs.h:23,
from /usr/include/linux/capability.h:17,
from /usr/include/linux/binfmts.h:5,
from /usr/include/linux/sched.h:9,
from /usr/include/linux/skbuff.h:19,
from firewall.c:9:
/usr/include/linux/string.h:8:2: warning: #warning Using kernel header in userla
nd!
In file included from /usr/include/linux/sched.h:14,
from /usr/include/linux/skbuff.h:19,
from firewall.c:9:
/usr/include/linux/timex.h:173: field `time' has incomplete type
In file included from /usr/include/linux/bitops.h:69,
from /usr/include/asm/system.h:7,
from /usr/include/linux/sched.h:16,
from /usr/include/linux/skbuff.h:19,
from firewall.c:9:
/usr/include/asm/bitops.h:327:2: warning: #warning This includefile is not avail
able on all architectures.
/usr/include/asm/bitops.h:328:2: warning: #warning Using kernel headers in users
pace: atomicity not guaranteed
In file included from /usr/include/linux/signal.h:4,
from /usr/include/linux/sched.h:25,
from /usr/include/linux/skbuff.h:19,
from firewall.c:9:
/usr/include/asm/signal.h:107: parse error before "sigset_t"
/usr/include/asm/signal.h:110: parse error before '}' token
In file included from /usr/include/linux/sched.h:81,
from /usr/include/linux/skbuff.h:19,
from firewall.c:9:
/usr/include/linux/timer.h:45: parse error before "spinlock_t"
/usr/include/linux/timer.h:53: parse error before '}' token
/usr/include/linux/timer.h:67: parse error before "tvec_base_t"
/usr/include/linux/timer.h:101: parse error before "tvec_bases"
/usr/include/linux/timer.h: In function `init_timer':
/usr/include/linux/timer.h:105: dereferencing pointer to incomplete type
/usr/include/linux/timer.h:105: dereferencing pointer to incomplete type
/usr/include/linux/timer.h:106: dereferencing pointer to incomplete type
/usr/include/linux/timer.h: In function `timer_pending':
/usr/include/linux/timer.h:121: dereferencing pointer to incomplete type
In file included from /usr/include/linux/highmem.h:5,
from /usr/include/linux/skbuff.h:26,
from firewall.c:9:
/usr/include/asm/pgalloc.h:6:24: asm/fixmap.h: No such file or directory
In file included from /usr/include/linux/highmem.h:5,
from /usr/include/linux/skbuff.h:26,
from firewall.c:9:
/usr/include/asm/pgalloc.h: At top level:
/usr/include/asm/pgalloc.h:57: parse error before '*' token
/usr/include/asm/pgalloc.h: In function `get_pgd_slow':
/usr/include/asm/pgalloc.h:59: `pgd_t' undeclared (first use in this function)
/usr/include/asm/pgalloc.h:59: (Each undeclared identifier is reported only once
/usr/include/asm/pgalloc.h:59: for each function it appears in.)
/usr/include/asm/pgalloc.h:59: `pgd' undeclared (first use in this function)
/usr/include/asm/pgalloc.h:59: parse error before ')' token
/usr/include/asm/pgalloc.h:62: `USER_PTRS_PER_PGD' undeclared (first use in this
function)
/usr/include/asm/pgalloc.h:63: `swapper_pg_dir' undeclared (first use in this fu
nction)
/usr/include/asm/pgalloc.h:63: `PTRS_PER_PGD' undeclared (first use in this func
tion)
/usr/include/asm/pgalloc.h: At top level:
/usr/include/asm/pgalloc.h:70: parse error before '*' token
/usr/include/asm/pgalloc.h: In function `get_pgd_fast':
/usr/include/asm/pgalloc.h:80: `pgd_t' undeclared (first use in this function)
/usr/include/asm/pgalloc.h:80: parse error before ')' token
/usr/include/asm/pgalloc.h: At top level:
/usr/include/asm/pgalloc.h:83: parse error before '*' token
/usr/include/asm/pgalloc.h: In function `free_pgd_fast':
/usr/include/asm/pgalloc.h:85: `pgd' undeclared (first use in this function)
/usr/include/asm/pgalloc.h: At top level:
/usr/include/asm/pgalloc.h:90: parse error before '*' token
/usr/include/asm/pgalloc.h: In function `free_pgd_slow':
/usr/include/asm/pgalloc.h:99: `pgd' undeclared (first use in this function)
/usr/include/asm/pgalloc.h: At top level:
/usr/include/asm/pgalloc.h:103: parse error before '*' token
/usr/include/asm/pgalloc.h: In function `pte_alloc_one':
/usr/include/asm/pgalloc.h:105: `pte_t' undeclared (first use in this function)
/usr/include/asm/pgalloc.h:105: `pte' undeclared (first use in this function)
/usr/include/asm/pgalloc.h:109: parse error before ')' token
/usr/include/asm/pgalloc.h: At top level:
/usr/include/asm/pgalloc.h:118: parse error before '*' token
/usr/include/asm/pgalloc.h: In function `pte_alloc_one_fast':
/usr/include/asm/pgalloc.h:127: `pte_t' undeclared (first use in this function)
/usr/include/asm/pgalloc.h:127: parse error before ')' token
/usr/include/asm/pgalloc.h: At top level:
/usr/include/asm/pgalloc.h:130: parse error before '*' token
/usr/include/asm/pgalloc.h: In function `pte_free_fast':
/usr/include/asm/pgalloc.h:132: `pte' undeclared (first use in this function)
/usr/include/asm/pgalloc.h: At top level:
/usr/include/asm/pgalloc.h:137: parse error before '*' token
/usr/include/asm/pgalloc.h: In function `pte_free_slow':
/usr/include/asm/pgalloc.h:139: `pte' undeclared (first use in this function)
/usr/include/asm/pgalloc.h: In function `flush_tlb_mm':
/usr/include/asm/pgalloc.h:183: `current' undeclared (first use in this function
)
/usr/include/asm/pgalloc.h: In function `flush_tlb_page':
/usr/include/asm/pgalloc.h:190: dereferencing pointer to incomplete type
/usr/include/asm/pgalloc.h:190: `current' undeclared (first use in this function
)
/usr/include/asm/pgalloc.h: In function `flush_tlb_range':
/usr/include/asm/pgalloc.h:197: `current' undeclared (first use in this function
)In file included from firewall.c:9:
/usr/include/linux/skbuff.h: At top level:
/usr/include/linux/skbuff.h:100: parse error before "spinlock_t"
/usr/include/linux/skbuff.h:120: parse error before "atomic_t"
/usr/include/linux/skbuff.h:124: parse error before '}' token
/usr/include/linux/skbuff.h:183: parse error before "atomic_t"
/usr/include/linux/skbuff.h:215: parse error before '}' token
firewall.c: In function `main_hook':
firewall.c:23: dereferencing pointer to incomplete type
firewall.c:32: dereferencing pointer to incomplete type
firewall.c:36: dereferencing pointer to incomplete type
firewall.c:40: dereferencing pointer to incomplete type
firewall.c:44: dereferencing pointer to incomplete type
firewall.c:44: dereferencing pointer to incomplete type
firewall.c: In function `init_module':
firewall.c:54: invalid use of undefined type `struct nf_hook_ops'
firewall.c:55: invalid use of undefined type `struct nf_hook_ops'
firewall.c:56: invalid use of undefined type `struct nf_hook_ops'
firewall.c:57: invalid use of undefined type `struct nf_hook_ops'
firewall.c: At top level:
firewall.c:12: storage size of `netfilter_ops' isn't known

Since I'm a beginner in this area,I expect your help to solve these errors.

Eagerly waiting for a genuine response
Thanks in advance

YOU JUST CRETAE A MAKE FILE

Anonymous's picture

YOU JUST CRETAE A MAKE FILE AND RUN IT, U WILL GET THE CORRECT RESULT, AND ALSO CHANGE THE PATH OF NETFILTER.H AND NETFILTER_IPV4.H TO THE PATH OF /USR/SRC/KERNEL../INCLUDE/LINUX/.

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

people:
muy buen articulo... me sirvio mucho.
saludos, velkro

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

when i am compiling the example in redhat 9.0 with kernel version 2.4.20-8 i got the following errors . please help me how to recover from errors

[root@localhost vamsi]# cc -c p4.c
In file included from p4.c:7:
/usr/include/linux/netfilter_ipv4.h:53: `INT_MIN' undeclared here (not in a function)
/usr/include/linux/netfilter_ipv4.h:53: enumerator value for `NF_IP_PRI_FIRST' not integer constant
/usr/include/linux/netfilter_ipv4.h:59: `INT_MAX' undeclared here (not in a function)
/usr/include/linux/netfilter_ipv4.h:59: enumerator value for `NF_IP_PRI_LAST' not integer constant
p4.c:18: warning: `struct net_device' declared inside parameter list
p4.c:18: warning: its scope is only this definition or declaration, which is probably not what you want
p4.c:18: warning: `struct sk_buff' declared inside parameter list
p4.c: In function `init_module':
p4.c:26: invalid use of undefined type `struct nf_hook_ops'
p4.c:27: invalid use of undefined type `struct nf_hook_ops'
p4.c:27: `PF_INET' undeclared (first use in this function)
p4.c:27: (Each undeclared identifier is reported only once
p4.c:27: for each function it appears in.)
p4.c:28: invalid use of undefined type `struct nf_hook_ops'
p4.c:29: invalid use of undefined type `struct nf_hook_ops'
p4.c:31: invalid use of undefined type `struct nf_hook_ops'
p4.c:32: invalid use of undefined type `struct nf_hook_ops'
p4.c:33: invalid use of undefined type `struct nf_hook_ops'
p4.c:34: invalid use of undefined type `struct nf_hook_ops'
p4.c: At top level:
p4.c:9: storage size of `netfilter_ops_in' isn't known
p4.c:10: storage size of `netfilter_ops_out' isn't known

Re: Roll Your Own Firewall with Net"storage size of `netfilter_o

Anonymous's picture

Why do I get this error when I compile the same module ?
I really need to know and I don't understand why it give me that error at :

"struct nf_hook_ops netfilter_ops_in;" .It's a simple example.

And at the :
"netfilter_ops_in.hook = main_hook;
netfilter_ops_in.pf = PF_INET;
netfilter_ops_in.hooknum = NF_IP_PRE_ROUTING;
netfilter_ops_in.priority = NF_IP_PRI_FIRST;
"
I have the following error :

-> invalid use of undentified type "nf_hook_ops".
PLEASE HELP.

Thanks.

Reply

Anonymous's picture

plz try different make file..

or Replace 'uname -r ' by using the result u got when typing it on terminal.

i think some problem is with include directories..

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

Hi all, I tried drop.c but failed and got loads of errors (see below)! Can anybody tell me what I shall do? Thanks very much in advance!

[root@host-172-16-2-203 netfilter]# cc -c drop.c
In file included from drop.c:7:
/usr/include/linux/netfilter_ipv4.h:53: `INT_MIN' undeclared here (not in a function)
/usr/include/linux/netfilter_ipv4.h:53: enumerator value for `NF_IP_PRI_FIRST' not integer constant
/usr/include/linux/netfilter_ipv4.h:59: `INT_MAX' undeclared here (not in a function)
/usr/include/linux/netfilter_ipv4.h:59: enumerator value for `NF_IP_PRI_LAST' not integer constant
drop.c:18: warning: `struct net_device' declared inside parameter list
drop.c:18: warning: its scope is only this definition or declaration, which is probably not what you want
drop.c:18: warning: `struct sk_buff' declared inside parameter list
drop.c: In function `init_module':
drop.c:26: invalid use of undefined type `struct nf_hook_ops'
drop.c:27: invalid use of undefined type `struct nf_hook_ops'
drop.c:27: `PF_INET' undeclared (first use in this function)
drop.c:27: (Each undeclared identifier is reported only once
drop.c:27: for each function it appears in.)
drop.c:28: invalid use of undefined type `struct nf_hook_ops'
drop.c:29: invalid use of undefined type `struct nf_hook_ops'
drop.c:31: invalid use of undefined type `struct nf_hook_ops'
drop.c:32: invalid use of undefined type `struct nf_hook_ops'
drop.c:33: invalid use of undefined type `struct nf_hook_ops'
drop.c:34: invalid use of undefined type `struct nf_hook_ops'
drop.c: At top level:
drop.c:9: storage size of `netfilter_ops_in' isn't known
drop.c:10: storage size of `netfilter_ops_out' isn't known
[root@host-172-16-2-203 netfilter]#

The reason is...

Anonymous's picture

Look at the message "/usr/include/linux/netfilter_ipv4.h:53..............."
your compiler includes "/usr/include/linux..." directory, that would not work.
you need to include "/usr/src/kernerl_source_dir/inlucde/linux....."

see the document "Linux kernel module programming guide" by Russel.

hai, I am too getting the

Anonymous's picture

hai,

I am too getting the same error .. i am new to linux .. how to include the path specified. I tried using the -I option but its not working.

pls help me

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

I have exactly the same problem

Re: Roll Your Own Firewall with Netfilter - COMPILE ERROR

Anonymous's picture

I have entered the code in from the article (for the simple block everything example) and tried to compile. My source filename is ts.c and when I issue a "cc -c ts.c" at the prompt I get the following errors:

In file included from /usr/include/linux/highmem.h:5,
from /usr.include/linux/skbuff.h:26,
from ts.c:11:
/usr/include/asm/pgalloc.h:6:24: asm/fixmap.h: No such file or direcory

Any suggestions?

Re: Roll Your Own Firewall with Netfilter - COMPILE ERROR

Anonymous's picture

you have to install the kernel source header files.

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

While I will probably never replace using userland iptables by writing my own kernel module, I thought this was a wonderful article.

I've always wondered how the netfilter hooks work.

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

Thanks a lot. Before I don't have a clear understanding of firewall (IN,OUT rules). Now I have a clear picture (architecture), even a background on programming in it. Thanks!!!

Example code seems to be missing some backslashes

Anonymous's picture

Hi, and thanks for a nice article.

It seems that the last example code is missing some crucial backslashes in the ip_address and port strings. Without the backslashes the filtering will not work properly.

The code at http://www.geocities.com/victorhugo83/micro_firewall.c looks the way originally intended.

Cheers,
Semi

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

GROAN.. fine for you C programers....
whats the point? surely a script would sufficient.

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

That is a good statement, however, a lot of sysadmins don't have time to learn C++. I have other things to do, back-ups, going thourh logs on Apache and IIS (yess IIS, we have Micro$oft too), as well as other maintenance tasks. I know a little bit of C, but enough to go tampering with a kernel and expecting the OS to work.

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

Scripts are sufficient, but what good is a script if it doesn't work? iptables is dependent on Netfilter's kernel code. Maybe understanding how the internals work, it might make you better understand how the scripts work.

-Victor

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

OK, I'm just an ole country sysadmin, not a programmer. What advantage is there to writing a firewall this way, rather than the old-fashioned method of putting your rules into a script?

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

In my opinion, control is everything. The closer I can get to the system the better. As to whether or not a sysadmin should write a kernel module firewall or a plain script, I would recommend the script. For those looking for a little more insight, Kernel Hacking is the way to go. This, however is not to say that one way is better than the other.

-Victor

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

Along this line, I would be interested to see a couple quick comments about how ipchains and iptables fits into this. Are they just facilities that have attached their own hook functions into this Netfilter system and provide an interface that interprets a script, or do they have some sort of special standing inside the kernel?

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

iptables is exactly that, a facility that calls on hook functions depending on the scripts it interprets inside a script. Ipchains is before iptables' time, in fact netfilter and ipchains was written as a result of the developer's being unsatisfied with ipchains.

-Victor

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

In my opinion, iptables is just a tool which based on netfilter.
It just reads rules from script or from input. And via ioctl system call, it put rules into kernel space. To an admin,iptables is enough. However, this method give us a clear insight into tcp/ip protocol stack. We can do many other thing by using the method metioned above.

Say, we can using up to 8 filter attached to Datalink according to their different priority. Or, to a hacker, this techonogy is powerful. He can do many things cheating a common admin. For example, he can plants into the os an
back door without execute a usr process and so on.

In a world, to a programmer, programming is everything. Control is everything!

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

does this work the same for 2.6 kernels?

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

I know there has been much work in Kernel 2.6 regarding packet filtering, mainly to size up to OpenBSD's packet filtering system, but the code should compile and run in Kernel 2.6.

-Victor

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

it does not work on my 2.6.0-test7:

insmod: error inserting 'micro_firewall.o': -1 Invalid module format

2.6 kernel module

Anonymous's picture

try inserting 'micro_firewall.ko'

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

you have to use a Makefile like this :

KERNELDIR = /usr/src/linux
KERNEL_SOURCES := $(KERNDIR)
KERNEL_HEADERS := -I$(KERNEL_SOURCES)/include
obj-m := something.o
EXTRA_CFLAGS += -Os
MODULE_NAME := something
all: *

and
compile it like this where you put both the code and Makefile:
make -C /usr/src/linux SUBDIRS=$PWD modules
peace

good stuff

Anonymous's picture

excellent article and good Makefile! :-) was frust with errors.
Such "hands-on" articles should be encouraged and I hope to see more of them in the future.
- vk

I'm gettin lots of erros

karacas's picture

I'm gettin lots of erros starting with "/usr/include..."... tried this makefile but gives no target error... I have linux src in /usr/src/linux wich is a link to the directory linux_2.4... containg the actual source... I tried use gcc with -I but seems it isn't changing nothing, keeps showing "/usr/include..." errors

Re: Roll Your Own Firewall with Netfilter

Anonymous's picture

Nice article. Graphical diagram of kernel 2.4 packet handling is available at

http://open-source.arkoon.net/kernel/kernel_net.png

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix