InfraFenceInfraFence

Live Security Operations

Inizia

Come bloccare gli attacchi brute force SSH

Ultimo aggiornamento:

Qualsiasi server con la porta 22 aperta su internet riceve tentativi di password pochi minuti dopo l'avvio, tutto il giorno, da migliaia di indirizzi. Sono quasi sempre bot che provano root, admin e nomi comuni con liste di password trafugate. Entrano solo dove una password è debole, ma riempiono i log, consumano CPU, e basta un account debole.

La soluzione è a strati: rendere inutili le password (solo chiavi), togliere di mezzo root, poi bannare e limitare quello che resta. I comandi qui sotto sono per Debian e Ubuntu e per la famiglia RHEL (RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora).

Verificare se sei sotto attacco

Il demone SSH registra ogni tentativo fallito. Conta le ultime 24 ore, poi guarda quali indirizzi ne mandano di più:

Qualsiasi distribuzione con systemd
sudo journalctl --since "24 hours ago" | grep -cE "Failed password|Invalid user"
Qualsiasi distribuzione con systemd
sudo journalctl --since "24 hours ago" \
  | grep -E "Failed password|Invalid user" \
  | grep -oE "from [0-9a-fA-F.:]+ port" | awk '{print $2}' \
  | sort | uniq -c | sort -rn | head -20

Centinaia o migliaia di righe al giorno sono normali per un server con IP pubblico. Se il journal non viene conservato tra un riavvio e l'altro, le stesse righe sono in /var/log/auth.log su Debian e Ubuntu e in /var/log/secure sulla famiglia RHEL.

Configurare le chiavi SSH e provarle prima di tutto

Tutto quello che segue spegne le password, quindi prima serve una chiave che funziona. Sul tuo computer crea una chiave, copiala sul server ed entra con quella. Sostituisci deploy con il tuo utente e SERVER_IP con l'indirizzo del server.

Sul tuo computer
ssh-keygen -t ed25519 -C "laptop"
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@SERVER_IP
ssh -i ~/.ssh/id_ed25519 deploy@SERVER_IP

L'ultimo comando deve farti entrare senza chiedere la password dell'account (può chiedere la passphrase della chiave, che resta sul tuo computer).

Attenzione: Da qui in avanti tieni aperta una sessione SSH sul server e fai ogni prova da un secondo terminale. Se una modifica ti chiude fuori, la sessione aperta è il modo per annullarla. Prima di cominciare trova anche la console web del provider (VNC o seriale): funziona senza SSH.

Creare un utente sudo prima di disattivare root

Se oggi entri come root, crea prima un utente normale con i permessi sudo e dagli le stesse chiavi.

Debian / Ubuntu
sudo adduser deploy
sudo usermod -aG sudo deploy
RHEL, Rocky Linux, AlmaLinux, Oracle Linux, Fedora
sudo useradd -m deploy
sudo passwd deploy
sudo usermod -aG wheel deploy
Copiare le chiavi di root al nuovo utente
sudo mkdir -p /home/deploy/.ssh
sudo cp /root/.ssh/authorized_keys /home/deploy/.ssh/
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys
Solo famiglia RHEL, per le etichette SELinux
sudo restorecon -R /home/deploy/.ssh

Dal secondo terminale entra con il nuovo utente ed esegui sudo -v: deve accettare la password dell'utente. Solo allora vai avanti.

Disattivare l'accesso con password e quello di root

Le versioni attuali di Debian, Ubuntu, famiglia RHEL 9 e Fedora leggono file aggiuntivi da /etc/ssh/sshd_config.d/. Controlla che la tua lo faccia:

Qualsiasi distribuzione
grep -i '^Include' /etc/ssh/sshd_config

