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). Theinetfamily 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 tablesLists all tables with their family and name.
-
List a specific table’s contents (chains, rules):
nft list table ip filterDisplays all chains and rules within the
ipfamily’sfiltertable. -
List all tables and their contents (comprehensive):
nft list rulesetShows the entire current firewall configuration.
-
Add a table:
nft add table ip filterCreates a new table named
filterin theipaddress family. -
Delete a table:
nft delete table ip filterRemoves the
filtertable 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
inputchain of typefilterto theip filtertable, attaching it to theinputhook with priority0. 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
forwardchain to theip filtertable with a defaultdroppolicy. -
List chains in a table:
nft list chain ip filter inputShows the rules within the
inputchain of theip filtertable. -
Delete a chain:
nft delete chain ip filter inputRemoves the
inputchain and all its rules. -
Set a chain’s policy:
nft chain ip filter input policy acceptChanges the default policy of the
inputchain toaccept.
Managing Rules
-
Add a rule to a chain (e.g., allow established connections):
nft add rule ip filter input ct state established,related acceptAdds a rule to the
ip filter inputchain that accepts packets if the connection tracking state isestablishedorrelated. -
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 inputchain 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 rejectRejects incoming TCP packets destined for port 22 on the
ip filter inputchain. -
Add a rule to allow specific TCP port:
nft add rule ip filter input tcp dport 80 acceptAllows incoming TCP traffic on port 80.
-
Add a rule to allow specific UDP port:
nft add rule ip filter input udp dport 53 acceptAllows 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 acceptAllows 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 acceptAllows 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 dropThis rule should typically be the last one in a chain with a default
acceptpolicy 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 masqueradeAdds a NAT rule to the
ip nat postroutingchain that masquerades outgoing traffic from the192.168.1.0/24network if it leaves via interfaceeth0. -
Add a rule with a counter:
nft add rule ip filter input tcp dport 80 counter acceptAccepts traffic on port 80 and increments a counter for that rule.
-
List rules in a chain:
nft list chain ip filter inputShows all rules, including their handles, within the specified chain.
-
Delete a rule by handle:
nft delete rule ip filter input handle 1Deletes the rule with handle
1from theip filter inputchain. -
Delete a rule by its exact definition:
nft delete rule ip filter input tcp dport 80 acceptDeletes 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_ipsfor IPv4 addresses in theip filtertable. -
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.4and5.6.7.8to theblocked_ipsset. -
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_ipsShows all elements currently in the
blocked_ipsset. -
Use a set in a rule:
nft add rule ip filter input ip saddr @blocked_ips dropDrops any traffic where the source IP address is present in the
blocked_ipsset. -
Delete elements from a set:
nft delete element ip filter blocked_ips { 1.2.3.4 }Removes
1.2.3.4from theblocked_ipsset. -
Delete a set:
nft delete set ip filter blocked_ipsRemoves the
blocked_ipsset.
Managing Maps
-
Add a map:
nft add map ip filter port_map { type ipv4_addr : integer\; }Creates a map named
port_mapin theip filtertable, 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.100to8080. -
Use a map in a rule:
nft add rule ip filter output ip daddr 192.168.1.100 tcp dport <port_map[ip.dst]> acceptThis is a conceptual example.
nftablesmaps 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 EOFExecutes multiple
nftcommands piped into the tool. -
Apply configuration from a file:
nft -f /etc/nftables.confLoads the entire firewall configuration from the specified file.
-
Save current ruleset to a file:
nft list ruleset > /etc/nftables.confSaves the active
nftablesconfiguration to a file.
Other Useful Commands
-
Flush all rules from a table:
nft flush rulesetRemoves all tables, chains, and rules. Use with extreme caution!
-
Flush all rules from a specific chain:
nft flush chain ip filter inputRemoves all rules from the
inputchain but leaves the chain itself. -
Flush all elements from a set:
nft flush set ip filter blocked_ipsRemoves all elements from the
blocked_ipsset. -
Show packet/byte counters for rules:
nft list chain ip filter input -aThe
-aflag shows detailed counters for each rule. -
Get help on a specific command or object:
nft help add rule nft help ip nft help tcpProvides 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 rejectThis example uses
meter(rate limiting) which is a more advancednftablesfeature. -
Using
inetfamily 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
inetvs.ip/ip6: Theinetfamily is a meta-family that handles both IPv4 and IPv6. If you useiporip6tables, you need separate rules for each.inetis 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 dropis crucial for a secure firewall. ct state invalid: Always dropinvalidpackets 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 rulevs.insert rule:add ruleappends the rule to the end of the chain.insert ruleinserts it at the beginning. Useinsert ruleif you need a rule to be evaluated before others (e.g., to override a generalacceptwith a specificdrop).nftables.confSyntax: When writing to/etc/nftables.conf, ensure correct syntax, including semicolons and curly braces. Incorrect syntax will preventnftablesfrom loading the ruleset.- Saving Rules: Rules added directly via the
nftcommand are volatile and lost on reboot. You must save the ruleset to/etc/nftables.conf(or your distribution’s equivalent) and ensure thenftablesservice is enabled to load them on boot. priorityin Chains: Thepriorityvalue 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 intervalfor Sets: When creating sets intended to hold IP address ranges, useflags intervalto enable this functionality.masqueradevs.snat:masqueradeis dynamic Source NAT (SNAT) typically used on interfaces with changing IP addresses (like DHCP clients).snatis static SNAT where you specify the source IP address.