Fail2ban: configurare la protezione SSH dagli attacchi a forza bruta
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
sshdcontrolla 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:
jail.confjail.d/*.confjail.localjail.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
| Parametro | Significato | Esempio |
|---|---|---|
enabled | se il jail è attivo | true |
port | porta/e da bloccare per l'aggressore | ssh, 2222, ssh,2222 |
maxretry | quanti errori sono tollerati prima del ban | 3 |
findtime | finestra in cui si contano gli errori | 10m |
bantime | durata del ban; -1 significa per sempre | 1h, 1d |
ignoreip | indirizzi e sottoreti da non bannare | 10.0.0.0/8 |
backend | sorgente dei log | systemd, auto |
logpath | percorso del file di log con backend a file | /var/log/auth.log |
banaction | con quale firewall bannare | nftables-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. Impostabackend = systemdoppure 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
porte l'output dinft list ruleset. - Le modifiche non hanno effetto. Hai modificato
jail.conf, ma injail.localo injail.d/*.localc'è 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-USERnell'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.
Questo argomento è trattato in modo approfondito, con pratica, nel corso «Linux: с нуля до уверенного администрирования».
Vai al corso