nftables is a modern packet filtering framework for Linux that replaces iptables. It offers a unified and efficient way to manage firewall rules across multiple protocols like IPv4, IPv6, and ARP, with better performance and a simpler configuration through a single interface instead of multiple tables. This guide installs and configures nftables on Linux, sets up basic firewall rules, manages network traffic, and implements common security policies. By the end, you'll have a persistent nftables firewall with SSH, HTTP, and HTTPS access rules, NAT/port forwarding, and logging in place.
Prerequisites
Before you begin, you need to:
- Have access to a Linux-based instance as a non-root sudo user.
- Have a basic understanding of network protocols and firewall rule management.
nftables versus iptables
iptables is the traditional firewall management tool on Linux, but its limitations include a complex rule structure, performance inefficiencies, and the need for separate tools to handle different protocols (IPv4, IPv6, ARP, and so on). nftables was introduced as a replacement, offering improvements in functionality, performance, and usability:
| Feature | iptables |
nftables |
|---|---|---|
| Packet Filtering | Requires multiple tools to manage different protocols (iptables, ip6tables, arptables) | Uses a unified approach with named tables and chains |
| Rule Syntax | Forces users to write complex chain-based rules with multiple entries | Offers a modern, table-based syntax that simplifies rule writing |
| Performance | Processes rules sequentially, which can slow down large rule sets | Uses optimized rule evaluation, reducing overhead |
| Atomic Rule Changes | Requires flushing and reloading entire rule sets for modifications | Supports atomic rule updates, preventing disruption |
| Logging | Uses legacy logging targets (LOG and ULOG frameworks) | Provides built-in logging with advanced tracing options (meta nftrace, log) |
| Connection Tracking | Requires external conntrack modules |
Integrates connection tracking directly into the system |
| Multi-protocol Support | Requires different commands for each protocol | Manages all protocols with a single command set |
| Resource Usage | Consumes more memory by duplicating rules | Manages memory efficiently with a unified ruleset |
| Scripting & Automation | Relies on shell scripting and manual rule management | Supports JSON-based rule definition and direct scripting integration |
| Compatibility | Runs on all distributions but follows a legacy architecture | Works natively on modern systems while supporting iptables conversion |
Install nftables on Linux
Install nftables using the package manager for your Linux distribution.
On Ubuntu and Debian
1. Update the server's package index:
$ sudo apt update
2. Install nftables using the APT package manager:
$ sudo apt install nftables -y
On Rocky Linux and AlmaLinux
1. Update the DNF package index:
$ sudo dnf update
2. Install nftables:
$ sudo dnf install -y nftables
On Arch Linux
1. Install nftables using Pacman:
$ sudo pacman -S nftables
nft Command Syntax
nft [ -nNscaeSupyjtT ] [ -I directory ] [ -f filename | -i | cmd ... ]
-
-n: Show rule numbers in output. -
-N: Print more detailed output for rules. -
-s: Show statistics for rules. -
-c: Show chain name for each rule. -
-a: Print the rule with its address family and protocol. -
-e: Expand rule details. -
-S: Print the ruleset (configuration). -
-u: Enable update mode for dynamic changes. -
-p: Print the current ruleset in a parsable format. -
-y: Show detailed object types. -
-j: Output in JSON format. -
-t: Show output in table format. -
-T: Show tokenized output. -
-I directory: Use the specified directory for configuration files. -
-f filename: Load rules from a file. -
-i: Interactive mode to modify rules directly. -
cmd ...: Command arguments to manipulate the nftables rules.
Manage the nftables System Service
The nftables service manages your firewall rules and ensures persistence across system reboots.
1. Enable the nftables service to start at boot:
$ sudo systemctl enable nftables
2. Start the nftables service:
$ sudo systemctl start nftables
3. Verify the service status:
$ sudo systemctl status nftables
Your output should be similar to the one below:
● nftables.service - Netfilter Tables
Loaded: loaded (/usr/lib/systemd/system/nftables.service; enabled; preset: disabled)
Active: active (exited) since Mon 2025-03-31 17:52:35 UTC; 5s ago
Docs: man:nft(8)
Process: 1838 ExecStart=/sbin/nft -f /etc/sysconfig/nftables.conf (code=exited, status=0/SUCCESS)
Main PID: 1838 (code=exited, status=0/SUCCESS)
CPU: 11ms
Mar 31 17:52:35 nftables-03 systemd[1]: Starting Netfilter Tables...
Mar 31 17:52:35 nftables-03 systemd[1]: Finished Netfilter Tables.
Tables, Chains, and Policies in nftables
In nftables, rules are organized into tables, which contain chains that define how traffic is processed. Each chain is associated with a hook (input, output, forward) that determines when it is evaluated, and chains have policies that define the default action when no explicit rule matches a packet.
nftables supports multiple address families for handling different network protocols:
-
inet: Unified handling for both IPv4 and IPv6. -
ip: IPv4-only filtering. -
ip6: IPv6-only filtering. -
arp: ARP packet filtering. -
bridge: Ethernet bridge packet filtering. -
netdev: Packet filtering at the network device level.
Each chain is linked to a specific traffic type: input controls packets destined for the local machine, output manages packets leaving the machine, and forward handles packets routed through the machine.
The default policy determines whether unmatched traffic is accepted, dropped, or rejected:
-
policy accept- Allows all traffic by default (useful for testing or initial configurations). -
policy drop- Discards unmatched packets (most secure, commonly used in production environments). -
policy reject- Sends a rejection notice to the source (informative but reveals the presence of the server, which might not be ideal for security).
Warning: Using
acceptas the default policy is not recommended for production environments, as it allows all traffic unless explicitly blocked.
Manage the Default nftables Configuration
1. View the list of existing nftables rules:
$ sudo nft list tables
Your output should be similar to the one below:
table ip filter
table ip6 filter
2. View the default nftables configuration file:
$ cat /etc/nftables.conf
Your output should be similar to the one below:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Configure Basic nftables Firewall Rules
Create Initial Table and Chains
1. Create a new firewall table for IPv4 and IPv6 traffic:
$ sudo nft add table inet my_table
This creates a new table named my_table that can process both IPv4 and IPv6 packets using the inet family. Replace my_table with your preferred table name; it's used throughout the rest of this guide.
2. Add an input chain with a default accept policy:
$ sudo nft add chain inet my_table input { type filter hook input priority 0 \; }
This creates a filtering chain that applies to incoming traffic. type filter designates it as a filtering chain, hook input ensures it processes incoming packets, and priority 0 determines the execution order (lower values run first).
3. Create a forward chain with a default accept policy:
$ sudo nft add chain inet my_table forward { type filter hook forward priority 0\; }
This creates a filtering chain that applies to forwarded traffic, using hook forward to process forwarded packets.
4. Allow established connections to keep existing communications:
$ sudo nft add rule inet my_table input ct state established,related accept
This rule uses connection tracking: ct state enables connection tracking, and established allows packets from existing connections.
Add, List, and Delete Rules
1. Add a rule to block incoming traffic from a specific IP address:
$ sudo nft add rule inet my_table input ip saddr 192.0.2.10 drop
This adds a rule to the my_table table's input chain, blocking incoming traffic from the IP address 192.0.2.10.
2. View all active nftables rules to verify configurations:
$ sudo nft list ruleset
3. List the rules with handle numbers:
$ sudo nft list chain inet my_table input
Your output should be similar to the one below:
table inet my_table {
chain input {
type filter hook input priority filter; policy accept;
ct state established,related accept
ip saddr 192.0.2.10 drop
}
}
4. Identify the handle number from the output and delete the corresponding rule:
$ sudo nft delete rule inet my_table input handle 0
This deletes the rule with handle number 0 from the input chain of the my_table table.
Implement Essential Security Rules
1. Allow SSH access to your server:
$ sudo nft add rule inet my_table input tcp dport 22 accept
This matches TCP packets targeting destination port 22 (the default SSH port) and accepts them.
2. Block a specific IP address that shows suspicious activity:
$ sudo nft add rule inet my_table input ip saddr 192.0.2.10 drop
This matches packets from the specified source IP address and drops them without notifying the sender.
3. Allow HTTP traffic on port 80:
$ sudo nft add rule inet my_table input tcp dport 80 accept
4. Allow HTTPS traffic on port 443:
$ sudo nft add rule inet my_table input tcp dport 443 accept
5. Drop all other incoming traffic:
$ sudo nft add rule inet my_table input ip daddr 0.0.0.0/0 counter drop
This drops all incoming traffic by default while allowing only the preconfigured rules (SSH, HTTP, HTTPS), effectively blocking unwanted access.
Enable NAT and Port Forwarding
1. Enable NAT functionality in the Linux kernel by editing /etc/sysctl.conf:
$ sudo vim /etc/sysctl.conf
2. Uncomment the following line:
...
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
....
Save and close the file.
3. Apply the changes:
$ sudo sysctl -p
4. Create a new NAT table to handle network address translation for your server:
$ sudo nft add table nat
5. Create a postrouting chain in the NAT table to process packets after routing:
$ sudo nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
6. Add a masquerading rule for your internal network to enable internet connection sharing:
$ sudo nft add rule nat postrouting ip saddr 192.0.2.0/24 oif enp1s0 masquerade
This tells nftables to perform NAT (masquerading) for outgoing traffic from the 192.0.2.0/24 network. The oif enp1s0 part specifies that the rule applies to traffic leaving the enp1s0 interface, typically the interface connected to the internet.
Save Rules Persistently Across Reboots
1. Save your current firewall configuration to the /etc/nftables.conf file:
$ sudo nft list ruleset | sudo tee /etc/nftables.conf
2. Apply saved rules from the configuration file:
$ sudo nft -f /etc/nftables.conf
3. Restart the nftables service:
$ sudo systemctl restart nftables
This reloads the firewall rules and ensures they persist after reboots.
Advanced Rule Configuration
1. Implement rate limiting for SSH connections:
$ sudo nft add rule inet my_table input tcp dport 22 limit rate 3/minute accept
This targets SSH traffic (port 22), limits connections to 3 per minute, and accepts connections within the limit to help prevent brute force attacks.
2. Create the prerouting chain in the nat table (if it doesn't exist):
$ sudo nft add chain ip nat prerouting { type nat hook prerouting priority 0 \; }
3. Add the port forwarding rule:
$ sudo nft add rule nat prerouting tcp dport 80 dnat to 192.0.2.10
This captures incoming HTTP traffic (port 80) and forwards it to an internal server (192.0.2.10), enabling you to host internal web services.
4. Enable logging for dropped packets:
$ sudo nft 'add rule inet my_table input log prefix "nftables-drop: " drop'
This logs packets before dropping them, with a custom prefix for easy filtering, and stores the logs in the system journal.
5. Flush all the nftables rules:
$ sudo nft flush ruleset
Warning: Be cautious when flushing the ruleset, as this removes all existing
nftablesrules, effectively resetting your firewall configuration.
Next Steps
- Combine
nftablessets and maps to manage large groups of IP addresses or ports more efficiently. - Script your
nftablesruleset into a version-controlled configuration file for repeatable deployments. - Pair
nftableslogging with a centralized log aggregator to monitor dropped and rejected traffic. - Explore IPv6-specific rules using the
ip6address family for dual-stack environments.
For the full guide with additional tips, visit the original article on Vultr Docs.
Top comments (0)