SSH è uno dei servizi più delicati di un server perché, quando funziona come previsto, consegna proprio ciò che un attaccante vorrebbe ottenere: una shell autenticata sul sistema. La differenza tra un servizio SSH sicuro e uno pericoloso non è quindi “avere o non avere SSH”, ma chi può raggiungerlo, come può autenticarsi e quali privilegi ottiene dopo l’accesso.
Per anni molte guide hanno trattato il cambio della porta 22 come una misura di sicurezza fondamentale. Spostare il servizio su una porta non standard riduce effettivamente il rumore dei bot più banali, ma non cambia il modello di sicurezza: una scansione completa trova comunque il servizio. È utile come misura operativa, non come sostituto dell’autenticazione forte o delle ACL.
Password e chiavi non sono semplicemente due password diverse
Con l’autenticazione a password il server riceve un segreto che deve verificare. Con una chiave pubblica il segreto privato non lascia mai il client: il server possiede soltanto la chiave pubblica e verifica una firma. Questo cambia drasticamente la resistenza a brute force e credential stuffing, a patto naturalmente che la chiave privata sia protetta e gestita correttamente.
La passphrase della chiave privata protegge invece il file sul client. Se il notebook viene rubato, una chiave cifrata con passphrase non è immediatamente utilizzabile. È quindi possibile avere sia la comodità delle chiavi sia una seconda barriera locale.
La rete è parte dell’hardening
Un server amministrato soltanto dalla VLAN Gestione o attraverso una VPN non ha motivo di esporre SSH a Internet. Questo è spesso il controllo più efficace in assoluto: riduciamo il numero di soggetti che possono persino iniziare una sessione TCP verso sshd. Fail2Ban e le policy di autenticazione lavorano dopo; il firewall lavora prima.
Hardening senza chiudersi fuori
SSH ha una caratteristica antipatica: una configurazione errata può togliere l’accesso proprio alla persona che dovrebbe correggerla. Per questo la procedura è parte integrante della sicurezza. Manteniamo una sessione aperta, validiamo con sshd -t, controlliamo la configurazione risultante con sshd -T, facciamo un reload e proviamo una seconda sessione prima di chiudere la prima.
A questo punto possiamo passare alle impostazioni concrete.
Prima regola: mantenere aperta una sessione
Durante l’hardening non chiudiamo la sessione amministrativa già funzionante. Apriremo una seconda connessione solo dopo aver validato la configurazione. È una precauzione banale che evita di trasformare un errore di battitura in una visita al datacenter.
Creare un amministratore dedicato
adduser adminops
usermod -aG sudo adminops
id adminops
Generare una chiave Ed25519
Le vecchie guide usavano DSA. Non va più fatto. Per un nuovo accesso interattivo usiamo normalmente Ed25519, proteggendo la chiave privata con passphrase.
ssh-keygen -t ed25519 -a 100 -C "adminops@workstation"
ssh-copy-id adminops@server.example.net
ssh adminops@server.example.net
Per hardware token compatibili possiamo valutare anche chiavi FIDO, per esempio ed25519-sk.
Configurazione separata in sshd_config.d
Sulle distribuzioni moderne è più pulito aggiungere un file dedicato invece di trasformare /etc/ssh/sshd_config in una stratificazione di modifiche storiche.
# /etc/ssh/sshd_config.d/90-hardening.conf
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 30
AllowGroups ssh-admins
X11Forwarding no
Prima creiamo il gruppo e aggiungiamo l’utente:
groupadd -f ssh-admins
usermod -aG ssh-admins adminops
Port forwarding: disabilitarlo solo se non serve
AllowTcpForwarding no e AllowAgentForwarding no riducono la superficie, ma possono rompere tunnel, bastion host, deploy e automazioni. Non vanno copiati alla cieca. Se il server non usa queste funzioni possiamo aggiungerli; altrimenti limitiamoli con blocchi Match.
Validare prima del reload
sshd -t
# Configurazione effettiva risultante
sshd -T | less
systemctl reload ssh
# su alcune distribuzioni:
systemctl reload sshd
Solo adesso apriamo un nuovo terminale e proviamo l’accesso con adminops. La vecchia sessione root/amministrativa rimane aperta finché il test non è concluso.
Limitare SSH a una rete di gestione
La protezione migliore è non rendere SSH raggiungibile da dove non serve. Se disponiamo di una VLAN Gestione, VPN o bastion, la porta 22 dovrebbe essere consentita soltanto da lì.
# esempio UFW
ufw allow from 10.0.20.0/24 to any port 22 proto tcp
# verifica
ss -lntp | grep ':22'
Su nftables/OpenWrt la stessa regola va espressa nel firewall centrale. Spostare SSH su 2222 può ridurre il rumore nei log, ma non sostituisce una ACL.
Fail2Ban
apt install fail2ban
cat > /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
EOF
systemctl enable --now fail2ban
fail2ban-client status sshd
Fail2Ban è una seconda linea: se SSH è raggiungibile solo dalla VPN o dalla rete Gestione, il numero di tentativi ostili si riduce prima ancora che Fail2Ban debba intervenire.
Log e diagnostica
journalctl -u ssh -f
journalctl -u sshd -f
ssh -vvv adminops@server.example.net
# Algoritmi supportati dal client
ssh -Q key
ssh -Q PubkeyAcceptedAlgorithms
Non congelare gli algoritmi senza motivo
Una vecchia abitudine è copiare liste rigide di cipher, MAC e KEX da una guida e lasciarle lì per anni. Con OpenSSH aggiornato, i default evolvono insieme al software. Restringere gli algoritmi ha senso per requisiti precisi o compliance, ma una lista manuale dimenticata può diventare più vecchia dei default che voleva “rafforzare”.
Checklist finale
sshd -t
sshd -T | egrep 'permitrootlogin|passwordauthentication|pubkeyauthentication|maxauthtries'
fail2ban-client status sshd
ss -lntp | grep ':22'
# Test da una seconda sessione
ssh adminops@server.example.net
Riferimento
La fonte da consultare per la versione installata resta sshd_config(5).


