Cosa fa
fail2ban legge i log. Quando un indirizzo fallisce il login maxretry volte entro findtime, aggiunge una regola del firewall che blocca quell'indirizzo per bantime. Tutto qui. Non ispeziona il traffico SSH e non rende robusta una password debole.
Installa
sudo apt install fail2ban python3-systemd
python3-systemd gli permette di leggere il journal di systemd. Sui sistemi della famiglia Red Hat il pacchetto è in EPEL. Su Debian 13 e Ubuntu 24.04 il pacchetto abilita già la jail sshd, con il backend systemd e nftables, tramite /etc/fail2ban/jail.d/defaults-debian.conf.
Configura: jail.local
Non modificare jail.conf, perché gli aggiornamenti possono sostituirlo. Metti le tue impostazioni in /etc/fail2ban/jail.local:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
backend = systemd
| Impostazione | Significato | Valore predefinito del pacchetto |
|---|---|---|
bantime | Quanto dura un ban | 10m |
findtime | La finestra in cui i fallimenti si sommano | 10m |
maxretry | Fallimenti ammessi in quella finestra | 5 |
ignoreip | Indirizzi mai bloccati | nessuno |
backend | Da dove arrivano i log | auto |
Aggiungi a ignoreip il tuo indirizzo fisso, così qualche errore di battitura non può chiuderti fuori. Se il tuo indirizzo cambia, assicurati di avere una console a cui ripiegare.
Usa backend = systemd dove i log di SSH vanno nel journal, come su Debian recente, che può non avere affatto /var/log/auth.log. Su un sistema che scrive quel file, puoi usare invece backend = auto e logpath.
Se sshd ascolta su un'altra porta, aggiungi port = 2222 alla jail. La regola che abbiamo visto corrispondeva solo alla porta indicata nell'impostazione della jail (tcp dport 22), quindi un ban sulla porta sbagliata non blocca nulla.
Prova il file, poi riavvia:
sudo fail2ban-client -t
sudo systemctl restart fail2ban
Controlla che funzioni davvero
sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 4
| `- Journal matches: _SYSTEMD_UNIT=ssh.service + _COMM=sshd
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: 203.0.113.20
Fai una prova reale. Da un altro indirizzo, non il server stesso e non uno in ignoreip, fai fallire un login con password ed esegui di nuovo il comando. Total failed deve salire. Se resta a 0, la jail non sta leggendo i log giusti, e il resto non serve a nulla. Confronta la corrispondenza nel journal con il nome della tua unit, ssh.service o sshd.service, e controlla con journalctl -u ssh -n 20.
Una volta bloccato, il client vede questo:
ssh: connect to host 203.0.113.10 port 22: Connection refused
La regola del firewall si vede con sudo nft list ruleset:
table inet f2b-table {
set addr-set-sshd {
type ipv4_addr
elements = { 203.0.113.20 }
}
chain f2b-chain {
type filter hook input priority filter - 1; policy accept;
tcp dport 22 ip saddr @addr-set-sshd reject with icmp port-unreachable
}
}
Comandi di tutti i giorni
| Obiettivo | Comando |
|---|---|
| Elencare le jail | sudo fail2ban-client status |
| Togliere il ban a un indirizzo | sudo fail2ban-client set sshd unbanip 203.0.113.20 |
| Togliere tutti i ban | sudo fail2ban-client unban --all |
| Bloccare a mano | sudo fail2ban-client set sshd banip 203.0.113.20 |
| Vedere i ban e quando finiscono | sudo fail2ban-client get sshd banip --with-time |
| Ignorare un indirizzo subito | sudo fail2ban-client set sshd addignoreip 203.0.113.10 |
| Leggere le impostazioni in uso | sudo fail2ban-client get sshd bantime |
| Leggere il suo log | sudo tail /var/log/fail2ban.log |
La modifica con addignoreip dura solo fino al prossimo reload. Aggiungila a jail.local per mantenerla.
Cosa conta come fallimento
Abbiamo provato la modalità predefinita su OpenSSH 10.0 con questi risultati:
- Una password sbagliata è stata contata, come anche una password sbagliata per un utente che non esiste.
- Una disconnessione Too many authentication failures è stata contata come uno.
- Le connessioni che offrivano una chiave sbagliata e poi si arrendevano non sono state contate. Nel log compaiono come
Connection closed by authenticating user.
Con mode = aggressive nella jail [sshd], sono state contate anche le connessioni con chiave sbagliata. Ne cattura di più, e rende anche più facile bloccare qualcuno con un client configurato male, quindi tieni ignoreip aggiornato.
Da cosa non protegge
- Una chiave rubata o una password trapelata. Un login corretto non è un fallimento, quindi non c'è nessun ban.
- Tentativi lenti o distribuiti. Molti indirizzi che fanno uno o due tentativi ciascuno restano sotto il limite.
- Una debolezza di sshd stesso. Reagisce alle righe di log, a cose fatte.
- Altri servizi, a meno che abbiano le proprie jail.
Può anche farti male: tutti dietro il NAT di un ufficio condividono un indirizzo, quindi gli errori di una persona possono chiudere fuori l'intero ufficio.
Se una chiave finisce in mani sbagliate, serve sapere dove è installata e togliere la chiave SSH da ogni server.
Cosa conta di più
Se il server accetta solo chiavi, per i tentativi con password non c'è nulla da indovinare, qualunque sia il numero di tentativi. Quindi fai prima questo:
- Usa una chiave e disattiva l'accesso con password.
- Limita chi può raggiungere la porta 22 con un firewall o una VPN, se puoi.
- Rivedi il resto delle tue impostazioni di sshd.
Dopo, fail2ban è un extra utile che tiene i log più tranquilli. Inoltre, OpenSSH 9.8 e successivi hanno un proprio PerSourcePenalties, attivo per impostazione predefinita, che rifiuta per poco tempo gli indirizzi che si comportano male. È molto più breve di un tipico ban di fail2ban, quindi i due funzionano bene insieme.
Domande
Come si sblocca un IP in fail2ban?
Esegui sudo fail2ban-client set sshd unbanip seguito dall'indirizzo. sudo fail2ban-client unban --all toglie tutti i ban in tutte le jail.
Come controllo che fail2ban funzioni?
Esegui sudo fail2ban-client status sshd, sbaglia un login da un altro indirizzo e ripeti il comando. Total failed deve salire. Se resta a 0, la jail non legge i log di SSH.
Perché un client bloccato vede Connection refused?
Con l'azione nftables predefinita su Debian, un indirizzo bloccato riceve un reject, quindi ssh stampa Connection refused invece di un timeout. Un'azione che scarta i pacchetti sembrerebbe invece un timeout.
Le chiavi SSH sbagliate contano come fallimenti?
Non nella modalità predefinita. Nel nostro test, cinque connessioni con una chiave sbagliata non hanno aggiunto nulla al conteggio. mode = aggressive nella jail le ha contate.
Fonti
- jail.conf(5), fail2ban
- Filtro sshd, fail2ban
- Documentazione di Fail2Ban
- sshd_config(5), PerSourcePenalties