IBMDO YOU?Hi, I'm MBO!

Settings

Make the site feel at home on your screen.

Theme

Loading your theme preference.

Keyboard shortcuts

Open search from anywhere, then move through the results without leaving the keyboard.

Open settings
Ctrl,or⌘,
Open search
CtrlKor⌘K
Select a search result
↑↓
Open the selected result
Enter
Close an open dialog
Esc

Linux

Set up a basic nftables firewall

Install nftables, build a persistent dual-stack server ruleset, validate it safely and manage temporary firewall rules.

nftables is the current Linux interface for configuring the Netfilter packet-filtering framework. A ruleset is organised into tables, chains and rules, and can handle IPv4 and IPv6 traffic in one inet table.

This example builds a small stateful firewall for a server. It drops unsolicited inbound and forwarded traffic, permits established connections, keeps essential ICMP working and allows selected services. Outbound traffic remains accepted unless the server has a documented reason to restrict it.

A default-drop firewall can disconnect you from a remote server. Keep an existing administrative session open, arrange console access and include the correct SSH rule before loading the configuration. Test on a non-production system first.

Install nftables

On Arch Linux, install nftables through pacman without performing a partial repository refresh:

sudo pacman -Syu nftables

On Debian or Ubuntu:

sudo apt update
sudo apt install nftables

Check the installed version:

sudo nft --version

Understand the persistent configuration

The packaged systemd service normally loads /etc/nftables.conf. Confirm the actual command on the server rather than copying a service definition from another distribution:

systemctl cat nftables.service

Enable the service only after creating and validating the ruleset:

sudo systemctl enable nftables.service

Create the ruleset

Back up the existing configuration before replacing it:

sudo cp --archive /etc/nftables.conf /etc/nftables.conf.backup

Create /etc/nftables.conf with the following baseline:

#!/usr/sbin/nft -f
 
flush ruleset
 
table inet firewall {
  chain input {
    type filter hook input priority filter; policy drop;
 
    # Reject packets that do not belong to a valid connection.
    ct state invalid drop
 
    # Allow replies to connections initiated by this host.
    ct state { established, related } accept
 
    # Allow local processes to communicate over the loopback interface.
    iifname "lo" accept
 
    # Keep IPv4 diagnostics and IPv6 neighbour discovery working.
    meta l4proto { icmp, ipv6-icmp } accept
 
    # Allow services hosted by this server. Remove any that are not needed.
    tcp dport { 22, 80, 443 } accept
 
    # Log a limited sample before dropping everything else.
    limit rate 5/second burst 10 packets counter log prefix "nft input drop: " drop
  }
 
  chain forward {
    type filter hook forward priority filter; policy drop;
 
    # This host is not acting as a router.
    limit rate 5/second burst 10 packets counter log prefix "nft forward drop: " drop
  }
 
  chain output {
    type filter hook output priority filter; policy accept;
  }
}

The three base chains attach to different points in the network stack:

  • input handles traffic addressed to this server.
  • forward handles traffic being routed through this server.
  • output handles traffic created by this server.

The input chain uses a default drop policy, so a packet must match an accept rule to reach a local service. The connection-tracking rule permits replies for existing connections without opening those service ports to new inbound connections.

The inet family evaluates both IPv4 and IPv6 traffic. Do not silently ignore IPv6 when the host has it enabled: IPv6 neighbour discovery depends on ICMPv6, and blocking it broadly can break connectivity.

Change the service-port rule to match the server. For example, a database server that should accept SSH only from an administrative network could replace it with:

ip saddr 192.0.2.0/24 tcp dport 22 accept

192.0.2.0/24 is a documentation network. Replace it with the real trusted source range before applying the rule.

Validate before loading

Ask nftables to parse and check the file without applying it:

sudo nft --check --file /etc/nftables.conf

A successful check produces no output. It confirms the syntax, but it cannot confirm that the rules allow the traffic your server needs.

Load the complete ruleset:

sudo nft --file /etc/nftables.conf

From a second machine, immediately test every required administrative and application connection. Keep the original session open until those checks pass. If access fails and you still have a console, restore the previous file and reload it:

sudo cp --archive /etc/nftables.conf.backup /etc/nftables.conf
sudo nft --file /etc/nftables.conf

Once the rules are confirmed, start the service and check its status:

sudo systemctl restart nftables.service
sudo systemctl status nftables.service

Inspect and clear the active ruleset

Display the rules currently loaded in the kernel:

sudo nft list ruleset

Include rule handles when diagnosing or preparing to delete an individual rule:

sudo nft --handle list ruleset

To remove every active nftables rule:

sudo nft flush ruleset

Flushing the ruleset leaves the host without this firewall protection. Use it only as a controlled recovery or maintenance action, and remember that restarting the service loads the persistent file again.

Add a temporary rule

Rules entered at the command line change the active kernel ruleset but do not update /etc/nftables.conf. For example, this inserts temporary access to TCP port 8443 from one source address before the final drop rule:

sudo nft insert rule inet firewall input ip saddr 192.0.2.10 tcp dport 8443 accept

List the chain with handles:

sudo nft --handle list chain inet firewall input

Remove the rule using the handle shown in that output:

sudo nft delete rule inet firewall input handle 12

Replace 12 with the actual handle. Reloading /etc/nftables.conf also removes ad hoc rules because this configuration begins with flush ruleset.

Restrict outbound traffic only with a complete plan

A default-drop output chain must allow every dependency the host needs, including DNS, time synchronisation, package mirrors, identity services, monitoring, backups and application endpoints. It must also account for both IPv4 and IPv6.

Start by observing actual traffic and documenting approved destinations. Where possible, restrict rules to the real destination addresses rather than allowing a service port to every address. Apply the same validation, console-access and rollback process used for the input chain.

The nftables project provides a quick reference, a simple server ruleset and guidance on loading native ruleset files atomically.

Find the fix

Search articles

Esc

Search titles, technical terms or error codes.