SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor

Installare Fail2ban su Ubuntu 24.04 per bloccare i bot SSH

Su Ubuntu 24.04 apt attiva già il filtro SSH: verifica con fail2ban-client status sshd e risolvi il caso in cui Total failed resti a 0.

Che cosa fa realmente Fail2ban

Fail2ban è un demone che legge i log. Monitora i messaggi di autenticazione SSH e, dopo alcuni tentativi non riusciti dallo stesso indirizzo entro un breve intervallo, esegue un comando del firewall che blocca temporaneamente quell’indirizzo. Questa è l’idea generale. La configurazione richiede circa trenta righe in un unico file e, su Ubuntu 24.04, l’installazione consiste in un solo comando apt che attiva la protezione prima ancora di modificare qualsiasi impostazione.

È importante chiarire che cosa sia e che cosa non sia. Fail2ban non autentica gli utenti, non cifra i dati e non impedisce un singolo tentativo di accesso mirato: blocca soltanto i tentativi ripetuti dalla stessa origine. È un filtro del rumore e un limitatore della frequenza, non una serratura. Il suo compito è impedire che le scansioni continue della porta 22 consumino CPU, banda e spazio nei log e rallentare un eventuale attaccante che deve operare un indirizzo alla volta.

Cosa non sostituisce Fail2ban

Fail2ban è il terzo livello di difesa, non il primo. Se il server accetta ancora password per SSH, una botnet distribuita su migliaia di indirizzi può continuare a tentare l'autenticazione, perché ogni indirizzo resta sotto la soglia di ban e non la supera mai. La difesa efficace è l'autenticazione con sole chiavi, che rende impossibili i tentativi basati su password indipendentemente dal numero di tentativi. Fail2ban, aggiunto all'autenticazione con sole chiavi, svolge due funzioni utili: riduce nei log il rumore generato dai tentativi di forza bruta ed espelle rapidamente gli scanner, impedendo loro di continuare a colpire la porta. Consideralo una misura di difesa in profondità. Viene dopo l'autenticazione con chiavi e dopo il firewall, mai prima.

Prerequisiti e realtà di Ubuntu 24.04

È necessario un VPS con Ubuntu 24.04, accesso root o sudo e SSH già funzionante, preferibilmente con autenticazione tramite chiave. Fail2ban utilizza poche risorse: alcune decine di megabyte di RAM e nessuna regolazione dei limiti.

Ora veniamo all’aspetto che quasi tutte le guide precedenti descrivono in modo errato. Per anni il consiglio standard è stato: "installa Fail2ban, quindi aggiungi backend = systemd, perché Ubuntu ha smesso di scrivere /var/log/auth.log". Questo vale soltanto per alcune immagini. Un server Ubuntu 24.04 standard o un’immagine cloud installa ancora rsyslog. Le regole predefinite di questo servizio scrivono auth,authpriv.* in /var/log/auth.log. Nella maggior parte dei VPS, quindi, i tentativi SSH non riusciti vengono registrati sia in quel file sia nel journal di systemd. Le immagini minimali (l’immagine cloud minimale di Ubuntu 24.04 viene fornita senza rsyslog) e la maggior parte dei container registrano SSH soltanto nel journal. In questi casi il file di testo non esiste davvero. In entrambi i casi, su Ubuntu 24.04 il pacchetto Fail2ban gestisce già questa situazione. Il pacchetto installa /etc/fail2ban/jail.d/defaults-debian.conf. È questo file, e non i valori predefiniti upstream, a determinare il comportamento effettivo del server:

[DEFAULT]
banaction = nftables
banaction_allports = nftables[type=allports]
backend = systemd

[sshd]
enabled = true

