Come gestire le chiavi SSH correttamente
Guida alla gestione chiavi ed25519, permessi richiesti da sshd, configurazione Host nel file config e procedure per revocare chiavi smarrite su Ubuntu 24.04.
Come funzionano le chiavi SSH
Una chiave SSH è una coppia di file: una chiave privata che rimane sul proprio dispositivo e una chiave pubblica che viene copiata su ogni server a cui si desidera accedere. Durante la connessione, il server utilizza la chiave pubblica per inviare una sfida che solo la chiave privata corrispondente può risolvere. La chiave privata non lascia mai il dispositivo; pertanto, nessun segreto viene trasmesso sulla rete e un server compromesso non ha dati utili da rubare. Per questo motivo le chiavi sono superiori alle password. La corretta gestione delle chiavi SSH si basa su quattro abitudini: una chiave per ogni dispositivo, i permessi dei file richiesti da sshd, un file ~/.ssh/config per evitare di digitare opzioni ogni volta, e la capacità di rimuovere una chiave nel momento in cui un laptop viene smarrito.
Questa guida tratta ogni abitudine su Ubuntu 24.04, sebbene quasi tutto il contenuto sia applicabile a qualsiasi server Linux e a qualsiasi versione recente di OpenSSH.
Un chiarimento terminologico prima di iniziare, per evitare errori critici. La chiave pubblica non è segreta. È possibile incollarla in un ticket, inviarla via email o pubblicarla, e nessuno potrà effettuare l'accesso utilizzando solo quella. La chiave privata è il segreto. Chiunque copi quel file, conoscendone la passphrase (se presente), risulterà essere l'utente legittimo per i server.
Creazione di una chiave: ed25519 è il default corretto
Sul proprio computer, non sul server, eseguire:
ssh-keygen -t ed25519 -C "laptop"-t ed25519 seleziona il tipo di chiave. Ed25519 è il default moderno: le chiavi sono brevi, veloci e supportate da ogni release di OpenSSH dal 2014. Utilizzare ssh-keygen -t rsa -b 4096 solo se necessario per comunicare con dispositivi obsoleti che non supportano ed25519. -C "laptop" imposta un commento. Il commento non ha funzioni crittografiche, ma serve a identificare la chiave nel file authorized_keys del server tra due anni; pertanto, indicare il nome del dispositivo a cui la chiave è associata.
ssh-keygen richiede la posizione di salvataggio della chiave. Accettare il default, ~/.ssh/id_ed25519. Successivamente verrà chiesta una passphrase. Impostarne una; la sezione relativa alla passphrase spiega perché non comporta costi operativi quotidiani. Si otterranno due file: ~/.ssh/id_ed25519 è la chiave privata e ~/.ssh/id_ed25519.pub è la chiave pubblica. Esaminare la parte pubblica:
cat ~/.ssh/id_ed25519.pubssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptopSi tratta di una singola riga: il tipo di chiave, il materiale della chiave e il commento. Quella riga è ciò che verrà copiato sui server.
Una chiave per dispositivo, non una per server
La domanda più comune è: serve una chiave nuova per ogni server? No. Crea una chiave per ogni dispositivo su cui digiti, e inserisci quella chiave pubblica su ogni server a cui il dispositivo deve accedere. La chiave identifica il dispositivo. Il file authorized_keys su ogni server è l'elenco dei dispositivi autorizzati.
Questo è il modello scalabile; le alternative falliscono in modo prevedibile. Una chiave per server implica che un laptop con venti server deve contenere venti chiavi private, rendendo difficile distinguere le chiavi stesse. Una chiave condivisa da tutti i dispositivi è peggiore: se il laptop viene rubato, non puoi revocare l'accesso del laptop senza bloccare anche il desktop, poiché utilizzano la stessa chiave privata. In questo caso, devi sostituire la chiave ovunque e ridistribuirla su ogni dispositivo contemporaneamente.
Con una chiave per dispositivo, la perdita del laptop comporta solo la cancellazione di una riga per server: elimina la riga relativa al laptop da authorized_keys e tutti gli altri dispositivi continueranno a funzionare. Il commento impostato con -C permette di individuare facilmente quella riga.
La regola alla base del modello: una chiave privata viene creata su un dispositivo e termina con quel dispositivo. Non copiare mai una chiave privata su una seconda macchina e non caricarne mai una su un server. Quando un nuovo dispositivo necessita dell'accesso, genera una nuova chiave su di esso.
Inserire la chiave pubblica sul server
Il metodo più semplice è ssh-copy-id, incluso in OpenSSH:
ssh-copy-id matt@10.0.0.10Il comando effettua l'accesso tramite il metodo attualmente attivo, solitamente una password, aggiunge la chiave pubblica a ~/.ssh/authorized_keys sul server e crea la directory e il file con i permessi corretti se non esistono. Verificare il funzionamento aprendo una nuova sessione SSH: il server deve permettere l'accesso senza richiedere la password dell'account. Se la chiave è protetta da passphrase, la macchina locale potrebbe richiedere quella; tale richiesta è locale e non corrisponde alla password del server.
Se l'accesso tramite password è già disabilitato, ssh-copy-id non può connettersi; in questo caso, aggiungere la riga manualmente. Effettuare l'accesso tramite una sessione ancora attiva o tramite la console web del provider, quindi eseguire questo comando sul server:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptop" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keysIncollare la chiave pubblica reale tra le virgolette, ovvero l'intera riga proveniente da id_ed25519.pub. authorized_keys prevede una chiave pubblica per riga; questo file costituisce l'intero database di accesso: aggiungere un dispositivo significa aggiungere una riga, revocare un dispositivo significa eliminarne una. Su un server appena installato, questo passaggio fa parte di i primi 10 minuti su un nuovo VPS, subito prima di disabilitare l'accesso tramite password.
I permessi che impediscono il login tramite chiave
Questo è il motivo più comune per cui il login tramite chiave fallisce; il fallimento avviene in modo silenzioso dal lato client. Su Ubuntu 24.04, sshd viene eseguito con StrictModes yes di default, il che significa che rifiuta l'uso di un file authorized_keys modificabile da altri utenti. Se il file, la directory ~/.ssh o la home directory sono scrivibili da chiunque non sia l'utente stesso, sshd ignora la chiave e richiede la password, senza fornire spiegazioni sul client. (L'OpenSSH di Ubuntu tollera un solo caso specifico: un file scrivibile dal proprio gruppo privato, se nessun altro fa parte di esso. Non fare affidamento su questo comportamento; utilizza i permessi indicati sotto.) Il motivo dell'errore appare solo nei log del server:
sudo grep 'Authentication refused' /var/log/auth.logSu un'immagine minimale senza rsyslog non è presente auth.log; la stessa riga è disponibile nel journal: sudo journalctl -u ssh | grep 'Authentication refused'.
Authentication refused: bad ownership or modes for file /home/matt/.ssh/authorized_keysLa soluzione consiste in due modifiche ai permessi e un controllo della proprietà, da eseguire sul server come l'utente interessato:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R matt:matt ~/.sshLa regola da ricordare: 700 sulla directory .ssh, 600 su tutto il contenuto. Gli stessi permessi si applicano anche al proprio computer, poiché anche il client effettua i controlli. Una chiave privata leggibile da altri utenti causa il rifiuto immediato della chiave da parte di ssh, e in questo caso l'errore viene segnalato esplicitamente:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/matt/.ssh/id_ed25519' are too open.chmod 600 ~/.ssh/id_ed25519 risolve il problema.
~/.ssh/config: evita di digitare le opzioni
Un file ~/.ssh/config sul proprio computer assegna un nome breve a ogni server e memorizza le opzioni utilizzate abitualmente. Crealo con permessi 600 e aggiungi un blocco Host per ogni server:
Host web1
HostName 10.0.0.10
User matt
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host db1
HostName 10.0.0.11
User matt
Port 2222
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yesOra ssh web1 sostituisce ssh -p 22 matt@10.0.0.10. Lo stesso nome breve funziona in scp, rsync e git, poiché tutti leggono questo file. HostName è l'indirizzo reale, User evita di digitare il nome utente e IdentityFile specifica quale chiave utilizzare.
IdentitiesOnly yes richiede una spiegazione, poiché risolve un errore comune. Quando l'agent contiene diverse chiavi, il client le propone una per una e il server conta ogni proposta come un tentativo fallito. Con molte chiavi caricate, si ottiene Received disconnect: Too many authentication failures prima che venga provata la chiave corretta. IdentitiesOnly yes costringe il client a proporre solo la chiave indicata in IdentityFile, evitando così l'errore.
Passphrase e ssh-agent
Una passphrase cripta il file della chiave privata su disco. Senza passphrase, chiunque copi il file può usarlo immediatamente; con una passphrase, il file rubato è inutile finché la passphrase non viene indovinata. Per una chiave su un laptop, questo è il livello di protezione necessario, poiché i laptop possono essere rubati e i relativi backup possono essere compromessi.
La passphrase non ha costi prestazionali in pratica a causa di ssh-agent. L'agent mantiene la chiave decriptata in memoria; pertanto, è necessario digitare la passphrase una sola volta per sessione di login e ogni connessione successiva sarà istantanea. La maggior parte delle distribuzioni Linux desktop e macOS esegue già un agent in background. Carica la tua chiave nell'agent con:
ssh-add ~/.ssh/id_ed25519ssh-add -l elenca le chiavi attualmente detenute dall'agent. Una precauzione: l'agent forwarding (ssh -A) permette al server remoto di utilizzare il tuo agent per autenticarsi verso altri host mentre sei connesso. Abilitalo solo verso server di cui ti fidi completamente e mantienilo disabilitato di default.
Rotazione e revoca: l'esercitazione per il laptop smarrito
Rovocare una semplice chiave SSH consiste nel rimuovere la relativa riga da authorized_keys su ogni server che la contiene. Non è necessario notificare alcuna Certificate Authority e non bisogna attendere una data di scadenza. Una volta rimossa la riga, i nuovi login con quella chiave falliscono.
Esegui l'esercitazione ora, prima che diventi un'emergenza. Scegli un server, apri ~/.ssh/authorized_keys e individua la chiave tramite il suo commento. Elimina la riga con un editor oppure filtrala tramite commento:
grep -v ' laptop$' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keysVerifica quindi dal dispositivo appena revocato che il login fallisca, e da un altro dispositivo che il login funzioni ancora. Nota un dettaglio: la rimozione di una chiave non chiude le sessioni già aperte, poiché la chiave viene controllata solo durante il login. Se stai revocando un dispositivo rubato, controlla anche who sul server e termina ogni sessione non riconosciuta.
La rotazione è la stessa operazione con un ordine differente: genera una nuova chiave sul dispositivo, installala con ssh-copy-id, conferma che la nuova chiave permetta il login e infine elimina la vecchia riga. Esegui questa procedura quando un dispositivo cambia proprietario, quando una chiave potrebbe essere stata esposta o quando un membro del team lascia il gruppo. Gestire l'operazione manualmente su due server è fattibile; su venti è necessario l'uso dell'automazione, e managing multiple Linux servers spiega come applicare lo stesso stato authorized_keys a un'intera flotta.
Cosa non fare
- Non utilizzare la stessa chiave privata su tutti i dispositivi. Se un dispositivo viene rubato, non sarà possibile revocare solo quella chiave senza doverla sostituire ovunque.
- Non caricare una chiave privata in un repository git, nemmeno se privato. Gli scanner automatizzati monitorano i repository pubblici e testano le chiavi trapelate pochi minuti dopo il push; inoltre, se un repository diventa pubblico in seguito, ne viene esposta l'intera cronologia.
- Non caricare la chiave privata del laptop su un server per permettere a quel server di connettersi a un altro server. Genera una chiave separata direttamente sul server e autorizza tale chiave solo dove è strettamente necessario.
- Non incollare una chiave privata in chat, email o ticket. La chiave pubblica, il file
.pub, è l'unica parte che deve essere condivisa.
Una volta che la chiave garantisce un accesso affidabile, disabilita l'autenticazione tramite password. Questo impedisce che i tentativi continui di brute-force sul server abbiano successo. La configurazione pronta all'uso è disponibile in SSH hardening on a VPS.
FAQ
Come funzionano le chiavi SSH senza inviare una password?
Il server memorizza la tua chiave pubblica in ~/.ssh/authorized_keys. Durante il login, il server invia una sfida; il client firma la sfida con la chiave privata e il server verifica la firma con la chiave pubblica. La chiave privata non lascia mai il tuo dispositivo, quindi non c'è nulla da intercettare durante il transito e nulla di riutilizzabile da rubare dal server. Un server compromesso espone solo le chiavi pubbliche, che non possono essere utilizzate per effettuare l'accesso altrove.
Devo usare la stessa chiave SSH per tutti i miei server?
Usare una chiave per più server è corretto, purché la chiave rimanga su un singolo dispositivo. La regola è una chiave per dispositivo, non una per server: la chiave pubblica del laptop va su ogni server a cui il laptop deve accedere, mentre il desktop deve avere la propria chiave. Questo semplifica la revoca, poiché la perdita di un dispositivo richiede solo la rimozione di una riga identificabile da ogni server, mentre gli altri dispositivi continuano a funzionare.
Quali permessi devono avere la directory .ssh e il file authorized_keys?
Imposta 700 su ~/.ssh e 600 su authorized_keys e su ogni chiave privata, con proprietà dell'account che le utilizza. sshd viene eseguito con StrictModes yes per impostazione predefinita; se un file o una home directory sono scrivibili da chiunque non sia l'utente, sshd ignorerà silenziosamente la chiave. L'unico segno sarà Authentication refused: bad ownership or modes nei log di autenticazione o nel journal del server.
Come posso rimuovere una chiave SSH da un server?
Elimina la riga della chiave da ~/.ssh/authorized_keys nell'account per cui era autorizzata. Individua la riga corretta tramite il commento, ovvero l'etichetta situata dopo il blocco della chiave. I nuovi login con quella chiave falliranno immediatamente, ma le sessioni già aperte rimarranno attive; termina anche ogni sessione attiva per quel dispositivo se è stato rubato. Ripeti l'operazione su ogni server su cui la chiave è stata copiata.
Devo usare una passphrase sulla mia chiave SSH?
Per una chiave su un laptop o un desktop, sì. La passphrase cripta il file della chiave, rendendo inutile una copia rubata o trapelata. L'uso di ssh-agent permette di digitare la passphrase una sola volta per sessione invece che per ogni connessione. Le chiavi utilizzate per l'automazione non assistita su un server solitamente non hanno una passphrase, poiché non è presente alcun operatore per digitarla; proteggi queste chiavi limitando i privilegi dell'account di destinazione.