Skip to content

nftables: Basic Rule Set

Note

All commands were verified on Debian/Ubuntu with the nftables package and on RHEL/CentOS 8+. On older systems you may need apt install nftables or yum install nftables.

nftables replaced iptables, but documentation for a basic rule set is often scattered. Here is the reference I use when bringing up a firewall on a new host.

Creating the inet filter table

The inet family table unifies IPv4 and IPv6 under a single namespace. This is the preferred approach when both stacks are active on the host.

nft add table inet filter

If the table already exists the command returns an error. To avoid duplication when a script is re-run:

nft 'add table inet filter' 2>/dev/null || true

To wipe the current rule set before loading your own:

nft flush ruleset
Warning

flush ruleset removes all rules instantly. On a production machine run this only from the console, not over a remote session without a fallback.

Input and forward chains

Chains bind to a table and define the interception point for traffic. A basic firewall needs input (traffic destined for the host itself) and forward (traffic passing through the host).

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 \; }

Key components inside the curly braces:

ComponentValue
type filterChain type, standard for packet filtering
hook input / hook forwardInterception point in the network stack
priority 0Processing priority
policy dropDefault policy — drop unmatched packets

The syntax requires escaping semicolons inside the string or using single quotes as shown above.

Tip

If you need to allow established connections, add an output chain with policy accept or use connection tracking in your input rules.

Basic rules for input

With a chain set to policy drop, you must explicitly permit the traffic you need. A typical minimum:

# Allow loopback
nft add rule inet filter input iif lo accept

# Allow established and related connections
nft add rule inet filter input ct state established,related accept

# Allow SSH (port 22)
nft add rule inet filter input tcp dport 22 accept

# Allow ping (ICMP echo request)
nft add rule inet filter input ip protocol icmp icmp type echo-request accept
nft add rule inet filter input ip6 nexthdr icmpv6 icmpv6 type echo-request accept

Each rule appends to the end of the chain. Order matters: accept rules for loopback and established traffic should come before rules with narrower criteria.

To log dropped packets before the drop policy (optional but useful for diagnostics):

nft add rule inet filter input log prefix "nft-drop: " level warn
Note

Logging adds overhead. On high-throughput interfaces use a rate limit: limit rate 10/second.

Basic rules for forward

The forward chain is needed when the host acts as a router or NAT gateway. A minimum setup:

# Allow established connections
nft add rule inet filter forward ct state established,related accept

# Allow forwarding between specific interfaces (example)
nft add rule inet filter forward iifname "eth0" oifname "eth1" accept

If the host does not perform routing, leave forward with policy drop and no additional rules.

To enable IP forwarding at the kernel level (if not already done):

sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

Viewing and managing rules

After setup, verify the current configuration:

nft list table inet filter
nft list chain inet filter input
nft list ruleset

list ruleset outputs the full config, which you can save and reuse as a boot script.

Deleting a specific rule by handle within a chain:

nft delete rule inet filter input handle <handle-number>

The handle number appears in the output of nft list ruleset -a.

To delete an entire chain:

nft delete chain inet filter input

A chain can only be deleted when it is empty. To remove a table completely, delete all chains inside it first.

Saving rules to a file for boot-time loading:

nft list ruleset > /etc/nftables.conf

On systems with systemd, enable auto-start:

systemctl enable nftables
systemctl start nftables
Warning

If /etc/nftables.conf does not exist or is empty, the service will not load any rules. Create the file manually before enabling the service.