nftables 2026: Guida Completa al Firewall Linux con Esempi e Migrazione da iptables

iptables è ufficialmente in fine vita e nftables è ormai lo standard de facto per il firewall su Linux. Questa guida 2026 copre installazione, sintassi, regole, set dinamici, NAT, contatori e una procedura di migrazione testata in produzione.

nftables Firewall Linux: Guida 2026

Nel 2026 nftables non è più un'alternativa sperimentale a iptables: è il framework firewall predefinito in tutte le principali distribuzioni Linux (Debian 12, Ubuntu 24.04 LTS, RHEL 9/10, Fedora 41, openSUSE Leap 15.6) ed è l'unica strada raccomandata da netfilter.org per chi avvia oggi un nuovo progetto di networking. Eppure, una percentuale sorprendentemente alta di server in produzione gira ancora regole iptables-legacy, spesso "tradotte" malamente da iptables-nft, con regressioni di performance e bug che sono davvero una rogna da diagnosticare.

Onestamente, dopo anni passati a scrivere regole iptables, il passaggio a nftables ti cambia la vita. Questa guida copre tutto ciò che serve per padroneggiarlo nel 2026: dall'installazione alla sintassi, dalle regole base ai set dinamici, dal NAT alla migrazione progressiva da iptables, fino agli esempi reali per i workload più comuni (web server, bastion SSH, host container con Docker e Podman). Ogni snippet è stato testato su Debian 12 e RHEL 9 con kernel 6.6+ e nft v1.1.x.

Perché nftables ha sostituito iptables (e cosa cambia davvero)

nftables esiste dal kernel 3.13 (2014), ma è solo nell'ultimo biennio che il consenso si è cristallizzato. Tre ragioni molto concrete spiegano la transizione:

  • Una sola utility per tutte le famiglie di protocollo. Dove prima servivano iptables, ip6tables, arptables ed ebtables, oggi basta nft con la famiglia inet, arp o bridge. Meno tool da ricordare, meno errori di sintassi incrociata.
  • Performance nettamente superiori su set di regole grandi. Le strutture dati di nftables (set, map, verdict map) permettono lookup in O(log n) o O(1), contro la valutazione lineare di iptables. Su un firewall con 50.000 IP bloccati la differenza è di ordini di grandezza — l'ho misurata personalmente e non c'è storia.
  • Aggiornamenti atomici. Il comando nft -f applica un intero set di regole in un'unica transazione: se una riga è invalida, nessuna modifica viene applicata. Con iptables si rischiavano stati intermedi pericolosi (il classico firewall "vuoto" durante il reload, con tutti i servizi improvvisamente esposti). Brutto ricordo.

Anche il progetto netfilter ha ormai ufficializzato la fine vita di iptables-legacy: dal kernel 6.10 (giugno 2025) i moduli x_tables non ricevono più feature, solo bugfix critici. Nuove funzionalità come il connection tracking ottimizzato, il flowtable offload hardware e l'integrazione nativa con nftables-eBPF sono esclusive di nftables. In pratica, restare su iptables oggi significa rinunciare volontariamente a metà del motore.

Installazione e verifica del backend attivo

Sulle distribuzioni recenti, nftables è già installato. Verifica veloce con:

nft --version
# nftables v1.1.5 (Commodore Bullmoose)

systemctl status nftables.service

Se manca (raro, ma può capitare su immagini minimali), installalo e abilita il servizio:

# Debian / Ubuntu
sudo apt update && sudo apt install nftables
sudo systemctl enable --now nftables

# RHEL / Rocky / AlmaLinux
sudo dnf install nftables
sudo systemctl enable --now nftables

# Arch
sudo pacman -S nftables
sudo systemctl enable --now nftables

A questo punto conviene verificare quale backend è effettivamente in uso — passaggio cruciale se stai migrando da una configurazione preesistente:

sudo update-alternatives --display iptables
# /usr/sbin/iptables - status is auto.
# link currently points to /usr/sbin/iptables-nft

# oppure
sudo iptables -V
# iptables v1.8.10 (nf_tables)

Se vedi (nf_tables) nell'output, il sistema sta già usando il backend nftables tramite il wrapper di compatibilità. Questo è il punto di partenza ideale per una migrazione "soft", senza strappi.

Anatomia di una configurazione nftables

