Vai al contenuto
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

Chiavi SSH: come funzionano e come usarle in sicurezza

Come funzionano le chiavi host e utente di SSH, perché la scelta predefinita è Ed25519 con passphrase e come impostare un accesso con chiave e fare hardening su una VM di laboratorio tua.

Base11 min di letturaDi NotHoly

Che cosa protegge SSH

SSH (Secure Shell) è il protocollo che la maggior parte delle persone usa per accedere a server Linux, macchine virtuali di laboratorio e host Git. Apre una shell su un canale cifrato, e lo stesso canale può copiare file o inoltrare porte. Ha tre compiti. Cifra il traffico, così nessuno sul percorso di rete può leggerlo. Dimostra al server chi sei. Dimostra a te chi è il server.

Le chiavi svolgono il secondo compito senza inviare una password sulla rete. Una password si può indovinare o rubare con il phishing. Una coppia di chiavi funziona in modo diverso. Il server conserva solo la metà pubblica. Per accedere, il tuo client firma un challenge con la metà privata e il server controlla la firma. La chiave privata non lascia mai la tua macchina.

In alcuni casi SSH non ti protegge, e quei casi contano quanto il protocollo. Se il tuo computer è compromesso, un malware eseguito con il tuo utente può leggere il file della chiave privata o chiedere al tuo agent di firmare. Se la chiave privata viene rubata e la passphrase è debole, un attaccante può provare a indovinarla offline. Se accetti l'identità di un server senza controllarla, potresti parlare con qualcuno che non è affatto il server.

Due tipi di chiavi

SSH usa due tipi diversi di chiavi, e capita spesso di confonderli.

Le chiavi host identificano il server. Ogni server SSH ne ha una o più, di solito in /etc/ssh/ssh_host_*_key. La parte privata resta sul server. La parte pubblica viene presentata a ogni client che si collega. La prima volta che la vede, il client la salva in known_hosts. Nelle connessioni successive, una chiave host cambiata fa scattare un avviso.

Le chiavi utente identificano te. Generi la coppia sulla tua macchina. La chiave privata resta con te. La chiave pubblica va sul server, in ~/.ssh/authorized_keys per l'account che vuoi usare.

La differenza ha conseguenze pratiche. Copiare la tua chiave privata su un server dà a quel server, e a chiunque possa leggerla, il materiale per agire come te ovunque la chiave sia accettata. Ignorare un avviso sulla chiave host significa che potresti inviare la password o i comandi a un impostore.

Perché Ed25519 con passphrase

OpenSSH gestisce diversi tipi di chiave. RSA funziona ancora, ma le nuove chiavi RSA dovrebbero avere almeno 3072 bit, e le righe della chiave pubblica diventano lunghe. Le chiavi Ed25519 sono corte, veloci da verificare e standardizzate per SSH nella RFC 8709. OpenSSH 9.5 e versioni successive usano Ed25519 come tipo predefinito di ssh-keygen. Ed25519 è la scelta predefinita giusta per una chiave di laboratorio, a meno che un sistema che devi raggiungere accetti solo un tipo più vecchio.

Una passphrase cifra il file della chiave privata sul disco. Senza passphrase, chiunque copi il file può usare la chiave. Se la imposti, servono il file e la passphrase. Questo protegge dagli incidenti più comuni: un backup finito nel posto sbagliato, una chiave lasciata in una cartella condivisa, un file sincronizzato per errore su un cloud drive. La passphrase non serve più una volta che la chiave è caricata in un agent e un malware gira con il tuo utente. Usa una passphrase lunga, salvala in un password manager e conserva un backup del file della chiave in un posto sicuro.

Come funziona una connessione

La RFC 4253 descrive il livello di trasporto. A grandi linee, una connessione passa da queste fasi:

  1. Il tuo client apre una connessione TCP verso il server, di solito sulla porta 22.
  2. Entrambe le parti inviano gli algoritmi che gestiscono e si accordano su uno scambio di chiavi. Lo scambio produce segreti condivisi, e da quel momento tutto il traffico è cifrato.
  3. Il server invia la sua chiave host e una firma sullo scambio. Il tuo client confronta quella chiave host con known_hosts. Se l'host è nuovo, il client mostra il fingerprint e ti chiede di confermarlo.
  4. Ti autentichi. Il client propone una chiave pubblica. Se il server la trova in authorized_keys, invia un challenge. Il tuo client firma il challenge con la chiave privata e il server controlla la firma.

