Guida

Fail2ban: configurare la protezione SSH dagli attacchi a forza bruta

Aggiornato: · Skillaria.Top

Fail2ban legge i log dei servizi, individua i tentativi di accesso falliti ripetuti e blocca temporaneamente l'IP dell'aggressore tramite il firewall. Per proteggere SSH basta installare il pacchetto, creare /etc/fail2ban/jail.local con la sezione [sshd] (enabled = true, maxretry, findtime, bantime) e riavviare il servizio; lo stato si controlla con fail2ban-client status sshd.

Fail2ban è un demone che controlla i log dei servizi, individua i tentativi di accesso falliti ripetuti e blocca per un certo tempo l'indirizzo IP da cui arrivano. Per SSH è la protezione più semplice contro gli attacchi a forza bruta sulle password: i bot smettono di insistere dopo pochi errori. Qui sotto trovi la configurazione di fail2ban dall'installazione fino al controllo dei ban e agli errori più comuni.

Perché serve fail2ban se ci sono le chiavi SSH

Ogni server con la porta 22 aperta riceve tentativi di accesso dai bot pochi minuti dopo l'avvio. Puoi verificarlo tu stesso:

$ sudo journalctl -u ssh --since "1 hour ago" | grep -c "Failed password"
412

Se l'accesso con password è disattivato e si usano solo le chiavi, indovinare l'accesso è praticamente impossibile. Ma fail2ban resta utile: ripulisce i log dal rumore, riduce il carico causato da migliaia di connessioni e ti protegge dagli errori di configurazione, come quando l'accesso con password viene riattivato per sbaglio. È un secondo livello di difesa, non un sostituto delle chiavi.

Come funziona fail2ban

La logica si compone di tre parti:

  • Filtro (filter) — un insieme di espressioni regolari che trovano nel log le righe relative a un tentativo fallito ed estraggono l'IP. I filtri stanno in /etc/fail2ban/filter.d/.
  • Azione (action) — cosa fare con l'aggressore: aggiungere una regola a iptables, nftables, ufw o firewalld. Le azioni stanno in /etc/fail2ban/action.d/.
  • Jail — l'insieme di filtro, azione, sorgente dei log e soglie. Ad esempio, il jail sshd controlla il log di SSH.

Se durante findtime da un IP si raccolgono maxretry corrispondenze, l'indirizzo viene bloccato per bantime. Allo scadere del tempo il ban viene rimosso automaticamente.

Installazione di fail2ban

Su Debian e Ubuntu:

sudo apt update
sudo apt install fail2ban

Su RHEL, Rocky, AlmaLinux il pacchetto si trova nel repository EPEL:

sudo dnf install epel-release
sudo dnf install fail2ban

Abilita l'avvio automatico e controlla lo stato del servizio:

sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban

Su Debian e Ubuntu il jail per SSH è già attivo di default tramite /etc/fail2ban/jail.d/defaults-debian.conf. Nella famiglia RHEL, dopo l'installazione non è attivato nulla: i jail vanno abilitati a mano.

Dove stanno le impostazioni: jail.conf e jail.local

