nftables Firewall

nftables cheatsheet — create tables, chains, add rules for allow/drop traffic, NAT. nft list ruleset, nft add rule, nft flush ruleset. Modern iptables replacement.

12 min read

What it is

nftables is a packet filtering framework that replaces iptables, ip6tables, arptables, and ebtables with a single, unified tool for IPv4, IPv6, ARP, and bridge filtering. You reach for it to configure your system’s firewall rules.

Installation

Linux

nftables is typically installed by default on modern Linux distributions. If not, use your distribution’s package manager:

Debian/Ubuntu:

sudo apt update
sudo apt install nftables

Fedora/CentOS/RHEL:

sudo dnf install nftables
# or
sudo yum install nftables

Arch Linux:

sudo pacman -S nftables

After installation, you’ll likely need to enable and start the service:

sudo systemctl enable nftables
sudo systemctl start nftables

Mac and Windows

nftables is a Linux-specific tool and is not directly available on macOS or Windows. For firewall functionality on these systems, you would use their native firewall tools (e.g., pf on macOS, Windows Defender Firewall on Windows).

Core Concepts

  • Tables: A collection of chains. Tables are named and are associated with an address family (e.g., ip, ip6, inet, arp, bridge). The inet family is a meta-family that handles both IPv4 and IPv6 traffic.
  • Chains: Ordered lists of rules. Chains are named and have a type (filter, nat, route, etc.) and a hook (where in the network stack they are attached, e.g., prerouting, input, forward, output, postrouting).
  • Rules: Individual statements that match packets and specify what to do with them (e.g., accept, drop, reject, redirect). Rules consist of a match expression and a statement (or set of statements).
  • Sets: Collections of elements (IP addresses, ports, etc.) that can be referenced by rules, improving efficiency and readability.
  • Maps: Similar to sets but associate keys with values, allowing for more complex actions based on matching elements.
  • Expressions: Conditions used to match packets. These can be simple (e.g., tcp dport 80) or complex combinations using logical operators.
  • Statements: Actions to be performed on matched packets (e.g., accept, drop, reject, counter, log, masquerade).

Commands / Usage

The primary command is nft.

Managing Tables

  • List all tables:

    nft list tables
    

    Lists all tables with their family and name.

  • List a specific table’s contents (chains, rules):

    nft list table ip filter
    

    Displays all chains and rules within the ip family’s filter table.

  • List all tables and their contents (comprehensive):

    nft list ruleset
    

    Shows the entire current firewall configuration.

  • Add a table:

    nft add table ip filter
    

    Creates a new table named filter in the ip address family.

  • Delete a table:

    nft delete table ip filter
    

    Removes the filter table and all its contents.

Managing Chains

  • Add a chain to a table:

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

    Adds an input chain of type filter to the ip filter table, attaching it to the input hook with priority 0. The semicolon and backslash are important for multi-line statements in the shell.

  • Add a chain with a policy:

    nft add chain ip filter forward { type filter hook forward priority 0 \; policy drop \; }
    

    Adds a forward chain to the ip filter table with a default drop policy.

  • List chains in a table:

    nft list chain ip filter input
    

    Shows the rules within the input chain of the ip filter table.

  • Delete a chain:

    nft delete chain ip filter input
    

    Removes the input chain and all its rules.

  • Set a chain’s policy:

    nft chain ip filter input policy accept
    

    Changes the default policy of the input chain to accept.