Nota da dove viene la fiducia. Il passo 3 riguarda il server. Il passo 4 riguarda te. Se salti il controllo del fingerprint al passo 3, il resto dell'handshake funziona a vantaggio di chiunque abbia risposto.

Fingerprint

Un fingerprint è un hash breve di una chiave pubblica. OpenSSH mostra per impostazione predefinita fingerprint SHA256. Due persone possono confrontare un fingerprint per confermare di avere la stessa chiave pubblica, senza leggere ad alta voce la chiave intera.

I comandi qui sotto sono stati eseguiti su una macchina Windows 11 con OpenSSH 9.9p2 (ssh -V), in Git Bash. La chiave era una copia temporanea creata per questa prova, con passphrase vuota, così da poter mostrare qui l'output. La tua chiave reale avrà un fingerprint diverso.

bash
ssh-keygen -t ed25519 -C 'lab-key' -f ./lab_ed25519 -N ''
ssh-keygen -lf ./lab_ed25519.pub

Output osservato:

text
256 SHA256:2BAyZTrHADdiG1FNwfCwb/fC5vSVZPwfGnZjRaaExc4 lab-key (ED25519)

ssh-keygen -lvf stampa lo stesso fingerprint con un disegno random-art. Il disegno rende più facile accorgersi di un cambiamento, ma quello che devi confrontare è il testo del fingerprint.

Laboratorio pratico

Ti serve una macchina virtuale o un'istanza cloud che possiedi e controlli, con un server OpenSSH attivo e un account che può usare sudo. Va bene una VM locale in VirtualBox o Hyper-V. Va bene anche una piccola istanza cloud che paghi e puoi cancellare. Non eseguire questi passi su una macchina che appartiene a qualcun altro.

Passo 1: genera la chiave

bash
ssh-keygen -t ed25519 -C 'lab-key' -f ~/.ssh/lab_ed25519

Quando ti viene chiesto, inserisci una passphrase lunga. Il comando crea due file: lab_ed25519 (privato) e lab_ed25519.pub (pubblico). Solo il file .pub è fatto per uscire dalla tua macchina.

Passo 2: controlla il fingerprint

bash
ssh-keygen -lf ~/.ssh/lab_ed25519.pub

Annota questo fingerprint, o almeno i primi caratteri. Lo confronterai di nuovo più avanti.

Passo 3: proteggi il file della chiave privata

bash
chmod 600 ~/.ssh/lab_ed25519

Su Linux e macOS, ssh rifiuta una chiave privata leggibile da altri utenti. Su Windows, OpenSSH controlla le ACL del file invece dei bit di modalità Unix. Su questa macchina Windows, chmod 600 è stato eseguito senza errori, ma dopo ls -l mostrava ancora -rw-r--r--. Non dare per scontato che lì i bit siano cambiati. Se ssh si lamenta dei permessi su Windows, controlla il file con icacls e togli l'accesso agli altri account.

Passo 4: installa la chiave pubblica sulla VM

bash
ssh-copy-id -i ~/.ssh/lab_ed25519.pub youruser@your-lab-vm

Questa è l'unica volta in cui digiti di proposito la password dell'account. Il comando aggiunge la chiave pubblica a ~/.ssh/authorized_keys sulla VM.

La prima connessione alla VM ti mostra anche il fingerprint di una chiave host. Confrontalo con quello reale. Sulla VM, esegui:

bash
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

Se i due fingerprint coincidono, digita yes. Se non coincidono, fermati. Scopri il motivo prima di continuare. Una differenza può significare che hai reinstallato la VM, o che qualcuno si è messo tra te e la VM.

Questo passo non è stato eseguito qui, perché su questa macchina non c'era una VM disponibile. Per questo i comandi dei passi da 4 a 6 sono riportati senza output. Puoi controllarli uno per uno sulla tua VM.

Passo 5: accedi con la chiave