Leggi con attenzione questa configurazione, perché chiarisce due aspetti prima di qualsiasi modifica. backend = systemd indica che il jail SSH legge il journal. Non cambia quindi nulla se l’immagine scrive o meno auth.log. banaction = nftables indica che i ban vengono applicati tramite nftables, il firewall effettivamente utilizzato da Ubuntu 24.04, invece che tramite il precedente iptables. [sshd] enabled = true indica inoltre che il jail è attivo già dal primo avvio. In sintesi: su Ubuntu 24.04, un apt install fail2ban standard blocca i tentativi di forza bruta su SSH senza ulteriori configurazioni. Nella maggior parte dei casi è sufficiente verificare questo comportamento, definire la policy più adatta e assicurarsi di non bloccare il proprio accesso.

Il problema del vecchio auth.log si presenta ancora in tre situazioni, che è utile saper riconoscere: hai installato Fail2ban con pip invece che con apt, quindi defaults-debian.conf non esiste; ti trovi all’interno di un container senza privilegi e senza un journal di systemd da leggere; oppure hai seguito un tutorial precedente e hai inserito backend = auto nel tuo jail.local, sovrascrivendo la configurazione predefinita funzionante. Il primo e il terzo caso impediscono il blocco degli accessi SSH soltanto su un’immagine priva di rsyslog, come un’immagine minimale. Quando rsyslog è presente, il backend basato sui file trova /var/log/auth.log e funziona. La sezione sui casi di errore mostra esattamente l’aspetto di ciascuna situazione.

Passaggio 1: installare Fail2ban e verificare che stia già applicando i ban

sudo apt update
sudo apt install -y fail2ban

Ubuntu 24.04 distribuisce Fail2ban 1.0.2 e il pacchetto installa python3-systemd come dipendenza obbligatoria, quindi il backend del journal dispone di tutto il necessario. Il servizio viene abilitato e avviato automaticamente:

sudo systemctl status fail2ban

Devi ottenere active (running). Poi controlla il jail che sta già svolgendo il suo compito:

sudo fail2ban-client status sshd

Su un VPS pubblico raggiungibile anche solo da pochi minuti, spesso vedrai già dei tentativi falliti conteggiati e alcuni indirizzi sottoposti a ban: Internet esegue scansioni continue sulla porta 22. Questa è la prova che la configurazione predefinita funziona. Da qui in poi la perfezioni, invece di crearla da zero.

Passaggio 2: modifica jail.local, non jail.conf

