← News
/PLAYBOOK · 2026-08-16

nftables Firewall Configuration in Practice: Modern Linux Firewall Rules Guide

nftables is the modern successor to iptables: cleaner syntax, higher performance. Starts from table/chain/rule basics and delivers a complete ruleset for web-server allow/deny, scan defense, and persistence.

Scope

Sysadmins and operators configuring nftables on Linux servers. RHEL/CentOS 8+, Debian 11+, Ubuntu 22.04+ default to or recommend nftables as the kernel firewall framework; classic iptables is in maintenance mode. This guide targets common workloads such as web and database servers and delivers a complete ruleset from zero to usable.

Prerequisites

Internals

nftables is built on the kernel nf_tables framework. Rules use a three-level structure: table, chain, rule. One command can manage batches; syntax is cleaner than iptables. Chains attach at protocol-stack positions: prerouting (pre-route), input/output (local ingress/egress), forward (forwarding). Dual-stack IPv4/IPv6 is supported. Rules can carry counters for troubleshooting. With `limit` and `ct state` you get scan defense and connection tracking, replacing the iptables state module.

Procedure

1. Create table and base chains

# Create table (family inet covers IPv4 and IPv6)
nft add table inet filter

# Create base chains: default policy drop; create chains first to avoid lockout
nft add chain inet filter input  { type filter hook input  priority 0; policy accept; }
nft add chain inet filter output { type filter hook output priority 0; policy accept; }
nft add chain inet filter forward { type filter hook forward priority 0; policy drop; }

Key point: set default policy to accept first. Switch to drop only after all rules are in place and verified, to avoid losing access mid-change.

2. Allow loopback and established connections

nft add rule inet filter input iif lo accept
nft add rule inet filter input ct state established,related accept

3. Allow common service ports

nft add rule inet filter input tcp dport 22 accept   # SSH
nft add rule inet filter input tcp dport 80 accept   # HTTP
nft add rule inet filter input tcp dport 443 accept  # HTTPS
nft add rule inet filter input icmp type echo-request limit rate 5/second accept

4. Rate-limit to block port scans

# Limit new-connection rate per IP
nft add rule inet filter input ct state new tcp dport 22 limit rate 5/minute accept
nft add rule inet filter input ct state new tcp dport 80 limit rate 100/minute accept

# Max 20 SYN per IP per minute (anti-scan)
nft add rule inet filter input tcp flags syn tcp dport 1-65535   ct state new limit rate 20/minute burst 40 drop

5. Tighten default policy and persist

# After all rules are ready, set input default policy to drop
nft chain inet filter input { policy drop; }

# List the full current ruleset
nft list ruleset

# Persist: write config file (Debian/Ubuntu)
nft list ruleset > /etc/nftables.conf
systemctl enable nftables --now

# RHEL family: write rules to /etc/sysconfig/nftables.conf, then enable the service the same way

6. Use a scripted config for maintenance

# /etc/nftables.conf example (Debian style)
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        iif lo accept
        ct state established,related accept
        tcp dport 22 accept
        tcp dport 80 accept
        tcp dport 443 accept
        icmp type echo-request limit rate 5/second accept
    }
    chain output {
        type filter hook output priority 0; policy accept;
    }
    chain forward {
        type filter hook forward priority 0; policy drop;
    }
}

After edits, run `nft -f /etc/nftables.conf` for an atomic load. A syntax error rolls back the whole set; you never leave a half-applied ruleset.

Verification

# 1. List rules and counters (hit counts are obvious)
nft list ruleset

# 2. Locally allowed ports are reachable
curl -sI http://127.0.0.1/ | head -3

# 3. From an external host, blocked ports should not respond
nc -zv <SERVER_IP> 3306

# 4. Syntax-check config (does not apply)
nft -c -f /etc/nftables.conf

# 5. Rules load automatically after restart
systemctl restart nftables && nft list ruleset | head -5

FAQ

Q1: Rules vanish after reboot even though they were saved?

Most likely nftables is not enabled at boot, or the config path is wrong. On Debian, run `systemctl enable nftables` and confirm rules are in `/etc/nftables.conf`. On RHEL, write `/etc/sysconfig/nftables.conf`. Check service state with `systemctl status nftables`.

Q2: nft reports "Operation not permitted"?

The current user lacks CAP_NET_ADMIN. Run as root or via sudo. In a container, confirm NET_ADMIN is not dropped. Cloud security groups are independent of the OS firewall; also check the console security-group allow list.

Summary

nftables firewall configuration is a required Linux ops skill. Once you own the table–chain–rule model plus `limit` and `ct state`, you can write a ruleset that is both safe and maintainable. Core method: allow first while building chains, then rate-limit, then tighten default policy. Load atomically with `nft -f` and enable the unit so rules survive reboot.