Detailed Explanation of Linux Netfilter Instances

Completed Content

I will create a simple firewall demo to help you familiarize yourself with network kernel programming. This demo will be implemented based on the Linux Netfilter framework.

Basic Framework

Detailed Explanation of Linux Netfilter Instances

Basic Concepts

Netfilter Framework

  • Netfilter is a framework in the Linux kernel used for filtering, modifying, and redirecting network packets. It provides multiple hook points, allowing users to insert custom logic at different network layers.

Main Functions of Netfilter

  1. Packet filtering (e.g., firewall).
  2. Network Address Translation (NAT, including SNAT and DNAT).
  3. Packet modification (e.g., modifying TTL, TOS fields, etc.).
  4. Packet logging.

Netfilter Hook Points

  1. NF_INET_PRE_ROUTING: After the packet enters the network stack but before routing decisions are made. Suitable for DNAT (Destination Network Address Translation) or packet marking.1)Location of the netfilter kernel mount point in the code: kernel code path: /net/ipv4/ip_input.c2)Specific function: in ip_rcv()Detailed Explanation of Linux Netfilter Instancesip_rcv_finish is the callback function after routing lookup

  2. NF_INET_LOCAL_IN: The packet’s destination is the local machine (i.e., the destination address is the local machine’s IP address). Suitable for filtering or modifying packets entering the local machine.1)Kernel code path: /net/ipv4/ip_input.c2)Specific function: in ip_local_deliver()Detailed Explanation of Linux Netfilter Instances

  3. NF_INET_FORWARD: The packet needs to be forwarded to another host (i.e., the local machine acts as a router). Suitable for filtering or modifying forwarded packets.1)Kernel code path: /net/ipv4/ip_forward.c2)Specific function: in ip_forward()Detailed Explanation of Linux Netfilter InstancesDetailed Explanation of Linux Netfilter Instances

  4. NF_INET_LOCAL_OUT: The packet is sent from the local machine. Suitable for filtering or modifying packets sent from the local machine.1)Kernel code path: /net/ipv4/ip_output.c2)Specific function: in __ip_local_out()Detailed Explanation of Linux Netfilter Instances

  5. NF_INET_POST_ROUTING: The packet is processed after routing decisions but before being sent to the network interface. Suitable for SNAT (Source Network Address Translation) or packet marking.1)Kernel code path: /net/ipv4/ip_output.c2)Specific function: in ip_output()Detailed Explanation of Linux Netfilter Instances

Implementation Example at NF_INET_PRE_ROUTING Point

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/netfilter.h>
#include<linux/netfilter_ipv4.h>
#include<linux/ip.h>
#include<linux/tcp.h>

static unsigned int custom_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) {
    struct iphdr *ip_header = ip_hdr(skb);
    if (ip_header->protocol == IPPROTO_TCP) { // Only process TCP packets
        struct tcphdr *tcp_header = tcp_hdr(skb);
        printk(KERN_INFO "Custom Netfilter Hook: TCP packet to port %u\n", ntohs(tcp_header->dest));
        if (ntohs(tcp_header->dest) == 22) { // Only process packets with destination port 22
            printk(KERN_INFO "Custom Netfilter Hook: TCP packet to port 22\n");
            return NF_DROP; // Drop the packet
        }
    }
    return NF_ACCEPT; // Allow the packet to continue
}

static struct nf_hook_ops nfho = {
    .hook     = custom_hook,
    .pf       = NFPROTO_IPV4, // Operates at the IP layer
    .hooknum  = NF_INET_PRE_ROUTING, // Process packets at the PRE_ROUTING stage
    .priority = NF_IP_PRI_FIRST, // Priority
};

static int __init pre_routing_module_init(void) {
    nf_register_net_hook(&init_net, &nfho);
    printk(KERN_INFO "Custom Netfilter Hook registered\n");
    return 0;
}

static void __exit pre_routing_module_exit(void) {
    nf_unregister_net_hook(&init_net, &nfho);
    printk(KERN_INFO "Custom Netfilter Hook unregistered\n");
}

module_init(pre_routing_module_init);
module_exit(pre_routing_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("pre_routing_module_init");
MODULE_DESCRIPTION("Netfilter hook example");

Makefile:

obj-m += hook_NF_INET_PRE_ROUTING.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

Compilation and Verification

Run the following command in the terminal to compile the kernel module

$ make 
make -C /lib/modules/5.4.0-150-generic/build M=/home/hook_netfilter modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-150-generic'
  CC [M]/home/hook_netfilter/hook_NF_INET_PRE_ROUTING.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC [M]/home/hook_netfilter/hook_NF_INET_PRE_ROUTING.mod.o
  LD [M]/home/hook_netfilter/hook_NF_INET_PRE_ROUTING.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-150-generic'
@ubuntu:hook_netfilter$ ls 
hook_NF_INET_PRE_ROUTING.c   hook_NF_INET_PRE_ROUTING.mod    hook_NF_INET_PRE_ROUTING.mod.o  Makefile       Module.symvers
hook_NF_INET_PRE_ROUTING.ko  hook_NF_INET_PRE_ROUTING.mod.c  hook_NF_INET_PRE_ROUTING.o      modules.order

Load Module

$ sudo insmod hook_NF_INET_PRE_ROUTING.ko

View Module

$ lsmod | grep hook
hook_NF_INET_PRE_ROUTING    163840
$ dmesg | tail
[716700.997388] Custom Netfilter Hook registered
[709907.950324] Custom Netfilter Hook: TCP packet to port 22
[709907.950325] Custom Netfilter Hook: TCP packet to port 22

Verification Results

Detailed Explanation of Linux Netfilter Instances

Verification Successful (Unable to Connect)

Detailed Explanation of Linux Netfilter Instances

We can use a block diagram to simply outline the data direction

Detailed Explanation of Linux Netfilter Instancesindicating that the custom_hook function is mounted at the NF_HOOK call point in the ip_rcv() function.

This is the earliest point where packets can be captured; all incoming packets (whether destined for the local machine or needing to be forwarded) will pass through here, and filtering rules will take effect very early.

Leave a Comment