Fail2ban mantiene i valori predefiniti forniti dal progetto in /etc/fail2ban/jail.conf. Non modificare questo file. Un aggiornamento del pacchetto può sostituirlo, come avverte l'intestazione del file, e le modifiche possono andare perse. Fail2ban legge i file in un ordine fisso: prima jail.conf, poi jail.d/*.conf in ordine alfabetico, quindi jail.local e infine jail.d/*.local in ordine alfabetico. In caso di valori duplicati, prevale l'ultimo. Di conseguenza, jail.local sovrascrive il valore fornito dal pacchetto in defaults-debian.conf, ma qualsiasi file *.local aggiunto in jail.d/ viene letto dopo e lo sovrascrive a sua volta. Mantieni tutte le sovrascritture in un unico punto, così puoi sapere quale valore è effettivamente attivo. Il file .local è di tua proprietà e gli aggiornamenti dei pacchetti non lo modificano. La stessa regola si applica ai filtri: un file *.local sovrascrive il file filter.d/*.conf fornito dal pacchetto.

Crea quindi un file jail.local di piccole dimensioni, che sovrascriva soltanto le poche impostazioni necessarie, e lascia intatti sia jail.conf sia il file jail.d/defaults-debian.conf fornito dal pacchetto, usandoli come riferimento.

Passaggio 3: Scrivere /etc/fail2ban/jail.local

sudo nano /etc/fail2ban/jail.local

Inserire questo contenuto e sostituire l'indirizzo nella riga ignoreip con il proprio IP pubblico:

[DEFAULT]
# Ubuntu 24.04 already sets these two in jail.d/defaults-debian.conf.
# Pinning them here documents the dependency and survives if that
# file is ever removed or changed by an upgrade.
backend   = systemd
banaction = nftables

# Ban for one hour ...
bantime  = 1h
# ... if an address fails ...
maxretry = 5
# ... 5 times within 10 minutes.
findtime = 10m

# Never ban these. PUT YOUR OWN IP HERE.
ignoreip = 127.0.0.1/8 ::1 10.0.0.24

# Longer bans for repeat offenders: 1h, 2h, 4h ... up to a week.
bantime.increment = true
bantime.maxtime   = 1w

[sshd]
enabled = true

Ogni riga ha una funzione precisa:

  • bantime, findtime e maxretry definiscono la policy. Il valore predefinito fornito, bantime, è di soli dieci minuti; un'ora è un valore minimo più adeguato. Cinque tentativi falliti dallo stesso indirizzo nell'arco di dieci minuti attivano il ban. Un utente può inserire una password errata una o due volte; cinque tentativi falliti in dieci minuti indicano uno script.
  • ignoreip è una misura di sicurezza. Inserire qui l'indirizzo pubblico da cui ci si connette, in modo che Fail2ban non possa mai bloccare l'accesso al proprio server. Una connessione domestica con IP dinamico è un motivo per preferire l'approccio tramite VPN descritto alla fine, non per omettere questa riga.
  • bantime.increment = true aumenta la durata di ogni ban successivo: un'ora, poi due, quindi quattro, fino a bantime.maxtime. Gli indirizzi che continuano a ripresentarsi vengono bloccati progressivamente più a lungo.

Individuare l'indirizzo da inserire nella whitelist dalla macchina da cui si esegue la connessione SSH, non dal server:

curl -s ifconfig.me

Qui è possibile generare un jail.local configurato per le proprie porte e policy di ban, quindi incollarlo nel file:

ToolFail2ban jail generator

Passaggio 4: riavviare e verificare che legga il journal

sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Il comando -t esegue prima un test della configurazione. Un refuso in jail.local genera quindi un errore esplicito in questa fase, invece di lasciare il servizio inattivo. Lo stato di un jail funzionante è simile al seguente:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     14
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 1
   |- Total banned:     3
   `- Banned IP list:   203.0.113.66

Il numero che dimostra che Fail2ban sta leggendo effettivamente i tentativi di accesso è Total failed. Se è maggiore di zero o aumenta quando si forza deliberatamente un accesso non riuscito da un altro computer, il journal viene letto e la configurazione è completa. Se resta uguale a 0 indipendentemente dal numero di tentativi non riusciti e si è certi di non eseguire il test dall'indirizzo indicato in ignoreip, consultare le modalità di errore riportate di seguito.

Notare che la riga Journal matches indica ancora sshd.service. In Ubuntu, l'unità SSH è in realtà ssh.service, ma il filtro fornito con il sistema cerca corrispondenze anche per _COMM=sshd. Inoltre, in OpenSSH 24.04 gli errori vengono registrati da un processo denominato sshd, quindi la corrispondenza funziona. Questo dettaglio è rilevante solo con versioni più recenti di OpenSSH (9.8 o successive), nelle quali il processo di lavoro per ogni connessione è sshd-session. Le modalità di errore includono anche questo caso.

Passaggio 5: osservare l'applicazione di un ban reale oppure forzarne uno per eseguire un test

Su qualsiasi VPS pubblico, i ban reali vengono applicati autonomamente entro pochi minuti. Per osservarne uno, monitora il log:

sudo tail -f /var/log/fail2ban.log

Un ban è simile al seguente:

2026-07-15 10:31:40,502 fail2ban.filter  [812]: INFO    [sshd] Found 203.0.113.66 - 2026-07-15 10:31:40
2026-07-15 10:31:44,118 fail2ban.actions [812]: NOTICE  [sshd] Ban 203.0.113.66

Per verificare il funzionamento end-to-end senza attendere, applica manualmente un ban a un indirizzo riservato alla documentazione, mai al tuo. 203.0.113.66 appartiene a TEST-NET-3, un blocco riservato alla documentazione. Non può quindi corrispondere a un host reale né a un indirizzo privato nella rete del provider:

sudo fail2ban-client set sshd banip 203.0.113.66

Il comando stampa 1 e l'indirizzo compare in Banned IP list all'interno di fail2ban-client status sshd. Ora verifica che il blocco esista realmente nel firewall. Su Ubuntu 24.04 viene usato nftables, non iptables:

sudo nft list table inet f2b-table

Vedrai un set denominato addr-set-sshd contenente 203.0.113.66 e una chain f2b-chain che rifiuta qualsiasi origine presente in quel set. Se fail2ban-client indica che un indirizzo è stato sottoposto a ban, ma non compare nulla in nft list, l'azione di ban non corrisponde alla configurazione del firewall. Consulta la nota su nftables/iptables nella sezione relativa alle modalità di errore.

Passaggio 6: rimuovere il ban dal proprio indirizzo e recuperare l'accesso in caso di blocco

Se hai applicato un ban a un indirizzo che non doveva essere bloccato, incluso il tuo, rimuovilo:

sudo fail2ban-client set sshd unbanip 203.0.113.66

In caso di esito positivo, restituisce 1. Per rimuovere tutti i ban da tutti i jail:

sudo fail2ban-client unban --all

Non fare affidamento su una sessione SSH già aperta: il ban di nftables rifiuta ogni pacchetto proveniente dall'indirizzo bloccato verso la porta 22, comprese le connessioni già stabilite, quindi una sessione esistente si blocca nel momento in cui viene applicato il ban. Se applichi un ban al tuo indirizzo e non disponi di una voce ignoreip, perdi l'accesso fino alla scadenza del ban. Recupera l'accesso tramite la console web del provider (VNC o seriale), che non passa da SSH, quindi attendi la scadenza di bantime oppure esegui lì il comando per rimuovere il ban.

Passaggio 7: rendere persistenti i ban e aumentarne la durata

Fail2ban conserva i ban attivi in un piccolo database SQLite in /var/lib/fail2ban/fail2ban.sqlite3, quindi restano disponibili dopo il riavvio del servizio o del server. Non vengono persi. Le righe bantime.increment aggiunte in precedenza trasformano ogni recidivo in un problema progressivamente più lungo per il suo stesso indirizzo, con una durata che raddoppia approssimativamente da un'ora fino a circa una settimana.

Per applicare anche una policy di sistema basata su «tre tentativi», Fail2ban include il jail recidive. Questo jail monitora il proprio /var/log/fail2ban.log e applica ban più lunghi a ogni indirizzo che è stato bannato ripetutamente in jail diversi. Poiché il tuo [DEFAULT] usa ora il backend systemd, imposta nuovamente questo jail sul file di log che deve leggere:

[recidive]
enabled  = true
backend  = auto
logpath  = /var/log/fail2ban.log
bantime  = 1w
findtime = 1d
maxretry = 5

backend = auto con l'esplicito logpath mantiene recidive collegato al file di testo fail2ban.log. È in quel file che compaiono effettivamente le righe Ban conteggiate. Il valore predefinito systemd impostato globalmente lo collegherebbe invece al journal, dove queste righe non compaiono.

Passo 8: abbinalo all’autenticazione SSH con sole chiavi, o meglio ancora a una VPN

Fail2ban è utile solo insieme all’autenticazione tramite chiavi. In un file di override nella directory /etc/ssh/sshd_config.d/, ad esempio /etc/ssh/sshd_config.d/00-hardening.conf, imposta:

PasswordAuthentication no
KbdInteractiveAuthentication no

Quindi esegui sudo systemctl restart ssh. Con le password disabilitate, un attacco brute force non può avere successo; Fail2ban serve quindi a ridurre il rumore nei log e a bloccare rapidamente gli scanner. Una soluzione ancora più sicura consiste nel non esporre affatto SSH a Internet: instrada SSH attraverso una VPN WireGuard self-hosted e configura il firewall in modo che la porta 22 risponda solo tramite il tunnel. Nessuno può eseguire un attacco brute force su una porta che non può raggiungere, e Fail2ban diventa una misura di contenimento, non la prima linea di difesa.

Fail2ban non serve soltanto per SSH. Qualsiasi servizio che registri nei log i tentativi di accesso falliti può avere un jail: un server di posta, un sito nginx o un gestore di password Vaultwarden self-hosted il cui accesso web non vuoi lasciare esposto al credential stuffing. Dopo aver pubblicato un’applicazione web dietro un sito nginx con un certificato Let's Encrypt, configura un filtro Fail2ban sul relativo access log, nello stesso modo in cui il jail SSH analizza il journal.

Modalità di errore, con le stringhe esatte visualizzate

"Have not found any log file for sshd jail", e Fail2ban non si avvia. Questo è il vecchio problema auth.log e, su Ubuntu 24.04, si verifica solo quando /var/log/auth.log non esiste (un'immagine priva di rsyslog, ad esempio un'immagine minimale o un container) e il journal non viene letto: un'installazione pip senza defaults-debian.conf, un container senza journal oppure un backend = auto estraneo incollato in jail.local. Su un backend basato su file senza /var/log/auth.log, il jail sshd non riesce a trovare il log e l'intero demone termina. fail2ban.log mostra:

ERROR   Failed during configuration: Have not found any log file for sshd jail

Poiché l'errore è fatale, il servizio non viene mai avviato e fail2ban-client status riporta quindi il sintomo conseguente:

ERROR  Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?

La riga "socket path" non indica che Fail2ban sia danneggiato. Indica che non è stato avviato perché un jail non riusciva a trovare il proprio log. Impostare backend = systemd in [DEFAULT], come fa già il pacchetto Ubuntu, risolve entrambi i messaggi.

Il jail è attivo, ma Total failed non cambia mai. Il demone è in esecuzione e il journal viene letto, ma i tentativi reali continuano ad accumularsi in journalctl -u ssh mentre il contatore resta a 0. Prima escludere la causa più ovvia: si sta eseguendo il test da un indirizzo elencato in ignoreip, quindi i propri tentativi falliti sono esclusi intenzionalmente. Se non è questo il problema, si sta usando una build di OpenSSH in cui il worker per connessione è sshd-session (9.8 e versioni successive), il cui _COMM nel journal è sshd-session, non sshd. La regola fornita non lo intercetta. Ampliare la corrispondenza nel blocco [sshd]:

[sshd]
enabled      = true
backend      = systemd
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd + _COMM=sshd-session

Riavviare il servizio, provocare intenzionalmente il fallimento di un login da un indirizzo non presente in ignoreip e verificare che Total failed inizi finalmente ad aumentare.

Ti sei bloccato fuori: Connection refused. Hai lasciato il tuo indirizzo fuori da ignoreip, hai provato alcuni login errati e ora:

ssh: connect to host 10.0.0.10 port 22: Connection refused

Il rifiuto, invece di un timeout silenzioso, è il comportamento previsto dal verdetto predefinito reject dell'azione nftables. Il problema riguarda il tuo accesso. Correggerlo come descritto nel passaggio 6: rimuovere il ban da una sessione proveniente da un altro indirizzo non bannato oppure dalla console del provider. Anche una sessione già aperta dall'indirizzo bannato si blocca. Aggiungere quindi il proprio indirizzo a ignoreip per evitare che accada di nuovo.

Fail2ban indica che un indirizzo è bannato, ma l'indirizzo riesce ancora a connettersi. Il contatore in status sshd aumenta, ma l'indirizzo raggiunge ancora la porta 22. Si tratta di una mancata corrispondenza tra l'azione di ban e il firewall. Su Ubuntu 24.04, quasi sempre significa che è stato sovrascritto il valore funzionante banaction = nftables con banaction = iptables-multiport, copiato da una guida precedente, su un sistema privo del livello iptables. fail2ban.log mostra:

fail2ban.actions [812]: ERROR  Failed to execute ban jail 'sshd' action 'iptables-multiport'

Eliminare la sovrascrittura e lasciare attiva l'azione nftables fornita dal pacchetto oppure, se il firewall è gestito interamente tramite ufw e si desidera che i ban siano visibili anche lì, impostare banaction = ufw in [DEFAULT]. Riavviare il servizio e verificare che la regola compaia con sudo nft list ruleset | grep f2b.

Fail2ban non si avvia dopo la modifica di jail.local. Un errore di battitura, un'intestazione estranea o un valore temporale non valido possono impedire l'avvio del servizio. Chiedere a Fail2ban di verificare la configurazione prima di eseguirla:

sudo fail2ban-client -t

Il comando indica il file e il jail che contengono il problema, ad esempio Errors in jail 'sshd'. Skipping.... In questo modo è possibile correggere la configurazione originale senza procedere per tentativi.

FAQ

Fail2ban installato da Ubuntu 24.04 blocca davvero gli attacchi SSH?

Sì. Il pacchetto include /etc/fail2ban/jail.d/defaults-debian.conf, che abilita il jail sshd, imposta backend = systemd in modo che legga il journal di systemd indipendentemente dal fatto che la tua immagine scriva o meno /var/log/auth.log e imposta banaction = nftables affinché i ban vengano applicati tramite il firewall effettivo di Ubuntu. Un semplice apt install fail2ban protegge SSH già dal primo avvio. Verificalo con sudo fail2ban-client status sshd e cerca un valore diverso da zero in Total failed.

Perché Fail2ban non blocca nulla sul mio server?

Escludi in ordine le tre cause più comuni. Potresti eseguire i test da un indirizzo incluso in ignoreip, che per progettazione è esente. Potresti avere sovrascritto la configurazione predefinita funzionante incollando backend = auto in jail.local seguendo una guida obsoleta. Questo interrompe il blocco SSH su un'immagine priva di rsyslog e quindi anche di auth.log. Oppure potresti trovarti in un container senza alcun journal di systemd da leggere. Controlla Total failed in fail2ban-client status sshd: se non aumenta mai mentre journalctl -u ssh mostra errori reali, il jail sta leggendo la posizione sbagliata.

Come rimuovo il ban dal mio indirizzo IP?

Esegui sudo fail2ban-client set sshd unbanip YOUR.IP.HERE, che restituisce 1 in caso di successo, oppure sudo fail2ban-client unban --all per rimuovere tutti i ban. Se non puoi più accedere a SSH, usa la console web o VNC del provider per eseguire lo stesso comando. Il ban rifiuta ogni pacchetto proveniente dal tuo indirizzo verso la porta 22, quindi anche una sessione già aperta smette di funzionare. Aggiungi quindi il tuo indirizzo a ignoreip per impedire che il problema si ripresenti.

Qual è la differenza tra jail.conf e jail.local?

jail.conf contiene le impostazioni predefinite fornite dal progetto Fail2ban e può essere sostituito da un aggiornamento del pacchetto, quindi ogni modifica apportata a quel file è a rischio. Il pacchetto Debian/Ubuntu applica le proprie impostazioni aggiuntive tramite jail.d/defaults-debian.conf. Le tue modifiche devono essere inserite in jail.local, che viene letto dopo entrambi e ha la precedenza, e che non viene modificato dagli aggiornamenti. Solo un file *.local all'interno di jail.d/ viene letto ancora più tardi, quindi non lasciare lì file estranei. Conserva jail.conf come riferimento in sola lettura.

Fail2ban sostituisce l'autenticazione SSH basata su chiavi?

No. Fail2ban limita la frequenza dei tentativi falliti provenienti da un singolo indirizzo. Non protegge da un attacco lento e distribuito in cui ogni indirizzo rimane sotto la soglia. L'autenticazione basata esclusivamente su chiavi (PasswordAuthentication no) rende impossibili i tentativi di indovinare la password e Fail2ban riduce quindi il rumore nei log e rimuove rapidamente gli scanner. Usa entrambe le misure e, idealmente, non esporre SSH direttamente a Internet.