Managing Rules

  • Add a rule to a chain (e.g., allow established connections):

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

    Adds a rule to the ip filter input chain that accepts packets if the connection tracking state is established or related.

  • Add a rule to log dropped packets:

    nft add rule ip filter input drop log prefix "nftables-dropped: "
    

    Adds a rule to the ip filter input chain that drops packets and logs them with a specific prefix.

  • Add a rule to reject packets:

    nft add rule ip filter input tcp dport 22 reject
    

    Rejects incoming TCP packets destined for port 22 on the ip filter input chain.

  • Add a rule to allow specific TCP port:

    nft add rule ip filter input tcp dport 80 accept
    

    Allows incoming TCP traffic on port 80.

  • Add a rule to allow specific UDP port:

    nft add rule ip filter input udp dport 53 accept
    

    Allows incoming UDP traffic on port 53.

  • Add a rule to allow specific IP address:

    nft add rule ip filter input ip saddr 192.168.1.100 accept
    

    Allows all traffic originating from the IP address 192.168.1.100.

  • Add a rule to allow specific IP address and port:

    nft add rule ip filter input ip saddr 192.168.1.100 tcp dport 22 accept
    

    Allows SSH traffic from a specific IP address.

  • Add a rule to drop all other traffic (after allowing specific ports):

    nft add rule ip filter input drop
    

    This rule should typically be the last one in a chain with a default accept policy to block everything else.

  • Add a rule with multiple matches and actions (NAT example):

    nft add rule ip nat postrouting ip saddr 192.168.1.0/24 oifname eth0 masquerade
    

    Adds a NAT rule to the ip nat postrouting chain that masquerades outgoing traffic from the 192.168.1.0/24 network if it leaves via interface eth0.

  • Add a rule with a counter:

    nft add rule ip filter input tcp dport 80 counter accept
    

    Accepts traffic on port 80 and increments a counter for that rule.

  • List rules in a chain:

    nft list chain ip filter input
    

    Shows all rules, including their handles, within the specified chain.

  • Delete a rule by handle:

    nft delete rule ip filter input handle 1
    

    Deletes the rule with handle 1 from the ip filter input chain.

  • Delete a rule by its exact definition:

    nft delete rule ip filter input tcp dport 80 accept
    

    Deletes the specific rule that accepts TCP traffic on port 80.

Managing Sets

  • Add a set:

    nft add set ip filter blocked_ips { type ipv4_addr\; }
    

    Creates an empty set named blocked_ips for IPv4 addresses in the ip filter table.

  • Add elements to a set:

    nft add element ip filter blocked_ips { 1.2.3.4, 5.6.7.8 }
    

    Adds IP addresses 1.2.3.4 and 5.6.7.8 to the blocked_ips set.

  • Add elements to a set with ports:

    nft add element ip filter blocked_ports { tcp dport { 22, 80, 443 } \}
    

    Adds TCP ports 22, 80, and 443 to a set (assuming the set is defined to handle port ranges).

  • List a set’s elements:

    nft list set ip filter blocked_ips
    

    Shows all elements currently in the blocked_ips set.

  • Use a set in a rule:

    nft add rule ip filter input ip saddr @blocked_ips drop
    

    Drops any traffic where the source IP address is present in the blocked_ips set.

  • Delete elements from a set:

    nft delete element ip filter blocked_ips { 1.2.3.4 }
    

    Removes 1.2.3.4 from the blocked_ips set.

  • Delete a set:

    nft delete set ip filter blocked_ips
    

    Removes the blocked_ips set.

Managing Maps

  • Add a map:

    nft add map ip filter port_map { type ipv4_addr : integer\; }
    

    Creates a map named port_map in the ip filter table, mapping IPv4 addresses to integers.

  • Add elements to a map:

    nft add element ip filter port_map { 192.168.1.100 : 8080 \}
    

    Adds an entry mapping 192.168.1.100 to 8080.

  • Use a map in a rule:

    nft add rule ip filter output ip daddr 192.168.1.100 tcp dport <port_map[ip.dst]> accept
    

    This is a conceptual example. nftables maps are typically used for more direct actions or lookups within statements. A more practical example might involve using a map to set a specific egress interface or queue based on source IP.

Batch Mode and Configuration Files

  • Apply a batch of commands from stdin:

    nft -f - <<EOF
    add table ip filter
    add chain ip filter input { type filter hook input priority 0 \; }
    add rule ip filter input accept
    EOF
    

    Executes multiple nft commands piped into the tool.

  • Apply configuration from a file:

    nft -f /etc/nftables.conf
    

    Loads the entire firewall configuration from the specified file.

  • Save current ruleset to a file:

    nft list ruleset > /etc/nftables.conf
    

    Saves the active nftables configuration to a file.

Other Useful Commands

  • Flush all rules from a table:

    nft flush ruleset
    

    Removes all tables, chains, and rules. Use with extreme caution!

  • Flush all rules from a specific chain:

    nft flush chain ip filter input
    

    Removes all rules from the input chain but leaves the chain itself.

  • Flush all elements from a set:

    nft flush set ip filter blocked_ips
    

    Removes all elements from the blocked_ips set.

  • Show packet/byte counters for rules:

    nft list chain ip filter input -a
    

    The -a flag shows detailed counters for each rule.

  • Get help on a specific command or object:

    nft help add rule
    nft help ip
    nft help tcp
    

    Provides detailed help information.