bash
ssh -i ~/.ssh/lab_ed25519 youruser@your-lab-vm

Il client ti chiede la passphrase della chiave, e non la password dell'account. Se ottieni una shell, la chiave funziona. Tieni aperta questa sessione per il passo successivo.

Passo 6: disattiva l'accesso con password

Sulla VM:

bash
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl restart ssh

La riga sed sostituisce la riga PasswordAuthentication, che sia commentata o no. sshd -t controlla la sintassi della configurazione e interrompe la catena se fallisce. systemctl restart ssh applica la modifica. Su Fedora e sugli altri sistemi della famiglia RHEL il servizio si chiama sshd, quindi usa quel nome.

Tre cose vanno storte spesso a questo punto:

  • La riga viene sovrascritta. Su molti sistemi Debian e Ubuntu, /etc/ssh/sshd_config include file da /etc/ssh/sshd_config.d/, e vince il primo valore letto per una parola chiave. Controlla il valore che sshd usa davvero:
bash
sudo sshd -T | grep -i '^passwordauthentication'

Dopo la modifica, l'output dovrebbe essere passwordauthentication no. Se dice ancora yes, trova il file che lo imposta e correggilo lì.

  • La riga non c'è. sed modifica solo una riga che esiste. Se non c'è alcuna riga PasswordAuthentication, si applica il valore predefinito, e la pagina man sshd_config(5) dice che è yes. Aggiungi tu la riga:
bash
echo 'PasswordAuthentication no' | sudo tee -a /etc/ssh/sshd_config
  • Resti chiuso fuori. Prima di chiudere la sessione usata al passo 5, apri un secondo terminale e accedi con la chiave. Chiudi il primo terminale solo dopo che il secondo funziona. Se perdi l'accesso, usa la console della VM dall'hypervisor o dalla dashboard del cloud per sistemare la configurazione.

Poi verifica dalla tua macchina che l'accesso con password venga rifiutato:

bash
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password youruser@your-lab-vm

La connessione dovrebbe fallire con un messaggio di permesso negato. Fai tu questa verifica sulla VM che possiedi. Su questa macchina non è stata eseguita.

L'agent e known_hosts

ssh-agent

Digitare la passphrase a ogni connessione alla lunga stanca. ssh-agent tiene in memoria la chiave decifrata per la durata della sessione, così digiti la passphrase una volta sola.

bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/lab_ed25519
ssh-add -l

ssh-add -l elenca i fingerprint che l'agent ha in memoria. Su questa macchina Windows, ssh-add -l è stato eseguito senza un agent attivo e ha stampato Could not open a connection to your authentication agent. con codice di uscita 2. Windows usa per questo il servizio OpenSSH Authentication Agent. Avvia quel servizio dalla console Servizi o da una PowerShell di amministratore. È una modifica al tuo sistema, quindi falla tu e solo se vuoi che l'agent sia attivo.

Un agent è comodo, ed è anche un bersaglio. Chiunque possa parlare con il socket dell'agent mentre sei connesso può chiedergli di firmare. Per questo evita l'inoltro dell'agent (ssh -A) verso host di cui non ti fidi del tutto. Un utente root sull'host remoto può usare il tuo agent inoltrato. Se devi raggiungere un host privato tramite un bastion, usa invece un jump host:

bash
ssh -J youruser@bastion youruser@private-vm

known_hosts

Il client conserva le chiavi host in ~/.ssh/known_hosts, una riga per host e tipo di chiave. Se imposti HashKnownHosts yes, le righe vengono salvate come hash, così chi legge il file non vede i nomi degli host.

Per cercare un host:

bash
ssh-keygen -F your-lab-vm

Per rimuovere una voce dopo aver ricostruito una VM e ottenuto una nuova chiave host:

bash
ssh-keygen -R your-lab-vm

Fallo solo quando sai perché la chiave è cambiata. Una chiave host cambiata è un avvertimento, e non un fastidio da togliere di mezzo. Se rimuovi la vecchia voce senza controllare il nuovo fingerprint, ti abitui a ignorare il prossimo avviso, e il prossimo potrebbe essere vero.

