nftables Firewall Rules for Production Linux Servers
Security

nftables Firewall Rules for Production Linux Servers

  • Author :Liam K.
  • Date :July 02, 2026
  • Time :26 minutes

nftables is the modern Linux firewall framework that replaces iptables, ip6tables, and arptables with a single unified syntax. Debian 12 and Ubuntu 22.04+ use nftables as the default backend even when you run UFW. Understanding nftables directly gives you finer control over rate limiting, set-based blocking, and logging — capabilities that higher-level tools expose only partially.

This guide builds a production baseline: default-deny inbound, allow established connections, permit SSH/HTTP/HTTPS, rate-limit SSH against brute force, log dropped packets for analysis, and persist rules across reboots. The rules work on bare metal, VPS, and cloud instances alike.

nftables vs UFW vs iptables

  • UFW — user-friendly wrapper, good for simple allow/deny rules. Uses nftables under the hood on modern Debian/Ubuntu.
  • iptables — legacy syntax, still functional but deprecated for new deployments.
  • nftables — native framework, atomic rule updates, sets/maps, built-in rate limiting.

Use UFW for quick setups on single-service servers. Use nftables directly when you need rate limiting, complex sets, or cross-table logic that UFW cannot express cleanly.

Step 1: Install and Verify nftables

bash
sudo apt update
sudo apt install -y nftables
sudo systemctl enable nftables

# Flush legacy iptables rules if migrating:
sudo iptables -F 2>/dev/null || true
sudo ip6tables -F 2>/dev/null || true

nft --version

Step 2: Production Ruleset

Write the complete ruleset to /etc/nftables.conf. The policy is default drop on input — only explicitly allowed traffic passes.

bash
sudo tee /etc/nftables.conf >/dev/null <<'EOF'
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
    sets {
        allowed_tcp_ports {
            type inet_service
            elements = { 22, 80, 443 }
[...]
Command truncated. Copy to view full command.

Step 3: Apply and Verify

bash
# IMPORTANT: keep an active SSH session open while testing!
sudo nft -c -f /etc/nftables.conf
sudo systemctl restart nftables
sudo nft list ruleset

# Verify from another terminal:
ssh user@your-server
curl -I http://your-server

Step 4: Restrict SSH to Management Network

If you use Tailscale or a VPN for admin access, restrict SSH to that interface only and remove port 22 from the public allowed set.

bash
# Add before the SSH rate limit rule:
# iifname "tailscale0" tcp dport 22 accept
# Remove 22 from allowed_tcp_ports set for public interface

Step 5: Block Known Bad IPs with Sets

bash
# Add a blocklist set:
# set blocklist {
#     type ipv4_addr
#     flags interval
#     elements = { 192.0.2.0/24, 198.51.100.50 }
# }
# ip saddr @blocklist drop

# Populate dynamically from CrowdSec bouncer or threat feeds

Step 6: Monitor Dropped Packets

bash
sudo journalctl -k | grep "nftables-drop"
sudo dmesg | grep "nftables-drop" | tail -20

# Count drops per hour for dashboard:
sudo journalctl -k --since "1 hour ago" | grep -c "nftables-drop"

Step 7: Runtime Rule Changes (Without Reboot)

bash
# Add a port temporarily:
sudo nft add element inet filter allowed_tcp_ports { 8080 }

# Remove it:
sudo nft delete element inet filter allowed_tcp_ports { 8080 }

# Runtime changes are lost on restart — always update /etc/nftables.conf too

Common Mistakes

  • Applying rules without nft -c check — syntax errors can lock you out.
  • Forgetting established/related rule — breaks active SSH sessions on reload.
  • Not testing from a second session before closing your current SSH connection.
  • Running UFW and nftables simultaneously with conflicting rules.
  • Logging every dropped packet without rate limiting — fills disk with kernel logs.

Production Checklist

  • Default deny inbound — allow only required ports explicitly.
  • Rate-limit SSH and any admin-facing port.
  • Version-control /etc/nftables.conf in your infrastructure repo.
  • Test rule changes with nft -c before applying.
  • Integrate with CrowdSec or similar for dynamic IP blocking.

"A firewall rule you have not tested is a lockout waiting to happen — always validate from a second session before you close the first."

Technical Author

Technical Author - Liam K.
Liam K.

System administrator and technical writer specializing in server infrastructure, security and deployment. Creating comprehensive guides to help you master server administration.