Demystifying Netfilter and nftables: How Linux Packet Filtering Really Works


Understanding how Linux handles network packets at the kernel level can feel overwhelming — until you see how the pieces fit together. Netfilter provides the foundation, while nftables gives us a modern, flexible way to define firewall rules, NAT, and packet mangling.

Whether you’re debugging connectivity issues, writing security tools, or optimizing performance, knowing these internals helps you work more effectively with Linux networking.

Netfilter: The Kernel’s Packet Processing Framework

Netfilter is the Linux kernel’s packet filtering and mangling infrastructure. It defines well-known hook points where packets can be inspected and modified as they flow through the system:

  • PREROUTING — Right after a packet arrives, before routing decisions
  • INPUT — Packets destined for the local system
  • FORWARD — Packets being routed through the host
  • OUTPUT — Locally generated packets
  • POSTROUTING — After routing, before leaving the host

Chains attached to these hooks let you enforce security policies, perform NAT, or influence routing.

nftables: The Modern Replacement for iptables

nftables brings a cleaner, more consistent syntax and better performance compared to the older iptables framework. It organizes configuration into tables, chains, rules, sets, and expressions.

Core nftables Building Blocks

Tables

Containers that group related chains, sets, and rules. Common families include ip (IPv4), ip6 (IPv6), and inet (both).

nft add table ip myfirewall

Chains

Sequences of rules. Base chains attach directly to Netfilter hooks and define behavior (filter, nat, route).

nft add chain ip myfirewall input { type filter hook input priority 0 \; }

Rules

Define matching conditions and actions (accept, drop, jump, etc.).

nft add rule ip myfirewall input tcp dport 22 accept

Sets

Efficient collections for matching (IP addresses, ports, etc.).

nft add set ip myfirewall trusted_ips { type ipv4_addr \; }
nft add element ip myfirewall trusted_ips { 192.168.1.10, 10.0.0.5 }

Practical Example: Simple Firewall

Here’s how to create a basic firewall that allows SSH from trusted IPs and drops everything else:

nft add table ip myfirewall
nft add chain ip myfirewall input { type filter hook input priority 0 \; }
nft add set ip myfirewall trusted_ips { type ipv4_addr \; }
nft add element ip myfirewall trusted_ips { 192.168.1.1, 192.168.1.2 }
nft add rule ip myfirewall input ip saddr @trusted_ips accept
nft add rule ip myfirewall input drop

Behind the Scenes: User Space to Kernel

Tools like nft use libmnl and libnftnl to communicate with the kernel via Netlink. This allows atomic batch operations — multiple changes applied together or not at all — ensuring consistent firewall state.

Best Practices for Production

  • Use named sets for frequently updated lists (trusted IPs, blocked addresses)
  • Keep base chains simple and explicit with a final drop rule
  • Leverage priorities to control execution order
  • Batch operations when making multiple changes
  • Monitor and log dropped packets for visibility

Conclusion

Netfilter and nftables form a powerful, unified framework for packet processing in Linux. Understanding how tables, chains, rules, and sets work together helps you build more effective firewalls, troubleshoot network issues faster, and appreciate the elegance of the modern Linux networking stack.

Whether you’re securing servers, implementing complex NAT rules, or exploring kernel internals, nftables gives you the tools to control traffic with precision and clarity.

Post a Comment

Previous Post Next Post