Punti da ricordare

  • Non condividere mai la chiave privata. Solo il file .pub va sui server, sugli host Git o ad altre persone.
  • Proteggi la chiave privata con una passphrase e conserva un backup del file.
  • Verifica il fingerprint dell'host alla prima connessione e indaga su qualsiasi cambiamento successivo.

Errori comuni

  • Incollare la chiave privata in una chat, un issue, un ticket o uno screenshot. Trattala come una password che non si può reimpostare. Se trapela, genera una nuova chiave, installala e rimuovi la vecchia chiave pubblica da authorized_keys.
  • Installare sul server la chiave privata invece di quella pubblica. Al server serve solo la riga .pub in authorized_keys.
  • Permessi sul server. Su Linux, ~/.ssh dovrebbe essere 700 e authorized_keys dovrebbe essere 600. Modalità più permissive possono far ignorare la chiave a sshd. Controlla i log di sshd quando un accesso con chiave fallisce.
  • Disattivare le password prima che l'accesso con chiave funzioni. È il modo più comune per restare chiusi fuori. Segui l'ordine del passo 6.
  • Una sola chiave per tutto. Riusare una chiave su VM di laboratorio, host Git e sistemi di produzione significa che una sola fuga apre tutto. Usa chiavi separate per scopo, come lab_ed25519 per il laboratorio e un'altra chiave per GitHub.
  • Accettare una chiave host sconosciuta senza controllarla. La prima connessione è il momento in cui è più probabile che si infili un impostore. Confronta il fingerprint prima di digitare yes.
  • Perdere la passphrase. Non c'è modo di recuperarla. Salvala in un password manager.
  • Righe duplicate in authorized_keys. Eseguire ssh-copy-id due volte non fa danni, ma aggiungere una chiave a mano più volte rende il file più difficile da controllare. Rimuovi le chiavi che non usi più.

Come andare oltre

Quando il laboratorio funziona, qualche passo rende l'uso quotidiano più sicuro e ordinato.

  • Impostazioni per host in ~/.ssh/config. Dai un alias a ogni host, imposta IdentityFile e aggiungi IdentitiesOnly yes, così il client propone solo la chiave che hai scelto. In questo modo il client non prova contro un server tutte le chiavi del tuo agent.
  • Chiavi di sicurezza. OpenSSH può creare chiavi conservate su una chiave di sicurezza hardware, usando ssh-keygen -t ed25519-sk. In questo caso la parte privata non si può copiare fuori dal dispositivo. Controlla la versione di OpenSSH e il supporto della tua chiave prima di farci affidamento.
  • Certificati SSH. Le organizzazioni con molti server usano spesso un'autorità di certificazione invece di distribuire chiavi su ogni host. Vale la pena imparare il concetto anche se per ora non ti serve.
  • Leggi i documenti originali. Le pagine man di ssh-keygen e sshd_config descrivono tutte le opzioni che incontrerai. La RFC 4253 spiega il livello di trasporto, e la RFC 8709 tratta Ed25519 in SSH.

Se modalità dei file e proprietà ti sono ancora nuove, leggi prima l'articolo precedente su file e permessi su Linux. Il prossimo articolo tratta le reti Docker isolate per i laboratori, che puoi usare per tenere il traffico del laboratorio lontano dalla tua rete di tutti i giorni.

Fonti

Fonti

  1. OpenBSD manual: ssh-keygen(1)
  2. OpenBSD manual: sshd_config(5)
  3. OpenSSH 9.5 release notes
  4. RFC 4253: The Secure Shell (SSH) Transport Layer Protocol
  5. RFC 8709: Ed25519 and Ed448 Public Key Algorithms for SSH

Altro su Linux e strumenti per sviluppatori

Linux e strumenti per sviluppatori

Basi di Bash per il lavoro di sicurezza

Impara pipe, redirezioni, variabili, loop, codici di uscita e set -euo pipefail, poi usali per contare gli accessi falliti e calcolare l'hash di una cartella.

Base13 min di lettura

Linux e strumenti per sviluppatori

Permessi Linux: utenti, gruppi, chmod e umask

Proprietari e gruppi Linux, bit rwx, chmod, umask e setuid, con un lab che prova l'accesso come secondo utente e trova i permessi rischiosi sui file.

Base13 min di lettura