Common Patterns

  • Basic Firewall Setup (Default Deny):

    # Create tables and chains
    nft add table inet filter
    nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
    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 \; }
    
    # Allow loopback traffic
    nft add rule inet filter input iif lo accept
    nft add rule inet filter output oif lo accept
    
    # Allow established/related connections
    nft add rule inet filter input ct state established,related accept
    nft add rule inet filter output ct state established,related accept
    
    # Allow SSH
    nft add rule inet filter input tcp dport 22 accept
    
    # Allow HTTP/HTTPS
    nft add rule inet filter input tcp dport { 80, 443 } accept
    
    # Log and drop invalid packets
    nft add rule inet filter input ct state invalid drop
    nft add rule inet filter input counter log prefix "nftables-invalid: " drop
    
    # Save the ruleset
    sudo nft list ruleset > /etc/nftables.conf
    
  • Port Forwarding (DNAT):

    # Assuming you have an 'inet nat prerouting' chain set up
    nft add table inet nat
    nft add chain inet nat prerouting { type nat hook prerouting priority -100 \; }
    nft add chain inet nat postrouting { type nat hook postrouting priority 100 \; }
    
    # Forward external port 8080 to internal IP 192.168.1.50 port 80
    nft add rule inet nat prerouting tcp dport 8080 dnat to 192.168.1.50:80
    
    # Masquerade traffic going out from the internal network
    nft add rule inet nat postrouting ip saddr 192.168.1.0/24 oifname eth0 masquerade
    
  • Blocking a range of IPs using a set:

    # Create a set for blocked IPs
    nft add set ip filter blocked_ips { type ipv4_addr\; flags interval\; }
    
    # Add a range of IPs to block
    nft add element ip filter blocked_ips { 192.168.1.100-192.168.1.150 \}
    
    # Add a rule to drop traffic from these IPs
    nft add rule ip filter input ip saddr @blocked_ips drop
    
  • Rate Limiting SSH:

    # Add a chain for rate limiting
    nft add chain ip filter input { type filter hook input priority 0 \; } # If not already present
    nft add chain ip filter ssh_rate_limit { type filter hook input priority 10 \; } # Custom priority
    
    # Add rule to redirect SSH to the rate limit chain
    nft add rule ip filter input tcp dport 22 jump ssh_rate_limit
    
    # Apply rate limiting within the ssh_rate_limit chain
    nft add rule ip filter ssh_rate_limit tcp dport 22 meter ssh_limit { rate 5/minute\; } accept
    nft add rule ip filter ssh_rate_limit tcp dport 22 reject
    

    This example uses meter (rate limiting) which is a more advanced nftables feature.

  • Using inet family for IPv4 and IPv6:

    # This table handles both IPv4 and IPv6
    nft add table inet filter
    nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
    
    # Allow SSH from any IP version
    nft add rule inet filter input tcp dport 22 accept
    

Gotchas

  • inet vs. ip / ip6: The inet family is a meta-family that handles both IPv4 and IPv6. If you use ip or ip6 tables, you need separate rules for each. inet is often preferred for simplicity if you don’t need to differentiate.
  • Rule Order Matters: Rules are processed in the order they appear within a chain. The first matching rule determines the action. Place more specific rules before general ones.
  • Default Policies: If a packet doesn’t match any rule in a chain and there’s no default policy, the packet continues to the next stage. A policy drop is crucial for a secure firewall.
  • ct state invalid: Always drop invalid packets early in your input chain. These are packets that don’t belong to any known connection and are often indicative of scanning or malicious activity.
  • add rule vs. insert rule: add rule appends the rule to the end of the chain. insert rule inserts it at the beginning. Use insert rule if you need a rule to be evaluated before others (e.g., to override a general accept with a specific drop).
  • nftables.conf Syntax: When writing to /etc/nftables.conf, ensure correct syntax, including semicolons and curly braces. Incorrect syntax will prevent nftables from loading the ruleset.
  • Saving Rules: Rules added directly via the nft command are volatile and lost on reboot. You must save the ruleset to /etc/nftables.conf (or your distribution’s equivalent) and ensure the nftables service is enabled to load them on boot.
  • priority in Chains: The priority value determines the order of execution for chains hooked at the same point. Lower numbers usually mean earlier execution. Standard priorities are often -150 (raw), -100 (mangle/nat prerouting), 0 (filter input/forward/output), 100 (nat postrouting).
  • flags interval for Sets: When creating sets intended to hold IP address ranges, use flags interval to enable this functionality.
  • masquerade vs. snat: masquerade is dynamic Source NAT (SNAT) typically used on interfaces with changing IP addresses (like DHCP clients). snat is static SNAT where you specify the source IP address.