Inside Netfilter and iptables: How Linux Filters Packets with Hooks and Tables

Netfilter, the Linux kernel’s packet‑processing framework, uses a series of hook points and the NF_HOOK macro to let user‑space tools like iptables register callback functions that inspect, modify, or drop packets, with detailed structures for tables, chains, rules, priorities, and connection tracking.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Inside Netfilter and iptables: How Linux Filters Packets with Hooks and Tables

Netfilter Design and Implementation

Netfilter is a packet‑processing framework built into the Linux kernel. It allows user‑space programs to register processing rules that are applied to packets as they traverse the kernel network stack, enabling efficient forwarding and filtering for host firewalls and Kubernetes Service forwarding.

Packet Journey Through the Kernel

At the physical‑network device layer the NIC writes the received packet into a ring buffer via DMA. The kernel then calls __skb_dequeue to enqueue the packet, converting it to an sk_buff (socket buffer) that is passed through the stack.

The function netif_receive_skb classifies the packet by protocol and dispatches it to the appropriate handler. For an IPv4 packet ip_rcv is invoked, which validates the IP header, performs reassembly if needed, and calls ip_rcv_finish for routing.

If the destination is the local host, dst_input calls ip_local_deliver, which examines the protocol field and eventually invokes the TCP handler tcp_v4_rcv.

The TCP handler processes the TCP header, computes checksums, looks up the associated socket via __tcp_v4_lookup, and either queues the packet for user‑space consumption or drops it.

Netfilter Hooks

Netfilter inserts hook points at predefined locations in the protocol stack. For IPv4 the relevant hooks are: NF_INET_PRE_ROUTING – first hook after packet reception, before routing. NF_INET_LOCAL_IN – after routing when the packet is destined for the local host. NF_INET_FORWARD – after routing when the packet is to be forwarded. NF_INET_LOCAL_OUT – when the local host generates a packet. NF_INET_POST_ROUTING – just before the packet leaves the host.

NF_HOOK Macro and Netfilter Vectors

static inline int NF_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb,
    struct net_device *in, struct net_device *out,
    int (*okfn)(struct sk_buff *)) {
    return NF_HOOK_THRESH(pf, hook, skb, in, out, okfn, INT_MIN);
}

The macro receives: pf: protocol family (e.g., NFPROTO_IPV4). hook: one of the NF_INET_* enumerations. skb: the packet buffer. in / out: input and output network devices. okfn: pointer to the next function in the processing chain.

Return values (netfilter vectors) are: NF_ACCEPT – continue processing. NF_DROP – discard the packet. NF_STOLEN – packet taken by the hook. NF_QUEUE – queue for userspace handling. NF_REPEAT – re‑invoke the current hook.

Hook Callback Functions and Priorities

struct nf_hook_ops {
    struct list_head list;
    nf_hookfn *hook;
    struct module *owner;
    u_int8_t pf;
    unsigned int hooknum;
    int priority;
};

Key members: hook: the callback function (signature matches NF_HOOK). hooknum: target hook enumeration. priority: lower values run first.

Callbacks are registered with nf_register_hook or nf_register_hooks. When a hook is triggered, nf_iterate walks the list of registered nf_hook_ops in priority order, invoking each hookfn. If a callback returns NF_ACCEPT, iteration continues; otherwise processing stops according to the returned vector.

iptables Integration

iptables is a user‑space utility that configures the netfilter hooks. It consists of:

User‑space commands that interact with the kernel module.

Kernel‑space code that maintains rule tables in memory.

xt_table Initialization

#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) |
                            (1 << NF_INET_FORWARD) |
                            (1 << NF_INET_LOCAL_OUT))
static const struct xt_table packet_filter = {
    .name = "filter",
    .valid_hooks = FILTER_VALID_HOOKS,
    .me = THIS_MODULE,
    .af = NFPROTO_IPV4,
    .priority = NF_IP_PRI_FILTER,
};

During module initialization ( iptable_filter_init) the function xt_hook_link registers the table for each valid hook (LOCAL_IN, FORWARD, LOCAL_OUT) with the appropriate priority.

Hook Priorities

enum nf_ip_hook_priorities {
    NF_IP_PRI_RAW    = -300,
    NF_IP_PRI_MANGLE = -150,
    NF_IP_PRI_NAT_DST = -100,
    NF_IP_PRI_FILTER = 0,
    NF_IP_PRI_SECURITY = 50,
    NF_IP_PRI_NAT_SRC = 100,
};

When a packet reaches a hook, callbacks from all tables registered at that hook are executed in the order defined by these priorities.

ipt_do_table()

The filter table’s hook callback iptable_filter_hook invokes the generic rule‑checking function ipt_do_table. This function receives the skb, the hook identifier, and the xt_table, then walks the rule list:

Compare the packet’s IP header with the first rule’s .ipt_ip. If it does not match, jump to the next rule via next_offset.

If it matches, evaluate each ipt_entry_match associated with the rule; each match may accept, drop, or continue.

After all matches succeed, execute the rule’s ipt_entry_target to produce the final netfilter vector.

Flexibility and Update Latency

The data structures allow powerful extensions: custom match conditions and actions can be added to each rule, and rules can jump between tables. However, because rule lengths vary and tables occupy contiguous memory, iptables updates replace the entire table atomically. In large Kubernetes clusters with many Services, this full‑replace approach can cause noticeable latency due to kernel locking.

User‑Space Tables, Chains, and Rules

From user space, iptables commands manipulate three concepts:

Table : corresponds to an xt_table (e.g., filter, nat).

Chain : a set of rules attached to a specific hook within a table.

Rule : composed of an ipt_entry, optional ipt_entry_match objects, and an ipt_entry_target that defines the action.

Rules are stored as a linked list in memory; each ipt_entry contains offsets to the next rule, matches, and target.

References

netfilter.h – include/linux/netfilter.h – Bootlin

Network_stack.pdf

Linux netfilter Hacking HOWTO

Linux Kernel Networking: Implementation and Theory – Chapter 9: Netfilter

Netfilter framework providing hooks system for Nftables

A Deep Dive into Iptables and Netfilter Architecture – DigitalOcean

Comparing kube-proxy modes: iptables or IPVS?

Linux Conntrack: Why It Breaks Down and Avoiding the Problem

走进 Linux 内核之 Netfilter 框架 – 掘金

19.3 The Netfilter Architecture of Linux 2.4 – Linux Network Architecture

Linux kerneliptablesnetfilterpacket filteringconnection trackingnetwork hooks
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.