L’autenticazione SSH con password è la più ampia superficie esposta di un server ordinario. Contro di essa non possono né Fail2ban né alcuna soglia: mille indirizzi a un tentativo all’ora non raggiungeranno mai un limite, e continueranno a provare esattamente finché provare sarà possibile. Le chiavi eliminano proprio questa possibilità, e di tutto l’elenco dell’hardening è l’unica impostazione che cambia la situazione in modo qualitativo.

Solo una cosa spaventa: disattivare la password e restare fuori. Ecco l’ordine in cui questo non può accadere.

La chiave

Si genera sulla sua macchina, non sul server:

ssh-keygen -t ed25519 -C "portatile di lavoro"

ed25519 invece di RSA: più corta, più veloce e senza domande sulla lunghezza. RSA serve solo se deve raggiungere qualcosa di molto vecchio; in tal caso -t rsa -b 4096.

Mettere una passphrase alla chiave conviene: il file della chiave può essere rubato da un portatile, e senza passphrase funziona all’istante. Non dovrà digitarla ogni volta, se ne occupa ssh-agent, e su macOS e sulla maggior parte dei Linux desktop è già in funzione.

La copia sul server è un solo comando, finché la password funziona ancora:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@203.0.113.25

Se ssh-copy-id non è disponibile, il contenuto del file .pub si aggiunge come riga a ~/.ssh/authorized_keys sul server. I permessi contano: la cartella .ssh a 700, il file a 600, di proprietà dell’utente stesso. Con permessi diversi sshd si rifiuta in silenzio di leggere il file, ed è la causa più frequente del «la chiave non funziona».

La verifica che decide

Prima di disattivare qualsiasi cosa, apra una seconda connessione senza chiudere la prima:

ssh -o PasswordAuthentication=no user@203.0.113.25

L’opzione vieta al client di ripiegare sulla password: se l’accesso riesce, riesce con la chiave. Finché questo comando non passa, non vada oltre. E tenga aperta la prima connessione fino alla fine: è da lì che si ripara tutto ciò che romperà.

Il taglio e un tranello poco evidente

Le impostazioni vanno in un file a parte perché un aggiornamento del pacchetto non le cancelli. Ma il nome del file conta:

sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PasswordAuthentication no
PermitRootLogin no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LogLevel VERBOSE
EOF

Il fatto è che OpenSSH usa il primo valore ottenuto per un parametro, e non l’ultimo come quasi ovunque. I file di sshd_config.d vengono letti in ordine alfabetico, e le immagini cloud di Ubuntu vi depositano 50-cloud-init.conf, dove spesso figura PasswordAuthentication yes. Il suo file con il numero 90 in quella situazione non farà nulla: l’impostazione sembra a posto e la password continua a funzionare. Da qui il numero 10, che viene letto prima.

Che cosa sia venuto fuori davvero si vede senza indovinare:

sudo sshd -T | grep -Ei 'passwordauth|permitrootlogin|pubkeyauth'

Quel comando stampa la configurazione effettiva dopo tutte le inclusioni. Creda a lui, non al contenuto dei file.

Poi, controllo della sintassi e ricarica delicata del servizio:

sudo sshd -t && sudo systemctl reload ssh

sshd -t è obbligatorio: un errore di battitura nella configurazione lascerà il servizio a terra con restart e lei fuori. reload, inoltre, non interrompe le sessioni aperte.

Ubuntu 24.04: la porta non è dove crede

Un tranello proprio degli Ubuntu recenti: lì sshd viene avviato tramite un socket di systemd. In quella modalità la riga Port in sshd_config non fa nulla: ascolta il socket, non il demone. Se cambia la porta, è lui che va modificato:

sudo systemctl edit ssh.socket

e ListenStream= (un valore vuoto azzera il precedente) deve indicare la nuova porta. Il sintomo che lo rivela: la configurazione è cambiata, il servizio riavviato, e il server risponde ancora sulla 22.

A proposito del cambio di porta: come protezione non funziona, gli scanner trovano un servizio su qualunque porta in pochi minuti. Il suo unico effetto sono registri più tranquilli, perché la ricerca di massa va solo sulla 22. È comodo, ma non lo confonda con la sicurezza.

Chi può entrare

Un’aggiunta utile è un elenco esplicito:

AllowUsers deploy admin

Tutto ciò che non vi figura viene respinto ancora prima della verifica della chiave. Questo copre anche il caso in cui qualche pacchetto crei un utente di sistema con shell e cartella personale.

Una via d’ingresso di riserva

Una chiave su un portatile è un punto unico di guasto. Il disco muore, il portatile si perde, e il server diventa irraggiungibile per sempre. Un minimo ragionevole:

  • una seconda chiave, da un altro dispositivo, in authorized_keys;
  • una copia della chiave privata in un gestore di password o su una chiavetta cifrata;
  • un accesso alla console del provider già collaudato: VNC o seriale. Collaudato significa che ci è entrato almeno una volta, non che «c’è un pulsante da qualche parte nel pannello».

Ne approfitti per guardare che cosa c’è già in authorized_keys, sia del suo utente sia di root. Una chiave altrui lì sopravvive a qualsiasi cambio di password e resta un accesso funzionante.

Dopo

La ricerca delle password non sparirà, diventa semplicemente inutile: nei registri resteranno migliaia di righe Failed password, nessuna delle quali può concludersi con successo. Ciò che ora vale la pena osservare sono gli accessi riusciti: da quale indirizzo, con quale utente, a che ora. Un accesso riuscito con chiave da un indirizzo sconosciuto è un evento molto più importante di un milione di fallimenti, e assai più difficile da notare nel flusso generale. È proprio questo il quadro che mostra la pagina dimostrativa qui sotto.