Se stampa Include /etc/ssh/sshd_config.d/*.conf, scrivi le impostazioni in un file a parte. SSH tiene il primo valore che legge per ogni impostazione, e i file sono letti in ordine di nome: il prefisso 00- vince su file come 50-cloud-init.conf, che su alcune immagini cloud riattiva le password.

Qualsiasi distribuzione
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf > /dev/null <<'EOF'
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
MaxAuthTries 4
LoginGraceTime 30
EOF

Se la riga Include non c'è (RHEL 8 e derivate), imposta le stesse sei righe direttamente in /etc/ssh/sshd_config, al posto di quelle esistenti. Poi prova la configurazione e guarda i valori che SSH userà davvero:

Qualsiasi distribuzione
sudo sshd -t && echo "config OK"
sudo sshd -T | grep -Ei '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin|maxauthtries) '

Ogni riga deve mostrare il valore impostato. Se root deve ancora entrare con una chiave, per esempio per un backup, usa PermitRootLogin prohibit-password invece di no. Ricarica SSH: le sessioni aperte restano collegate.

Debian / Ubuntu
sudo systemctl reload ssh
RHEL, Rocky Linux, AlmaLinux, Oracle Linux, Fedora
sudo systemctl reload sshd

Attenzione: Non chiudere ancora la sessione aperta. Dal secondo terminale entra con la chiave, poi verifica che una password venga rifiutata: il comando qui sotto deve finire con Permission denied (publickey).

Sul tuo computer
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password deploy@SERVER_IP

Cambiare la porta SSH, sapendo cosa non risolve

Spostare SSH dalla porta 22 riduce il rumore nei log, perché la maggior parte dei bot prova solo la 22. Non rende SSH più sicuro: gli scanner trovano la nuova porta in poche ore, e un attaccante mirato subito. Con l'accesso solo a chiave la porta conta poco. Fallo per avere log più puliti, non per la sicurezza, e solo dopo i passi precedenti.

Scegli una porta (qui 2222), aprila nel firewall e, sulla famiglia RHEL, di' a SELinux che SSH può usarla:

Debian / Ubuntu con ufw
sudo ufw allow 2222/tcp
Famiglia RHEL con firewalld e SELinux
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222

Apri la porta anche nel firewall cloud o nel security group del provider. Poi imposta la porta e riavvia SSH:

Qualsiasi distribuzione
echo "Port 2222" | sudo tee /etc/ssh/sshd_config.d/01-port.conf
sudo sshd -t && echo "config OK"

Da Ubuntu 24.04 SSH può essere avviato da ssh.socket: se il primo comando qui sotto stampa active, esegui tutte e quattro le righe; altrimenti solo l'ultima.

Debian / Ubuntu
systemctl is-active ssh.socket
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
sudo systemctl restart ssh
RHEL, Rocky Linux, AlmaLinux, Oracle Linux, Fedora
sudo systemctl restart sshd
Sul tuo computer
ssh -p 2222 deploy@SERVER_IP

Attenzione: Solo quando l'accesso sulla nuova porta funziona, togli dal firewall la regola della porta 22. Anche fail2ban, sshguard e i rate limit qui sotto devono usare la nuova porta.

Bannare chi insiste con fail2ban o sshguard

Con le password spente i tentativi non possono riuscire, ma bannare gli indirizzi che continuano a provare riduce carico e rumore. fail2ban legge il log e banna un indirizzo sul firewall dopo un certo numero di errori.

Debian / Ubuntu
sudo apt update
sudo apt install -y fail2ban python3-systemd
Rocky Linux, AlmaLinux, CentOS Stream (EPEL)
sudo dnf install -y epel-release
sudo dnf install -y fail2ban

Su RHEL e Oracle Linux attiva EPEL come dice la loro documentazione, poi installa fail2ban. Su Fedora è nei repository principali. Amazon Linux 2023 non può usare EPEL: usa invece il rate limit del firewall qui sotto.

Le impostazioni vanno in jail.local, mai in jail.conf, che gli aggiornamenti sovrascrivono. Controlla di non averne già uno, poi crealo. Sostituisci YOUR_OFFICE_IP con gli indirizzi fissi da cui lavori, oppure toglilo, e imposta port sulla tua porta SSH se l'hai cambiata.

Qualsiasi distribuzione
ls -l /etc/fail2ban/jail.local
Qualsiasi distribuzione
sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 YOUR_OFFICE_IP
bantime = 1h
bantime.increment = true
findtime = 10m
maxretry = 5

[sshd]
enabled = true
backend = systemd
port = ssh
EOF

Così un indirizzo viene bannato per un'ora dopo 5 errori in 10 minuti, e più a lungo ogni volta che ritorna. backend = systemd legge il journal, e funziona anche su Debian 12 e successive, dove /var/log/auth.log può non esistere.

Qualsiasi distribuzione
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Sotto attacco, Total failed e Currently banned crescono in pochi minuti. Se Total failed resta a 0 mentre il journal mostra accessi falliti, la jail non sta leggendo il log giusto. Per togliere un ban:

Qualsiasi distribuzione
sudo fail2ban-client set sshd unbanip 203.0.113.7

sshguard, l'alternativa più leggera

sshguard fa lo stesso lavoro con meno configurazione ed è nei pacchetti di Debian e Ubuntu (e in EPEL). Metti prima i tuoi indirizzi nella sua whitelist, poi guarda sudo journalctl -u sshguard -f durante un attacco per vedere i blocchi. Usane uno dei due, non entrambi.

Debian / Ubuntu
sudo apt install -y sshguard
echo "YOUR_OFFICE_IP" | sudo tee -a /etc/sshguard/whitelist
sudo systemctl restart sshguard

Limitare o restringere SSH sul firewall

Su Ubuntu e Debian con ufw, limit rifiuta un indirizzo che apre 6 o più connessioni in 30 secondi. Sostituisce una semplice regola allow 22/tcp. Se sudo ufw status mostra anche una regola OpenSSH, cancellala quando il limite è attivo (sudo ufw delete allow OpenSSH): verrebbe applicata prima del limite.

Debian / Ubuntu con ufw
sudo ufw limit 22/tcp
sudo ufw enable
sudo ufw status verbose

Attenzione: Se ufw non è ancora attivo, ufw enable comincia a bloccare ogni porta senza una regola. Consenti i servizi che il server offre (per esempio sudo ufw allow 80,443/tcp) prima di attivarlo, e tieni la sessione aperta.

Le rich rule di firewalld hanno un limit, ma conta tutte le sorgenti insieme: un attacco può esaurire la quota e chiudere fuori anche te. Sulla famiglia RHEL usa fail2ban per i limiti per indirizzo.

Consentire SSH solo dai tuoi indirizzi

Il passo più forte, se lavori da indirizzi fissi o da una VPN: nessun altro può nemmeno raggiungere SSH.

Debian / Ubuntu con ufw
sudo ufw allow from YOUR_OFFICE_IP to any port 22 proto tcp
sudo ufw delete limit 22/tcp
sudo ufw status numbered
Famiglia RHEL con firewalld
sudo firewall-cmd --permanent --zone=trusted --add-source=YOUR_OFFICE_IP
sudo firewall-cmd --reload
sudo firewall-cmd --permanent --zone=public --remove-service=ssh
sudo firewall-cmd --reload

Attenzione: Così chiudi fuori ogni altro indirizzo, anche il tuo se cambia. Prova un nuovo accesso dopo il primo reload e prima di togliere la regola SSH pubblica, e tieni la console web del provider come via di ritorno.

Come InfraFence gestisce il brute force SSH

L'agent InfraFence legge il log di SSH mentre viene scritto e banna un indirizzo sul firewall quando raggiunge la soglia di errori nella finestra di tempo, entrambe modificabili dalla dashboard.

  • 15 schemi di rilevamento: password errate, utenti inesistenti, errori PAM, scansioni prima dell'autenticazione, protocolli errati e connessioni chiuse durante lo scambio di chiavi.
  • Ban crescenti: 24 ore, 7 giorni, 30 giorni, poi permanente, oppure una durata che scegli tu. Facoltativo: un indirizzo bannato su un server viene bannato su tutti i tuoi server.
  • La stessa protezione per gli accessi a Postfix, Dovecot, MySQL, PostgreSQL, MongoDB, Pure-FTPd, ProFTPD e vsftpd.
  • I controlli di hardening segnalano l'accesso di root, quello con password, la porta predefinita e un MaxAuthTries alto. MaxAuthTries si corregge con un clic, in un file a parte (/etc/ssh/sshd_config.d/00-infrafence-hardening.conf) provato prima di ricaricare SSH. Root, password e porta possono chiuderti fuori, quindi vengono spiegati passo per passo, come in questa guida.
  • Ogni sessione SSH è seguita dall'accesso all'uscita e riceve un punteggio di rischio, così sai chi era collegato quando è scattato qualcos'altro.

Funziona accanto a fail2ban: l'agent lo riconosce e tiene le sue regole in catene INFRAFENCE separate, che rimette al loro posto dopo un reload del firewall.

Domande

Cambiare la porta SSH basta per fermare il brute force?
No. Riduce i tentativi nei log, perché la maggior parte dei bot prova solo la porta 22, ma gli scanner trovano presto la nuova porta. È l'accesso solo con chiave a rendere inutili i tentativi.
Meglio fail2ban o sshguard?
Per SSH vanno bene entrambi. fail2ban ha più filtri per altri servizi e più opzioni; sshguard richiede meno configurazione. Usane uno, non tutti e due, così non si contendono gli stessi indirizzi.
Ho disattivato le password e vedo ancora accessi falliti. C'è qualcosa che non va?
No. I bot continuano a provare perché non sanno che le password sono spente. I tentativi falliscono prima che una password venga controllata. Ban e rate limit riducono il rumore.

Provalo gratis su 1 server

Starter è gratuito per un server, con protezione completa e blocco automatico. Senza carta di credito.

Installa l'agent come root, con il tuo token al posto di <TOKEN>:

curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>

Il token si crea nella dashboard, in Server › Aggiungi server.