SSH Hardening

Qualche giorno fa ho iniziato a lavorare con un nuovo cliente.
Classico scenario: VPS economico, applicazione web in produzione, “va tutto bene”, nessun problema apparente.
Prime cose che faccio sempre in questi casi? Analisi dell’infrastruttura, programmo gli aggiornamenti, controllo servizi esposti… e poi uno sguardo ai log.
# journalctl -u ssh --since "30 days ago" | grep Failed | wc -l
Il numero non era drammatico. Era… costante.
Tentativi di login su root. Utenti random. IP da mezzo mondo.
Niente compromissioni, per fortuna. Ma abbastanza rumore da ricordarmi una cosa semplice:
Se SSH è esposto su Internet, qualcuno proverà ad entrarci. Sempre.
Da lì è partita una revisione completa dell’hardening. E, soprattutto, una riflessione più ampia.
Le basi che non dovrebbero essere opzionali
1. Root non deve poter entrare
Sul VPS del cliente era attivo.
PermitRootLogin yes
No.
La prima modifica è sempre questa:
PermitRootLogin no
Accesso solo con utente normale + sudo.
Motivi:
- tracciabilità
- riduzione del rischio
- doppio layer da compromettere
Semplice. Ma fondamentale.
2. Password disabilitate
SSH esposto + password attive = attesa passiva di un brute force riuscito.
Configurazione minima:
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
Chiavi ed25519, sempre:
ssh-keygen -t ed25519 -a 100
Dopo questa modifica, il rumore nei log diventa irrilevante.
3. Cambiare porta: serve davvero?
Sì.
Non è sicurezza strutturale. È riduzione del rumore automatico.
Port 2849
Con firewall aggiornato, ovviamente.
Nel VPS del cliente, dopo il cambio porta, i tentativi sono crollati drasticamente. Non perché il server sia “più sicuro” in senso assoluto, ma perché la maggior parte dei bot scansiona solo la 22.
Nel mondo reale, questo conta.
4. Ridurre tutto al minimo indispensabile
Alcune direttive che considero baseline:
MaxAuthTries 3
LoginGraceTime 30
AllowGroups sshusers admins
X11Forwarding no
AllowTcpForwarding no
Principio semplice: default deny, eccezioni mirate.
La domanda che mi ha fatto riflettere davvero
Mentre sistemavo il VPS mi sono chiesto:
Ma questo server deve davvero avere SSH esposto su Internet?
Perché spesso l’hardening diventa un esercizio tecnico… quando forse la soluzione più efficace è architetturale.
Quando NON dovresti esporre SSH
Negli ultimi anni sto spingendo sempre più verso modelli diversi.
Accesso via VPN
WireGuard su un nodo pubblico e SSH accessibile solo su subnet privata.
Risultato:
- Porta SSH invisibile dall’esterno
- Attacchi azzerati
- Accesso controllato
Bastion host
Un solo server esposto, fortemente hardened, e tutti gli altri accessibili solo tramite quello.
Architettura classica, ancora perfettamente valida.
Apertura selettiva per IP
Se hai IP statico, puoi limitare l’accesso direttamente da firewall:
ufw allow from TUO_IP to any port 2849 proto tcp
Superficie di attacco ridotta praticamente a zero.
Ridurre l’esposizione > aggiungere regole
Questa è la vera lezione emersa dal VPS del cliente.
Puoi avere il miglior sshd_config del mondo. Ma un servizio non esposto è sempre più sicuro di uno perfettamente configurato ma pubblico.
A volte la miglior difesa è semplicemente non essere visibili.
CrowdSec: il passo successivo
Sul VPS del cliente era installato Fail2Ban.
Va benissimo. Fa il suo lavoro.
Ma negli ultimi tempi sto preferendo CrowdSec.
Perché?
Perché non è solo reattivo. È collaborativo.
CrowdSec:
- analizza i log
- identifica pattern malevoli
- utilizza blacklist condivise
- contribuisce in forma anonima alla community
In pratica: benefici della reputazione collettiva.
Installazione su Debian/Ubuntu
curl -s https://install.crowdsec.net | sudo bash
sudo apt install crowdsec
sudo apt install crowdsec-firewall-bouncer-iptables
SSH viene coperto automaticamente tramite le collection standard.
Controllo stato:
cscli metrics
cscli decisions list
Perché lo considero un upgrade rispetto a Fail2Ban
- Analisi comportamentale più evoluta
- Feed di reputazione condivisi
- Ecosistema di bouncer (nginx, firewall, cloudflare…)
- Dashboard e metriche più chiare
È come passare da una difesa locale a un sistema immunitario distribuito.
La mia baseline oggi
Se dobbiamo configurare un VPS esposto:
- root login disabilitato;
- solo chiavi moderne (es:ed25519);
- porta non standard;
- accesso limitato a gruppi specifici;
- logLevel VERBOSE;
- crowdSec attivo,
- preferibilmente accesso via VPN.
E soprattutto:
SSH esposto solo se strettamente necessario.
Conclusione
Quel VPS non era compromesso. Non era configurato male in modo drammatico.
Era semplicemente “normale”.
Ed è proprio questo il problema.
Nel 2026, un server “normale” esposto su Internet è un bersaglio automatico.
L’hardening non è paranoia. È riduzione del rischio.
E spesso la mossa più intelligente non è aggiungere un’altra direttiva a sshd_config.
È chiudere la porta.
Le opinioni in quanto tali sono opinabili e nulla ti vieta di approfondire l’argomento.
Risorse: