nftables – the New Firewall Backend in RHEL 8

nftables is a replacement for all of: iptables, ip6tables, arptables, ebtables, and ipset (henceforth known as “iptables and family”). The main advantages of nftables over iptables are the simplification of the Linux kernel Application Binary Interface (ABI), reduction of code duplication, improved error reporting, and more efficient execution, storage and incremental changes of filtering rules. Traditionally used iptables, ip6tables, arptables and ebtables (for IPv4, IPv6, ARP and Ethernet bridging, respectively) are replaced with nft as a single unified implementation, providing firewall configuration on top of the in-kernel virtual machine. This means you can optimize rules, e.g. log and drop a packet in the same rule. In iptables this would require two rules, both with the same match parameters.

There are many longstanding issues with firewalld that we can address with nftables that were not possible with the old iptables backend. For the end-user, the nftables backend allows the following improvements:

  • All firewall information viewable with a single underlying tool, nft
  • Single rule for both IPv4 and IPv6 instead of duplicating rules
  • Does not assume complete control of firewall backend
  • Won’t delete firewall rules installed by other tools or users
  • Rule optimizations (log and deny in same rule)

What are the differences?

Nftables is easier to use and combines all tools of the IPtables framework (e. g. iptables, ip6tables, arptables, etc.) in a single tool. The syntax has also become better and easier, but there is a compatibility layer so you could still use the old IPtables syntax even if filtering is internally done with nftables. Although it basically does the same job as IPtables, its architecture is different. Unlike IPtables, there are no predefined default tables and chains (like filter/NAT or FORWARD/INPUT) in nftables. You can also perform multiple actions in a single rule.

Here is an example for the simple task of dropping any packets to the destination IP address 1.2.3.4.
# nft add rule ip filter output ip daddr 1.2.3.4 drop

For the old IPtables this would’ve been:
# iptables -A OUTPUT -d 1.2.3.4 -j DROP

Another example for the creation of a ruleset that allows packets to use different ports and allows different icmpv6 types:
# nft add rule ip6 filter input tcp dport {telnet, http, https} accept
# nft add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept

That’s it. Small and simple.

Just to give you an idea, with the old IPtables this would’ve been something like:
# ip6tables -A INPUT -p tcp -m multiport –dports 23,80,443 -j ACCEPT
# ip6tables -A INPUT -p icmpv6 –icmpv6-type neighbor-solicitation -j ACCEPT
# ip6tables -A INPUT -p icmpv6 –icmpv6-type echo-request -j ACCEPT
# ip6tables -A INPUT -p icmpv6 –icmpv6-type router-advertisement -j ACCEPT
# ip6tables -A INPUT -p icmpv6 –icmpv6-type neighbor-advertisement -j ACCEPT

How does firewalld use nftables?

firewalld interacts with nftables directly through the nft binary. This is similar to how firewalld interacts with iptables and family in previous Red Hat Linux versions.