A simpler packet filter

Traffic Rules

© Photo by Ian Taylor on Unsplash

© Photo by Ian Taylor on Unsplash

Article from Issue 270/2023

Filter rules for firewalls can be tricky. As the successor to iptables, nftables simplifies the process of creating and maintaining firewall rules.

Whether you are training to become an IT specialist, managing networks, or preparing for the Linux Professional Institute second certification (LPIC-2) [1], you can't avoid the topic of firewalls, especially rules for filtering packets on the network. After ipchains and Ipfw, the netfilter project's [2] iptables is mostly commonly used for configuring firewall rules on Linux, while FreeBSD/NetBSD and the two Solaris successors Illumos and OpenIndiana use IPFilter [3].

However, iptables is getting a little long in the tooth. In particular, the program code has become increasingly complex. Small changes in the project core have tended to affect all related tools. Iptables, ip6tables, ebtables, and arptables all come from the same codebase, but not in the form of modules. Instead they rely on code duplication, which has resulted in the four tools drifting apart over time. Iptables has been the best maintained, while ebtables has been neglected. Bugs fixed in iptables are still unfixed in ebtables years later.

This situation prompted the netfilter project to launch the development of an iptables successor, nftables [4], as early as 2009. The first two letters in nftables are derived from the project (netfilter). The stated development goals include higher data throughput, greater scalability with a view to changing requirements, and – in particular – a modular structure leading to improved maintainability [5]. Starting with Linux 3.13 (January 2014), nftables is part of the Linux kernel [6], using proven in-house components by the netfilter project.

Since the release of Debian 10 "Buster" in early July 2019, Debian also uses nftables [7], which in turn has affected derivatives such as Ubuntu and Linux Mint, as well as Red Hat Enterprise Linux (RHEL) and CentOS v7 [8] and later. All major distributions have included nftables for quite some time. While they don't necessarily enable nftables by default, it is at least operational.

Removals and Conversions

To create firewall rules, you need the iptables (IPv4), ip6tables (IPv6), arptables (ARP packets), and ebtables (Ethernet frames) command-line tools. Nftables replaces all four with a single command-line tool named nft, which you can use to set all the rules for accepting, forwarding, modifying, or dropping packets from the network on the system.

While iptables uses various filters and the three processing chains INPUT, FORWARD, and OUTPUT to forward the packets, you have to define these yourself for the nftables framework to recognize them.

The nft tool draws on two libraries: libnml, a minimalist Netlink library [9], and libnftml, a Netlink userspace library [10]. This results in a reduction of code size in the Linux kernel, and minor changes to nft do not prompt the need to rebuild the kernel [11].

To ensure that the correct kernel module has been loaded into the system kernel, check the output from the modinfo (Figure 1) and lsmod (Figure 2) commands. Once this has been confirmed (as shown in Figures 1 and 2), you can start using nft directly.

Figure 1: The modinfo command's output provides information about the kernel module.
Figure 2: You can use lsmod to find out if the system has the kernel module in place.

Basic Configuration

Initially, nftables starts with a completely empty ruleset; there are no predefined tables, chains, or rules. As a user (or admin), you first create the tables, add chains to the tables that hook into the Linux kernel as netfilter hooks, and then fill the chains with the appropriate rules. All of the above steps are done using the nft command, which you execute as root.

Listing 1 demonstrates how to define a firewall that prevents (currently) any packets from passing through. Line 1 creates a table for IP packets of the filter type. Line 2 adds a chain to the filter table. Line 3 adds a rule to the chain that drops all packets (drop).

Listing 1

Defining a Firewall

01 # nft add table ip filter
02 # nft add chain ip filter input {type filter hook input priority 0\;}
03 # nft add rule ip filter input drop
04 # nft list ruleset -a
05 # nft delete rule ip filter input handle 2

Line 4 provides an overview with all the firewall's rules (Figure 3). Next to the entries, you will see comments formatted as # handle NUMBER; you use these comments to reference the entries. This is especially interesting if you want to delete or change existing definitions or insert new definitions in front of or after the entries. For example, line 5 deletes the drop rule.

Figure 3: The nft list ruleset -a command lists all enabled rules.

Basic Operation

When it comes to writing the rules, the nft developers rely on the Berkeley Packet Filter (BPF) [12] and use the classic tcpdump [13] as a guide, so you don't have to learn everything from scratch [14].

In addition, nft also provides a number of address families. The predefined familes are arp (ARP), bridge (previously provided by ebtables), inet (covers IPv4 and IPv6), ip (for IPv4), ip6 (for IPv6), and netdev (which is used to filter incoming packets before they reach Layer 3 according to the ISO/OSI specification [15]).

The nft tool acts as a translator of the rules and keeps them in a small virtual machine (nftables core) for communication with the Linux kernel.

Where appropriate, I will compare the spelling and calls in iptables and nft based on practical examples. Listing 2 shows how to enable port 22 for incoming packets, just as you would for access via SSH, for both iptables and nft. You will notice that nft reduces this to a single command with simpler syntax.

Listing 2

Enabling Port 22 for Incoming Packets

### Allow incoming packets on port 22.
### With Iptables:
# iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
### With Nft:
$ nft add rule inet filter input tcp dport 22 ct state new,established accept

If you want to add ports 80 and 443 (i.e., HTTP and HTTPS), you need two more lines for iptables per port. With nft, on the other hand, it is sufficient to extend the existing line to combine all three protocols in one go. All three ports are enclosed in curly brackets, starting with port 22 followed by ports 80 and 443 separated by commas (Listing 3).

Listing 3

Adding Two Additional Ports

# nft add rule inet filter input tcp dport { 22, 80, 443 } ct state new,established accept

Please note that the spaces inside the brackets in Listing 3 must be exactly as shown – otherwise Bash will choke and protest. Users of Zsh run into the same problem, which can be solved by quoting appropriately.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Nftables

    The nftables firewall utility offers a simpler and more consistent approach for managing firewalls in Linux.

  • New Kernel Firewall Nftables to Succeed Netfilter

    The Netfilter team has long been mulling over rework of firewall code in the Linux kernel. Now team lead Patrick McHardy ends months of work by announcing nftables.

  • FAQ

    Nftables promises to be the future of Linux firewalls. Meet iptables' replacement.

  • Persistent iptables

    The Linux iptables packet filter lacks an easy way to load rules automatically after restarting a system, but you can automate this process several ways.

  • Netfilter's Recent Module

    Netfilter’s Recent module builds a temporary blacklist to keep intruders off your network.

comments powered by Disqus