Hai appena messo online un nuovo server Linux e SSH è l’unico punto di accesso. In questa fase non serve un tutorial teorico. Serve una checklist corta, verificabile e ripetibile.
Lo scenario è semplice: server appena deployato, accesso root ancora attivo, chiavi non ancora controllate, fail2ban non testato e troppo spesso una regola sbagliata che ti lascia fuori. Qui trovi una mini checklist post-deploy pensata per evitare proprio questo.
Obiettivo pratico: verificare hardening SSH, permessi file, aggiornamenti, segreti e principio del least privilege senza perdere tempo in passaggi superflui.
Prerequisiti
Prima di toccare la configurazione, assicurati di avere una sessione SSH già aperta e un secondo accesso di emergenza. Se lavori su cloud, prepara anche la console web del provider.
- Accesso sudo su una shell attiva.
- Un utente non-root già creato.
- Chiave SSH privata disponibile sul client.
- Accesso alla console del provider o al pannello rescue.
- Pacchetti base: openssh-server, fail2ban, cron o systemd timer per gli update.
Warning: non chiudere mai la sessione corrente prima di aver aperto una seconda connessione con il nuovo utente e la nuova chiave.
Step 1: fotografa lo stato reale di sshd prima di cambiare
Il primo controllo non è il file di configurazione, ma lo stato effettivo di sshd. Molte opzioni vengono sovrascritte da include, drop-in o override del sistema.
sudo sshd -T | egrep 'permitrootlogin|passwordauthentication|pubkeyauthentication|kbdinteractiveauthentication|x11forwarding|allowtcpforwarding|clientaliveinterval|clientalivecountmax'# Output:
permitrootlogin no
passwordauthentication no
pubkeyauthentication yes
kbdinteractiveauthentication no
x11forwarding no
allowtcpforwarding noPerché funziona: sshd -T mostra la configurazione già risolta, non solo quello che leggi nel file.
Nota cross-distro: su alcune distribuzioni le direttive effettive arrivano da /etc/ssh/sshd_config.d/*.conf, non solo da /etc/ssh/sshd_config.
Step 2: blocca l’accesso root e verifica che l’utente operativo funzioni
Il punto non è “vietare root” in astratto. Il punto è confermare che l’utente amministrativo usi sudo e che la chiave funzioni prima di disabilitare il login diretto.
sudo useradd -m -s /bin/bash deployops
sudo usermod -aG sudo deployops
sudo mkdir -p /home/deployops/.ssh
sudo chmod 700 /home/deployops/.ssh
sudo cp /root/.ssh/authorized_keys /home/deployops/.ssh/authorized_keys
sudo chown -R deployops:deployops /home/deployops/.ssh
sudo chmod 600 /home/deployops/.ssh/authorized_keys# Output:
drwx------ 2 deployops deployops 4096 ... /home/deployops/.ssh
-rw------- 1 deployops deployops 399 ... /home/deployops/.ssh/authorized_keysPerché funziona: SSH rifiuta chiavi e directory con permessi troppo larghi, quindi il controllo dei permessi è parte della sicurezza, non un dettaglio estetico.
Note: su Debian e Ubuntu il gruppo amministrativo è spesso sudo. Su RHEL, AlmaLinux e Rocky è più comune wheel.
Test immediato da client
ssh -i ~/.ssh/id_ed25519 deployops@server.example.com 'whoami && sudo -n true && echo sudo-ok'# Output:
deployops
sudo-okPerché funziona: provi sia l’autenticazione sia il passaggio a sudo senza password interattiva.
Step 3: riduci la superficie di attacco di sshd senza rompere l’accesso
Qui conviene lavorare per blocchi piccoli. Cambiare troppi parametri insieme rende difficile capire quale opzione ha causato un lockout.
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
sudoedit /etc/ssh/sshd_configInserisci o verifica queste direttive:
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
X11Forwarding no
AllowTcpForwarding no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2# Output:
Config savedPerché funziona: togli i metodi di login più fragili e limiti brute force e sessioni zombie.
Warning: se usi tunnel SSH per amministrazione o deploy, AllowTcpForwarding no può romperli. In quel caso lascialo su yes e limita con match per utente o gruppo.
Prima del reload, fai il controllo sintattico.
sudo sshd -t# Output:
nessun outputPerché funziona: sshd -t blocca errori di sintassi prima che il demone ricarichi una configurazione invalida.
Step 4: installa e testa fail2ban con un caso reale, non a occhio
fail2ban serve solo se legge i log giusti e applica la jail giusta. La verifica post-deploy deve confermare entrambi.
sudo apt-get update && sudo apt-get install -y fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status# Output:
Status
|- Number of jail: 1
`- Jail list: sshdPerché funziona: prima avvii il servizio, poi controlli se la jail SSH è caricata davvero.
Su RHEL, AlmaLinux e Rocky il comando equivalente usa dnf.
sudo dnf install -y fail2banOra verifica la jail nel dettaglio.
sudo fail2ban-client status sshd# Output:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| `- Total failed: 0
`- Actions
|- Currently banned: 0
`- Total banned: 0Perché funziona: confermi che il filtro monitora i tentativi falliti e che l’azione di ban è attiva.
Note: se non vedi la jail, controlla il backend log. Su systemd recenti spesso conviene backend = systemd.
Simula un errore di login per vedere il ban
ssh baduser@server.example.com# Output:
Permission denied (publickey).Perché funziona: un tentativo fallito reale genera evento nei log e permette a fail2ban di reagire.
Step 5: controlla i permessi file SSH con una scansione mirata
Molti problemi di sicurezza nascono da file troppo aperti. La parte fastidiosa è che SSH li segnala con un errore poco esplicito.
sudo find /home -maxdepth 2 -type d -name .ssh -exec stat -c '%A %U:%G %n' {} \;
sudo find /home -maxdepth 3 -name authorized_keys -exec stat -c '%A %U:%G %n' {} \;# Output:
drwx------ deployops:deployops /home/deployops/.ssh
-rw------- deployops:deployops /home/deployops/.ssh/authorized_keysPerché funziona: i permessi corretti impediscono a SSH di rifiutare la chiave e riducono il rischio di lettura accidentale.
Se trovi deviazioni, correggi in blocco.
sudo chmod 700 /home/deployops/.ssh
sudo chmod 600 /home/deployops/.ssh/authorized_keys
sudo chown -R deployops:deployops /home/deployops/.sshNote: se usi home directory montate via NFS o filesystem con ACL, verifica anche le ACL con getfacl.
Step 6: aggiorna il sistema e verifica che la finestra di manutenzione sia reale
Un server sicuro ma non aggiornato resta esposto. Il controllo post-deploy deve includere patch e reboot pending, soprattutto se hai appena creato l’immagine.
sudo apt-get update
sudo apt-get -s upgrade | sed -n '1,20p'
if [ -f /var/run/reboot-required ]; then echo reboot-required; fi# Output:
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.Perché funziona: il test simulato ti dice se esistono aggiornamenti prima di pianificare la finestra di riavvio.
Su RHEL-like usa:
sudo dnf check-update
sudo needs-restarting -rWarning: se il kernel è stato aggiornato, pianifica il reboot. Non lasciare il server in stato misto per giorni.
Step 7: tratta i segreti come segreti, non come file di progetto
Chiavi API, token e password non devono stare in repository, immagini, backup casuali o variabili esportate senza controllo. Questa verifica è piccola ma molto utile subito dopo il deploy.
sudo grep -RInE '(api[_-]?key|secret|token|password)' /etc /opt/app 2>/dev/null | head -n 20# Output:
/opt/app/.env:3=DATABASE_PASSWORD=***Perché funziona: trovi in fretta segreti lasciati in chiaro nei percorsi più probabili.
Se l’app usa file .env, limita i permessi.
sudo chown root:root /opt/app/.env
sudo chmod 600 /opt/app/.env# Output:
-rw------- 1 root root 412 ... /opt/app/.envPerché funziona: riduci la lettura accidentale da parte di altri utenti o processi non necessari.
Step 8: applica il least privilege anche ai servizi di sistema
La sicurezza non finisce su SSH. Se il servizio applicativo gira come root, stai spostando il problema più avanti. Il controllo post-deploy deve confermare l’utente effettivo del servizio.
systemctl cat app.service
systemctl show app.service -p User -p Group -p NoNewPrivileges -p PrivateTmp# Output:
User=appuser
Group=appuser
NoNewPrivileges=yes
PrivateTmp=yesPerché funziona: separi il processo applicativo dai privilegi di sistema e limiti il danno in caso di compromissione.
Se il servizio non ha utente dedicato, crealo prima di andare in produzione.
sudo useradd --system --home /var/lib/app --shell /usr/sbin/nologin appuserNote: per servizi web o worker, usa account di servizio senza login e con home dedicata.
Verifica finale
Qui serve una conferma rapida, non un report lungo. Esegui questi controlli in sequenza.
- Apri una nuova sessione SSH con chiave.
- Verifica che root non possa entrare via SSH.
- Controlla la jail fail2ban e lo stato dei ban.
- Controlla i permessi di .ssh, authorized_keys e dei file .env.
- Conferma che gli update siano applicati o pianificati.
- Verifica che il servizio applicativo non giri come root.
ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no deployops@server.example.com 'whoami'
sudo fail2ban-client status sshd
sudo sshd -T | egrep 'permitrootlogin|passwordauthentication|pubkeyauthentication'
sudo find /home -maxdepth 3 -name authorized_keys -exec stat -c '%A %U:%G %n' {} \;# Output:
deployops
Status for the jail: sshd
permitrootlogin no
passwordauthentication no
-rw------- deployops:deployops /home/deployops/.ssh/authorized_keysPerché funziona: questa sequenza conferma accesso, protezione, ban e permessi con pochi comandi.
Troubleshooting
1) Permission denied (publickey).
Causa: la chiave è corretta, ma i permessi di .ssh o authorized_keys non lo sono.
Fix:
sudo chmod 700 /home/deployops/.ssh
sudo chmod 600 /home/deployops/.ssh/authorized_keys
sudo chown -R deployops:deployops /home/deployops/.ssh2) sshd: no hostkeys available -- exiting.
Causa: il demone non trova le chiavi host, spesso dopo un hardening troppo aggressivo o un’immagine incompleta.
Fix:
sudo ssh-keygen -A
sudo systemctl restart sshd3) ERROR Failed during configuration: Jail 'sshd' is not defined
Causa: fail2ban è attivo, ma la jail SSH non viene caricata dal file di configurazione corretto.
Fix:
sudo grep -RIn '^[[]sshd[]]' /etc/fail2ban
sudo systemctl restart fail2ban
sudo fail2ban-client statusConclusione
Una buona sicurezza SSH dopo il deploy non richiede cinquanta interventi. Richiede una sequenza corta, testata e con output verificabile.
Se vuoi fare il passo successivo, trasforma questa checklist in uno script di bootstrap idempotente e salvalo nel tuo repository infrastrutturale. Così il controllo resta uguale su ogni nuovo server.
Note: il vero vantaggio non è “blindare tutto”. È sapere esattamente cosa hai cambiato e come tornare indietro senza panico.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.