Dopo un deploy, SSH è il primo punto che va verificato. Se un errore di permessi o una regola troppo larga passa inosservato, il server resta esposto anche quando l’app funziona.
Qui trovi una mini checklist post-deploy pensata per un caso concreto: hai appena pubblicato una nuova macchina Linux, magari su VPS o cloud, e vuoi controllare che l’accesso remoto sia davvero ridotto al minimo. Il focus è su hardening SSH, fail2ban, permessi file, aggiornamenti, segreti e least privilege.
Warning: esegui questi passi con una sessione SSH già aperta e una console di emergenza disponibile. Un errore su sshd o firewall può tagliarti fuori.
Prerequisiti
Serve accesso root o sudo. I comandi qui sotto assumono Debian, Ubuntu o derivate. Su altre distro cambiano soprattutto i percorsi dei servizi e il gestore aggiornamenti.
- Accesso root o utente con sudo.
- Una chiave SSH già configurata per l’accesso amministrativo.
- fail2ban installato o installabile dal repository di sistema.
- UFW, nftables o un firewall equivalente.
- Un editor testuale per controllare configurazioni e permessi.
Note: alcuni controlli sono solo da riga di comando. Se usi un pannello come Plesk, cPanel o Webmin, la parte di firewall o servizi può essere visibile da interfaccia, ma SSH e permessi file restano quasi sempre più affidabili da terminale.
Step numerati
1. Verifica che SSH accetti solo chiavi, non password
Questo è il primo filtro. Se la password resta attiva, un brute force ha ancora senso. La verifica va fatta sul file di configurazione e sul servizio attivo, non solo a memoria.
Controlla le opzioni effettive di sshd e cerca l’uso di chiavi pubbliche.
sudo sshd -T | egrep 'passwordauthentication|pubkeyauthentication|permitrootlogin|kbdinteractiveauthentication'
# Output:
# passwordauthentication no
# pubkeyauthentication yes
# permitrootlogin prohibit-password
# kbdinteractiveauthentication noSe il server è gestito da pannello, cerca la sezione SSH o sicurezza del sistema. In Plesk, ad esempio, vai in Strumenti e impostazioni → Accesso SSH. Se il pannello non espone il dettaglio, conferma dal terminale.
Se il valore non è corretto, modifica /etc/ssh/sshd_config e ricarica il servizio.
sudoedit /etc/ssh/sshd_config
sudo systemctl reload ssh
# Output:
# Reloaded ssh.serviceWarning: prima di disattivare la password, apri una seconda sessione e verifica che la chiave funzioni davvero.
2. Limita root e riduci il privilegio iniziale
Il principio è semplice: l’utente amministrativo non deve essere root diretto, se puoi evitarlo. Anche quando root è disabilitato via SSH, il server resta gestibile con sudo.
Verifica il login root e l’elenco degli utenti con privilegi elevati.
getent group sudo
getent group wheel
sudo sshd -T | grep permitrootlogin
# Output:
# sudo:x:1001:adminops
# permitrootlogin prohibit-passwordSe usi un pannello, controlla la creazione utenti da Server → Utenti o Amministrazione. L’obiettivo è avere un account nominativo, non un accesso condiviso.
Per vedere chi ha sudo davvero, usa:
sudo -l -U adminops
# Output:
# User adminops may run the following commands on host:
# (ALL : ALL) ALLNote: se il tuo team usa account condivisi, il problema non è solo tecnico. È anche di audit e responsabilità.
3. Controlla i permessi della chiave e della home
Molti accessi falliscono, o peggio si aprono male, per permessi troppo larghi su .ssh. La verifica è veloce e deve diventare automatica dopo ogni deploy.
namei -l /home/adminops/.ssh/authorized_keys
ls -ld /home/adminops /home/adminops/.ssh
ls -l /home/adminops/.ssh/authorized_keys
# Output:
# drwxr-x--- adminops adminops /home/adminops
# drwx------ adminops adminops /home/adminops/.ssh
# -rw------- adminops adminops /home/adminops/.ssh/authorized_keysLa home non deve essere scrivibile da altri. La directory .ssh deve stare a 700. Il file authorized_keys a 600.
Se trovi valori sbagliati, correggili così:
chmod 700 /home/adminops/.ssh
chmod 600 /home/adminops/.ssh/authorized_keys
chown -R adminops:adminops /home/adminops/.ssh
# Output:
# permissions correctedWarning: non rendere mai authorized_keys leggibile da gruppo o altri. Alcune configurazioni sshd lo rifiutano in modo silenzioso.
4. Verifica fail2ban sul solo servizio SSH
fail2ban serve a bloccare tentativi ripetuti, ma ha senso solo se la jail SSH è attiva e sta davvero bannando. Dopo un deploy, controlla sia lo stato sia il log degli ultimi eventi.
sudo fail2ban-client status
sudo fail2ban-client status sshd
# Output:
# Status for the jail: sshd
# |- Filter
# | |- Currently failed: 0
# | |- Total failed: 3
# | `- File list: /var/log/auth.log
# `- Actions
# |- Currently banned: 1
# `- Total banned: 1Se amministri via GUI, alcuni pannelli di sicurezza mostrano il ban, ma non sempre il motivo. Il comando resta il controllo più affidabile.
Per una verifica pratica, puoi testare la risposta ai fallimenti da un IP di test, senza esagerare con i tentativi.
sudo tail -f /var/log/fail2ban.log
# Output:
# NOTICE [sshd] Ban 203.0.113.45Note: se usi un IP dinamico o una VPN condivisa, alza con cautela i tempi di ban. Un tempo troppo lungo blocca anche il tuo team.
5. Controlla aggiornamenti di sicurezza e reboot necessario
La macchina è davvero pronta solo se ha ricevuto gli aggiornamenti critici e, quando serve, un riavvio pianificato. Lasciare kernel o OpenSSH vecchi è un rischio inutile.
apt list --upgradable 2>/dev/null | head
needrestart -b
# Output:
# The system requires a reboot to apply updates: yesSu sistemi con interfaccia, vai in Aggiornamenti o Software e cerca i pacchetti di sicurezza. Se la macchina è in produzione, pianifica il reboot in finestra controllata.
Per Ubuntu e Debian, una verifica utile è anche questa:
uname -r
ssh -V
# Output:
# Linux 6.1.0-28-amd64
# OpenSSH_9.2p1 Debian-2+deb12u4Confronta la versione installata con gli avvisi del vendor. Se c’è un CVE noto, il deploy non è chiuso finché non applichi la patch.
6. Cerca segreti lasciati nei file di deploy
Il problema non è solo SSH. Spesso il deploy lascia token, password o API key in file di ambiente, backup temporanei o log. La ricerca va fatta subito, prima che i permessi sbagliati diventino una fuga di dati.
sudo grep -RIn --exclude-dir=.git --exclude='*.log' -E 'API_KEY|SECRET|TOKEN|PASSWORD' /var/www /etc /opt 2>/dev/null | head -20
# Output:
# /var/www/app/.env:3:APP_SECRET=...
# /var/www/app/.env:7:DB_PASSWORD=...Se il progetto usa pannelli o deploy automatici, controlla anche le directory di staging e i backup del pannello. Un file .env in una cartella web pubblica è un errore classico.
La correzione minima è spostare i segreti fuori dal document root e restringere i permessi.
chmod 600 /var/www/app/.env
chown root:www-data /var/www/app/.env
# Output:
# secret file locked downWarning: se il web server deve leggere il file, usa un gruppo dedicato e non chmod 644. Leggibile da tutti non è una scorciatoia accettabile.
7. Conferma il least privilege sui servizi
Il deploy è più sicuro quando ogni servizio fa solo ciò che deve. Se l’app gira come root, o se un worker può leggere chiavi private inutili, il danno aumenta molto.
Controlla l’utente del servizio systemd e i file accessibili dal processo.
systemctl cat app.service | sed -n '1,80p'
systemctl show -p User -p Group app.service
# Output:
# User=www-data
# Group=www-dataSe usi un pannello, vai nella sezione PHP-FPM o servizio applicativo e verifica il pool dedicato. Ogni sito dovrebbe avere un utente separato, non un account globale per tutto il server.
Un controllo rapido dei processi aiuta a scoprire eccessi evidenti.
ps -eo user,group,comm --sort=user | head -20
# Output:
# root root systemd
# www-data www-data php-fpm8.2
# appuser appuser node
Note: se un demone non può abbassare i privilegi, va rivisto il design, non solo la configurazione.
Verifica finale
Questa è la checklist finale da chiudere in ordine. Se un punto fallisce, non considerare il deploy completo.
- SSH accetta chiavi e non password.
- Root via SSH è vietato o limitato.
~/.ssheauthorized_keyshanno permessi corretti.- fail2ban vede la jail
sshde registra ban reali. - Gli aggiornamenti di sicurezza sono applicati.
- Nessun segreto sensibile resta in percorsi pubblici o condivisi.
- Ogni servizio gira con l’utente minimo necessario.
Una verifica pratica utile è fare un login reale da una seconda macchina e controllare i log subito dopo.
sudo journalctl -u ssh -n 20 --no-pager
# Output:
# Accepted publickey for adminops from 198.51.100.20 port 51422 ssh2Troubleshooting
1. Authentication refused: bad ownership or modes for directory /home/adminops
Causa: la home o una directory padre è scrivibile da altri, e sshd blocca la chiave.
Fix: correggi proprietà e permessi lungo il percorso.
sudo chown adminops:adminops /home/adminops
sudo chmod 750 /home/adminops
sudo chmod 700 /home/adminops/.ssh
sudo chmod 600 /home/adminops/.ssh/authorized_keys
# Output:
# fixed ownership and modes2. Failed to start ssh.service: Unit ssh.service not found.
Causa: sulla distribuzione il servizio si chiama sshd, non ssh, oppure OpenSSH server non è installato.
Fix: verifica il nome del servizio e il pacchetto.
systemctl status sshd
sudo apt install openssh-server
sudo systemctl enable --now ssh
# Output:
# ssh service active3. NOTICE [sshd] Ban 127.0.0.1 seguito da lockout del tuo IP
Causa: fail2ban ha bannato un indirizzo usato anche dal tuo accesso amministrativo o da una VPN condivisa.
Fix: escludi l’IP fidato e sblocca manualmente solo quel ban.
sudo fail2ban-client set sshd unbanip 203.0.113.45
sudoedit /etc/fail2ban/jail.d/sshd.local
# aggiungi ignoreip = 127.0.0.1/8 203.0.113.45
sudo systemctl restart fail2ban
# Output:
# sshd jail restartedConclusione
Una macchina è davvero pronta solo quando accesso, log, permessi e segreti tornano tutti sotto controllo. La sicurezza post-deploy non è un blocco unico, ma una serie di controlli brevi e ripetibili.
Il prossimo passo concreto è trasformare questa checklist in uno script di audit o in una runbook interna. Così ogni nuovo server passa gli stessi controlli, senza affidarsi alla memoria di chi lo ha configurato.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.