How to Configure nftables Firewall on RHEL 7

nftables is the modern successor to iptables, combining the functionality of iptables, ip6tables, arptables, and ebtables into a single, unified framework with a cleaner syntax, better performance, and native support for atomic rule replacement. While firewalld is the default front end on RHEL 7, nftables is available starting with RHEL 7.7 and provides a low-level alternative for administrators who want direct control over the netfilter subsystem. This guide covers installing nftables on RHEL 7, understanding its table and chain model, writing rules with the nft command, using sets and maps for efficient multi-address matching, and persisting your ruleset across reboots.

Prerequisites

  • RHEL 7.7 or later (nftables is not available in earlier RHEL 7 minor releases)
  • Root or sudo access
  • An active SSH session — keep it open while testing firewall changes
  • Basic familiarity with firewall concepts (tables, chains, policies)

Step 1: Install nftables

The nftables package is in the base RHEL 7 repository from version 7.7 onward:

yum install nftables -y

Verify the installation and check the version:

nft --version

Enable and start the nftables service, which will load rules from /etc/sysconfig/nftables.conf at boot:

systemctl enable nftables
systemctl start nftables

If you are transitioning from firewalld or iptables, stop those services first to avoid conflicts:

systemctl stop firewalld
systemctl disable firewalld
systemctl mask firewalld

systemctl stop iptables
systemctl disable iptables

Step 2: Understand the nftables Data Model

nftables uses a hierarchy of three objects:

  • Tables — top-level containers associated with an address family (ip, ip6, inet, arp, bridge). The inet family handles both IPv4 and IPv6 in one table, which is the recommended approach for most servers.
  • Chains — ordered lists of rules within a table. Base chains hook into the kernel netfilter hooks (input, output, forward, prerouting, postrouting); regular chains are called by rules using jump or goto.
  • Rules — individual match-and-verdict statements within a chain.

Step 3: View the Current Ruleset

Display all currently loaded tables, chains, and rules:

nft list ruleset

On a fresh installation the output will be empty. To list only a specific table:

nft list table inet filter

Step 4: Create a Table and Chains

Create an inet family table named filter that handles both IPv4 and IPv6 traffic:

nft add table inet filter

Add a base chain for incoming traffic with a default drop policy:

nft add chain inet filter input { type filter hook input priority 0 ; policy drop ; }

Add chains for forwarded and outgoing traffic:

nft add chain inet filter forward { type filter hook forward priority 0 ; policy drop ; }
nft add chain inet filter output { type filter hook output priority 0 ; policy accept ; }

Verify the chains were created:

nft list table inet filter

Step 5: Add Rules to the Input Chain

Allow loopback traffic, which is required by many local services:

nft add rule inet filter input iif lo accept

Allow established and related connections (stateful tracking equivalent to iptables -m state):

nft add rule inet filter input ct state established,related accept

Drop invalid packets:

nft add rule inet filter input ct state invalid drop

Allow ICMP (IPv4 ping) and ICMPv6:

nft add rule inet filter input ip protocol icmp accept
nft add rule inet filter input ip6 nexthdr icmpv6 accept

Allow SSH (TCP port 22):

nft add rule inet filter input tcp dport 22 accept

Allow HTTP and HTTPS:

nft add rule inet filter input tcp dport { 80, 443 } accept

Note the curly-brace syntax — nftables supports anonymous sets directly in rules, eliminating the need for multiple identical rules for different ports.

Step 6: Add Packet Counters

nftables can attach byte and packet counters to individual rules without separate tools. Add a counter to the SSH rule for monitoring:

nft add rule inet filter input tcp dport 22 counter accept

View the counters:

nft list chain inet filter input

Output will include per-rule packet and byte counts:

table inet filter {
  chain input {
    ...
    tcp dport 22 counter packets 47 bytes 3124 accept
  }
}

Step 7: Use Named Sets for Efficient Multi-Address Matching

Named sets allow you to define a collection of addresses, ports, or prefixes once and reference them in multiple rules. Create a set of trusted management IP addresses:

nft add set inet filter trusted_hosts { type ipv4_addr ; }
nft add element inet filter trusted_hosts { 10.0.0.10, 10.0.0.11, 192.168.1.5 }

Reference the set in a rule to restrict SSH to those addresses only:

nft add rule inet filter input ip saddr @trusted_hosts tcp dport 22 accept

Adding or removing addresses from the set takes effect immediately without reloading the entire ruleset:

nft add element inet filter trusted_hosts { 10.0.1.50 }
nft delete element inet filter trusted_hosts { 10.0.0.10 }

Step 8: Use Maps for Dynamic Port-to-Action Mapping

Maps associate keys with verdicts, enabling compact multi-service rules. For example, map specific ports to accept or drop:

nft add map inet filter port_verdict { type inet_service : verdict ; }
nft add element inet filter port_verdict { 22 : accept, 80 : accept, 443 : accept, 23 : drop }
nft add rule inet filter input tcp dport vmap @port_verdict

Step 9: Persist Rules in /etc/sysconfig/nftables.conf

Flush the current ruleset to a file and configure the nftables service to load it on boot:

nft list ruleset > /etc/sysconfig/nftables.conf

The nftables systemd service reads this file at startup. Verify by examining the service unit:

systemctl cat nftables

To flush all rules and reload from the file at any time:

nft flush ruleset
nft -f /etc/sysconfig/nftables.conf

For atomic rule replacement (replacing all rules in one kernel operation with no momentary gap):

nft -f /etc/sysconfig/nftables.conf

Unlike iptables, nftables applies the entire file as a transaction, so the transition between old and new rules is instantaneous.

Step 10: Delete Specific Rules

Each rule in nftables has a numeric handle. To find handles:

nft list chain inet filter input --handle

Delete a rule by its handle (e.g., handle 8):

nft delete rule inet filter input handle 8

Conclusion

nftables brings a coherent, powerful approach to Linux packet filtering on RHEL 7. The unified inet address family eliminates the need for parallel IPv4 and IPv6 rule sets, anonymous and named sets replace repetitive single-value rules, and atomic file loading via nft -f makes rule updates safe and instantaneous. While the tooling is slightly less mature than iptables on RHEL 7 and documentation is thinner, nftables is the future of Linux firewalling — Red Hat Enterprise Linux 8 and 9 use it as the default backend. Learning it on RHEL 7 now positions you well for upgrades and ensures your firewall configurations remain relevant as the ecosystem continues to move away from the legacy iptables framework.