nftables ha una gerarchia chiara e prevedibile: tabelle → catene → regole. Una tabella appartiene a una famiglia (ip, ip6, inet, arp, bridge, netdev) e contiene catene; ogni catena è agganciata a un hook netfilter (input, output, forward, prerouting, postrouting) con una priority e una policy di default.

Ecco un esempio minimale di una configurazione "deny all, allow needed" per un server stand-alone — il tipo di base che uso come punto di partenza in quasi tutti i progetti:

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        # Loopback e connessioni stabilite
        iif "lo" accept
        ct state established,related accept
        ct state invalid drop

        # ICMP utile (no flood)
        ip protocol icmp icmp type { echo-request, destination-unreachable, time-exceeded } limit rate 5/second accept
        ip6 nexthdr icmpv6 icmpv6 type { echo-request, destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept

        # SSH solo da rete admin
        ip saddr 10.0.0.0/24 tcp dport 22 accept

        # Web pubblico
        tcp dport { 80, 443 } accept

        # Logging dei drop (limitato)
        limit rate 3/minute log prefix "nft-drop: " level info
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Salva il file in /etc/nftables.conf e applicalo:

sudo nft -c -f /etc/nftables.conf   # check syntax
sudo systemctl reload nftables

L'opzione -c (check) è la tua rete di sicurezza: convalida la sintassi senza applicare nulla. Usala sempre prima di un reload remoto, specialmente via SSH. Una regola persa in produzione può chiuderti fuori dal server in meno tempo di quanto tu impieghi a dire "oops".

Sintassi essenziale: matcher, statement, verdict

Una regola nftables, nella sua forma generale, è così:

<matcher> <matcher> ... <statement> <verdict>

I matcher filtrano il pacchetto (tcp dport 443, ip saddr 10.0.0.0/8, ct state new); gli statement compiono azioni intermedie (log, counter, limit, meta mark set); il verdict decide il destino finale (accept, drop, reject, jump, queue). Semplice da leggere una volta interiorizzato.

Ecco alcuni matcher utili che in iptables proprio non c'erano:

MatcherEsempioA cosa serve
meta l4protometa l4proto { tcp, udp } th dport 53Match su TCP+UDP in una sola regola
tcp flagstcp flags & (fin|syn|rst|ack) == synSolo SYN iniziali (anti scan)
ct countct count over 20 rejectLimite connessioni concorrenti per IP
numgennumgen inc mod 3Load balancing puro su L3/L4
jhashjhash ip saddr mod 16Sharding deterministico

Set, map e verdict map: il vero superpotere

Il principale collo di bottiglia di iptables è sempre stato la valutazione lineare delle regole. nftables introduce invece strutture dati native: set (insiemi), map (chiave→valore) e verdict map (chiave→azione). Possono essere statici o dynamic, cioè modificabili a runtime senza alcun reload. Ed è qui che la magia succede.

Set statici

table inet filter {
    set ssh_admins {
        type ipv4_addr
        elements = { 10.0.0.5, 10.0.0.6, 192.168.50.10 }
    }

    chain input {
        type filter hook input priority 0; policy drop;
        ct state established,related accept
        tcp dport 22 ip saddr @ssh_admins accept
    }
}

Set dinamici per blocklist anti-bruteforce

Questo pattern, onestamente, sostituisce in modo elegante fail2ban per scenari semplici — senza processo in user-space da monitorare:

table inet filter {
    set blackhole {
        type ipv4_addr
        flags dynamic, timeout
        timeout 1h
        size 65536
    }

    chain input {
        type filter hook input priority 0; policy drop;
        ct state established,related accept

        # Drop immediato se già in blocklist
        ip saddr @blackhole drop

        # Aggiungi alla blocklist se supera 5 tentativi SSH in 1 minuto
        tcp dport 22 ct state new \
            meter ssh_meter { ip saddr timeout 1m limit rate over 5/minute } \
            add @blackhole { ip saddr } \
            log prefix "ssh-bruteforce: " drop

        tcp dport 22 accept
    }
}

Puoi ispezionare e manipolare il set direttamente a runtime, senza ricaricare nulla:

sudo nft list set inet filter blackhole
sudo nft add element inet filter blackhole { 1.2.3.4 timeout 24h }
sudo nft delete element inet filter blackhole { 1.2.3.4 }

Verdict map per dispatching

chain input {
    type filter hook input priority 0; policy drop;
    ct state established,related accept

    tcp dport vmap {
        22  : jump ssh_chain,
        80  : accept,
        443 : accept,
        25  : drop
    }
}

Le vmap sono O(log n): che tu abbia 5 o 5000 porte, il lookup ha sempre lo stesso costo. È una differenza sottile su piccola scala, brutale su scala seria.

NAT con nftables: SNAT, DNAT e masquerade

Il NAT richiede una tabella separata (per convenzione nat) con catene agganciate agli hook prerouting e postrouting:

table ip nat {
    chain prerouting {
        type nat hook prerouting priority dstnat;

        # Port forwarding: 80 esterno -> 8080 interno
        iif "eth0" tcp dport 80 dnat to 192.168.1.10:8080
    }

    chain postrouting {
        type nat hook postrouting priority srcnat;

        # Masquerade per la LAN che esce su eth0
        oif "eth0" ip saddr 192.168.1.0/24 masquerade
    }
}

Per scenari ad alte prestazioni (router, gateway con >1 Gbit/s), vale la pena abilitare anche un flowtable per offloadare il fast-path al kernel o addirittura all'hardware:

table inet filter {
    flowtable ft {
        hook ingress priority 0;
        devices = { eth0, eth1 };
        flags offload;   # solo se la NIC supporta hw offload
    }

    chain forward {
        type filter hook forward priority 0; policy accept;
        ip protocol { tcp, udp } flow add @ft
        ct state established,related accept
    }
}

Migrazione pratica da iptables (senza downtime)

La via più sicura è una migrazione in 4 passi. Funziona anche su server in produzione, a patto di non bruciare le tappe.

1. Esporta le regole esistenti

sudo iptables-save > /root/iptables.bkp
sudo ip6tables-save > /root/ip6tables.bkp

2. Traduci automaticamente

iptables-restore-translate -f /root/iptables.bkp > /root/nftables-from-ipt.nft
ip6tables-restore-translate -f /root/ip6tables.bkp >> /root/nftables-from-ipt.nft

Importante: il file generato è solo un punto di partenza, non un risultato finale. Va riletto e refattorizzato a mano per:

  • Unificare IPv4 e IPv6 nella famiglia inet.
  • Sostituire blocchi ripetitivi con set e vmap.
  • Usare ct state al posto di --state.
  • Rimuovere catene custom ormai superflue.

3. Applica in dry-run

sudo nft -c -f /root/nftables-from-ipt.nft

4. Switch atomico

Sempre (e sottolineo sempre) da una sessione SSH secondaria, con un timer di rollback attivo:

# Rete di sicurezza: ripristina iptables fra 5 minuti se l'SSH cade
sudo bash -c "sleep 300 && iptables-restore < /root/iptables.bkp" &
ROLLBACK_PID=$!

# Spegni iptables, accendi nftables
sudo systemctl stop iptables 2>/dev/null
sudo iptables -F && sudo iptables -X
sudo cp /root/nftables-from-ipt.nft /etc/nftables.conf
sudo systemctl restart nftables

# Se la nuova SSH funziona, annulla il rollback
kill $ROLLBACK_PID

Questo trucco mi ha salvato le chiappe più di una volta. Non saltarlo, anche se sembra paranoia.

Esempio reale: hardening di un host Docker

Docker manipola pesantemente le tabelle nat e filter della famiglia ip. Per non collidere, conviene definire le proprie regole nella famiglia inet con priorità inferiore (cioè più precoce) rispetto alle catene di Docker.

table inet hardening {
    set trusted_admin {
        type ipv4_addr
        elements = { 10.0.0.0/24, 192.168.50.0/24 }
    }

    chain prerouting_block {
        type filter hook prerouting priority -300;

        # Anti-spoofing
        iif "eth0" ip saddr { 127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16 } drop

        # Drop di pacchetti malformati
        ct state invalid drop
        tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 drop
        tcp flags & (syn|fin) == (syn|fin) drop
    }

    chain input_filter {
        type filter hook input priority -100; policy accept;

        ct state established,related accept
        iif "lo" accept

        tcp dport 22 ip saddr @trusted_admin accept
        tcp dport 22 drop

        # Lascia passare il traffico verso le porte pubblicate da Docker
        # (Docker gestisce le sue catene a priority 0)
    }
}

Logging, contatori e troubleshooting

nftables integra counter e log come statement nativi, eliminando la necessità di moduli esterni:

chain input {
    type filter hook input priority 0; policy drop;

    tcp dport 443 counter accept comment "https-traffic"
}

Visualizza i contatori in tempo reale:

sudo nft list ruleset -a
sudo nft monitor trace        # tracing pacchetto-per-pacchetto
sudo nft list counters

Per il logging strutturato verso journald + un SIEM (Wazuh, Splunk, Elastic):

tcp dport 22 ct state new log prefix "[NFT-SSH-NEW] " group 0 level warn accept

I log finiscono in journalctl -k e possono essere raccolti via auditd o rsyslog con un parser dedicato. Il nft monitor trace, in particolare, è una gemma quando devi capire perché diavolo un pacchetto non arriva dove dovrebbe.

Best practice di sicurezza per il 2026

  1. Default deny in input e forward. Mai policy accept sugli hook che ricevono traffico.
  2. Famiglia inet ovunque possibile: una regola, due protocolli (IPv4 e IPv6). Meno duplicazione, meno errori.
  3. Limita ICMP e ICMPv6 con limit rate ma non bloccarli del tutto: icmpv6 è essenziale per Path MTU Discovery e Neighbor Discovery (tanti ci sono caduti, chiedi in giro).
  4. Usa set dynamic con timeout al posto di catene "blocklist" statiche aggiornate da cron.
  5. Versiona /etc/nftables.conf con git e applica le modifiche via Ansible/Salt con nft -c obbligatorio in fase di lint.
  6. Non eseguire nft flush ruleset in produzione senza un timer di rollback attivo. Mai.
  7. Disabilita IPv6 forwarding se non lo usi: sysctl -w net.ipv6.conf.all.forwarding=0.
  8. Integra con eBPF per visibilità: tool come Tetragon o bpftrace permettono di vedere quali processi triggerano quali regole nftables.

Domande frequenti su nftables

Posso usare iptables e nftables contemporaneamente?

Tecnicamente sì, ma è fortemente sconsigliato. I due framework lavorano su priority differenti dello stesso hook netfilter e l'ordine di valutazione può riservarti sorprese spiacevoli. In più, qualsiasi reload di iptables tramite il wrapper iptables-nft sovrascrive parti del ruleset nftables. Regola d'oro: scegli un framework e mantienilo.

nftables è più lento di iptables su regole semplici?

No. Su set di regole piccoli (< 50 regole) le performance sono praticamente indistinguibili. Su set medio-grandi nftables vince nettamente grazie a set, map e vmap. Il vero collo di bottiglia, oggi, è raramente il firewall: è il conntrack sotto carico DDoS, e anche lì nftables offre flowtable per offloadare il fast-path.

Come posso fare backup e ripristino delle regole nftables?

Usa nft list ruleset > backup.nft per esportare lo stato corrente e nft -f backup.nft per ripristinarlo. Per un ripristino atomico dell'intero ruleset, anteponi flush ruleset al file di backup. Su systemd basta systemctl reload nftables per riapplicare /etc/nftables.conf.

nftables supporta il logging in formato JSON?

Sì, dalla versione 0.9.4. Esegui nft -j list ruleset per ottenere l'intero ruleset in JSON — ideale per pipeline di osservabilità. Anche nft monitor supporta --json, il che lo rende perfetto per integrazioni con Vector, Fluent Bit o Logstash.

Devo migrare anche se uso UFW o firewalld?

Probabilmente no, almeno non subito. Sia UFW (Ubuntu) sia firewalld (RHEL/Fedora) usano già nftables come backend di default dal 2022. La migrazione esplicita ha senso solo se vuoi superare le astrazioni dei frontend e sfruttare feature avanzate come flowtable, vmap dinamici o regole eBPF.

Conclusioni

nftables nel 2026 è la base imprescindibile di qualsiasi strategia seria di hardening Linux: più espressivo, più performante e con un modello transazionale che riduce drasticamente il rischio di errori operativi. Investire qualche ora in una migrazione pulita ripaga in stabilità, leggibilità delle regole e capacità di automatizzare con Ansible o GitOps. Il passo successivo, quello logico, è integrare nftables con un SIEM come Wazuh per chiudere il cerchio su detection e response.

Sull'Autore Editorial Team

Our team of expert writers and editors.