Il file principale è /etc/fail2ban/jail.conf, ma non va modificato: al prossimo aggiornamento del pacchetto verrebbe sovrascritto. Le impostazioni personali si mettono in /etc/fail2ban/jail.local oppure in singoli file /etc/fail2ban/jail.d/*.local. Fail2ban legge i file in quest'ordine, e ciascuno sovrascrive il precedente:

  1. jail.conf
  2. jail.d/*.conf
  3. jail.local
  4. jail.d/*.local

Non copiare l'intero jail.conf in jail.local: così congeleresti i valori predefiniti attuali. In jail.local si scrive solo ciò che si cambia.

Configurazione di fail2ban per SSH: un jail.local minimo

Crea il file:

sudo nano /etc/fail2ban/jail.local

E aggiungi:

[DEFAULT]
# Propri indirizzi da non bannare mai
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
bantime  = 1h
findtime = 10m
maxretry = 5
# Da dove leggere i log: journal di systemd oppure file
backend  = systemd

[sshd]
enabled  = true
port     = ssh
maxretry = 3

Riavvia il servizio e verifica che il jail sia attivo:

$ sudo systemctl restart fail2ban
$ sudo fail2ban-client status
Status
|- Number of jail:      1
`- Jail list:   sshd

Significato dei parametri

ParametroSignificatoEsempio
enabledse il jail è attivotrue
portporta/e da bloccare per l'aggressoressh, 2222, ssh,2222
maxretryquanti errori sono tollerati prima del ban3
findtimefinestra in cui si contano gli errori10m
bantimedurata del ban; -1 significa per sempre1h, 1d
ignoreipindirizzi e sottoreti da non bannare10.0.0.0/8
backendsorgente dei logsystemd, auto
logpathpercorso del file di log con backend a file/var/log/auth.log
banactioncon quale firewall bannarenftables-multiport, ufw

I tempi si possono scrivere con i suffissi s, m, h, d, w. I numeri senza suffisso sono secondi.

backend: systemd oppure file

Su Debian 12 e Ubuntu 24.04 moderni il file /var/log/auth.log può non esistere, se rsyslog non è installato: i log di SSH vivono solo nel journal di systemd. In quel caso serve backend = systemd, altrimenti fail2ban non parte e segnala che non trova il file di log. Se invece rsyslog è presente, puoi tenere la variante con file:

[sshd]
enabled  = true
backend  = auto
logpath  = /var/log/auth.log

Sui sistemi RHEL il file equivalente è /var/log/secure.

SSH su una porta non standard

Se sshd ascolta, per esempio, sulla porta 2222, indicala nel jail: altrimenti fail2ban bloccherebbe la porta 22 e l'attacco proseguirebbe sulla 2222:

[sshd]
enabled = true
port    = 2222

Per bloccare per l'aggressore tutte le porte in una volta si può usare l'azione iptables-allports o nftables-allports tramite il parametro banaction.

Scelta del firewall: iptables, nftables, ufw, firewalld

Di default Debian usa banaction = nftables (nelle versioni più vecchie iptables), su RHEL firewalld. Se sul server è configurato ufw, conviene che i ban siano visibili lì:

[DEFAULT]
banaction = ufw

Per firewalld:

[DEFAULT]
banaction = firewallcmd-rich-rules

Per verificare che le regole siano davvero comparse, usa sudo nft list ruleset | grep f2b oppure sudo iptables -L -n | grep f2b: fail2ban crea catene con il prefisso f2b-.

Come verificare il funzionamento: fail2ban-client status

Lo strumento principale di gestione è fail2ban-client. Stato di un singolo jail:

$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 2
|  |- Total failed:     147
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 4
   |- Total banned:     38
   `- Banned IP list:   45.148.10.12 92.118.39.7 185.224.128.40 218.92.0.112

Qui si vede quanti errori ci sono ora nella finestra, quanti IP sono bloccati e quali. Per provare la protezione dal vivo, fai alcuni tentativi di accesso con password sbagliata da un'altra macchina (non da quella in ignoreip): dopo il terzo tentativo la connessione non andrà più a buon fine.

Il log di fail2ban stesso si trova in /var/log/fail2ban.log:

$ sudo tail -n 3 /var/log/fail2ban.log
2026-10-14 09:12:41,118 fail2ban.filter  [812]: INFO    [sshd] Found 218.92.0.112
2026-10-14 09:12:44,302 fail2ban.filter  [812]: INFO    [sshd] Found 218.92.0.112
2026-10-14 09:12:47,551 fail2ban.actions [812]: NOTICE  [sshd] Ban 218.92.0.112

Come sbloccare un IP in fail2ban

Se hai bloccato te stesso o un collega, rimuovi il ban dalla console del server (tramite il pannello dell'hosting o da un altro IP):

sudo fail2ban-client set sshd unbanip 203.0.113.25

Per rimuovere tutti i ban in tutti i jail:

sudo fail2ban-client unban --all

Per bloccare manualmente un indirizzo senza attendere il filtro:

sudo fail2ban-client set sshd banip 198.51.100.7

Perché l'episodio non si ripeta, inserisci i tuoi indirizzi fissi o la sottorete dell'ufficio in ignoreip.

Ban crescente per i recidivi

Molti bot tornano subito dopo lo sblocco. Dalla versione 0.11 fail2ban può aumentare la durata del ban per i recidivi:

[DEFAULT]
bantime = 1h
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w

Ogni nuovo ban dello stesso IP sarà più lungo del precedente, ma non oltre quattro settimane. Un'alternativa per le versioni più vecchie è il jail recidive, che legge il log di fail2ban stesso e blocca per lungo tempo gli indirizzi che si ripresentano più volte:

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

Verifica del filtro: fail2ban-regex

Se il jail è attivo ma non banna nessuno, controlla che il filtro trovi davvero le righe nel log. Per un log su file:

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

Per il journal di systemd:

sudo fail2ban-regex systemd-journal sshd

Nell'output guarda la riga Lines: ... matched. Zero corrispondenze significa che il filtro non corrisponde al formato dei log oppure che la sorgente è sbagliata. Prima di riavviare conviene verificare la sintassi di tutta la configurazione:

sudo fail2ban-client -t

Errori comuni

  • Il servizio non parte: «Have not found any log file for sshd jail». Manca /var/log/auth.log. Imposta backend = systemd oppure installa rsyslog.
  • I ban compaiono nello stato ma l'attacco continua. La porta indicata è sbagliata (SSH è stato spostato) oppure le regole del firewall sono scavalcate da una regola di autorizzazione precedente. Controlla port e l'output di nft list ruleset.
  • Le modifiche non hanno effetto. Hai modificato jail.conf, ma in jail.local o in jail.d/*.local c'è un altro valore. Verifica il valore effettivo: sudo fail2ban-client get sshd maxretry.
  • Ti sei bloccato da solo. Sblocca dalla console e aggiungi il tuo IP a ignoreip.
  • Fail2ban in Docker non vede gli attacchi. Le porte dei container vengono pubblicate tramite la catena DOCKER, che aggira INPUT. Per questi servizi si usa chain = DOCKER-USER nell'azione.

Altre misure per proteggere SSH

Fail2ban funziona bene insieme alle misure di base in /etc/ssh/sshd_config:

PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3

Dopo la modifica controlla la configurazione con sudo sshd -t e riavvia il servizio. Non chiudere la sessione attuale finché non hai verificato in una nuova che l'accesso con chiave funziona. Inoltre puoi limitare l'accesso a SSH a livello di firewall solo agli indirizzi necessari.

Conclusioni

La configurazione di fail2ban si riduce a pochi passi: installare il pacchetto, creare jail.local con la sezione [sshd], scegliere il backend e la porta giusti, impostare maxretry, findtime e bantime, inserire i propri indirizzi in ignoreip e verificare con fail2ban-client status sshd. Insieme all'accesso solo con chiavi, questo protegge SSH in modo affidabile dagli attacchi a forza bruta. La protezione del server e di fail2ban è trattata in pratica nel corso di Linux.

Domande frequenti

Serve fail2ban se l'accesso con password è disattivato?

Non è obbligatorio, ma è utile: elimina migliaia di tentativi inutili dai log, riduce il carico e ti copre se qualcuno riattiva per sbaglio l'accesso con password.

Come vedere tutti gli IP bloccati in tutti i jail?

Esegui sudo fail2ban-client banned — il comando mostra gli indirizzi bloccati per ogni jail. Per un solo jail usa fail2ban-client status sshd.

I ban restano dopo un riavvio del server?

Sì, fail2ban memorizza i ban nel database SQLite (/var/lib/fail2ban/fail2ban.sqlite3) e ripristina i blocchi attivi all'avvio, a meno che il parametro dbpurgeage non li abbia già eliminati.

Si può proteggere con fail2ban anche altro oltre a SSH?

Sì, ci sono filtri per nginx, Apache, Postfix, Dovecot e altri servizi. Basta attivare il jail necessario in jail.local, per esempio [nginx-http-auth] con enabled = true.

In cosa fail2ban si differenzia da una restrizione nel firewall?

Il firewall consente o vieta in modo statico degli indirizzi, mentre fail2ban banna dinamicamente chi si comporta male, secondo i log. Spesso si combinano: una whitelist nel firewall e fail2ban per tutto il resto.

Impara l’argomento in video

Questo argomento è trattato in modo approfondito, con pratica, nel corso «Linux: с нуля до уверенного администрирования».

Vai al corso