Da tempo non accedevo via ssh ad un server di un mio cliente, è successo questo:
$ ssh user@myhost.com Unable to negotiate with <some IP adddress> port 22: no matching key exchange method found. Their offer: diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
Il problema si chiama key exchange method, metodo di scambio delle chiavi. Ho controllato quali erano i metodi disponibili in locale con:
$ ssh -Q kex diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group14-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 curve25519-sha256 curve25519-sha256@libssh.org
Mi pare ce ne siano parecchi. Ne scelgo uno:
$ ssh -oKexAlgorithms=diffie-hellman-group1-sha1 user@myhost.com Unable to negotiate with <some IP adddress> port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss
Il problema si sposta, adesso si chiama host key type (tipo di chiave host), allora aggiungo anche l’altro parametro:
$ ssh -oKexAlgorithms=diffie-hellman-group1-sha1 -oHostKeyAlgorithms=ssh-rsa user@myhost.com The authenticity of host 'myhost.com (<some IP adddress>)' can't be established. RSA key fingerprint is SHA256:QrIQ15WsEr48UvcEE9cLJhoj7ilRCTL3ghaRMYI2Ewg. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'myhost.com' (RSA) to the list of known hosts. user@myhost.com's password: Last login: Tue Jan 9 11:54:48 2024 from <some other IP address> -bash-3.2$
L’ultimo problema (server authenticity) era la firma RSA dell’host che non era tra i miei host conosciuti (con questo PC in effetti era la prima volta che mi connettevo).
Sommario
Cos’è successo al mio client SSH?
Al client SSH ovviamente non è successo nulla: i tre problemi sono di natura diversa. L’ultimo (il problema della firma o fingerprint) l’ho già spiegato.
Vediamo cosa sono gli altri due.
I parametri HostKeyAlgorithms
e KexAlgorithms
sono entrambi utilizzati per specificare gli algoritmi crittografici utilizzati durante la fase di negoziazione di una connessione SSH. Tuttavia, hanno scopi leggermente diversi:
- HostKeyAlgorithms:
Questo parametro specifica gli algoritmi utilizzati per generare e verificare le chiavi pubbliche degli host. Quando un client si connette a un server SSH per la prima volta, il server invia la sua chiave pubblica al client. Il client verifica quindi questa chiave pubblica confrontandola con una copia locale. Se le chiavi pubbliche non corrispondono, potrebbe esserci un attacco man-in-the-middle in corso. Gli algoritmi elencati inHostKeyAlgorithms
specificano quali algoritmi il client accetterà per la chiave pubblica del server. - KexAlgorithms:
Questo parametro specifica gli algoritmi utilizzati per lo scambio delle chiavi segrete durante la fase di negoziazione della chiave di sessione. Questa fase è cruciale per garantire che le comunicazioni tra client e server siano protette da crittografia. Gli algoritmi elencati inKexAlgorithms
specificano quali algoritmi il client è disposto ad utilizzare per lo scambio delle chiavi durante la connessione SSH.
Entrambi i parametri sono importanti per garantire la sicurezza e la compatibilità delle connessioni SSH. È possibile configurarli in modo da includere solo gli algoritmi più sicuri e recenti supportati da entrambe le parti, evitando quelli considerati obsoleti o vulnerabili. Tuttavia, è importante anche assicurarsi che l’algoritmo specificato sia supportato sia dal client che dal server per evitare errori di compatibilità, come quelli che ho riscontrato.
È infatti importante che il client e il server abbiano almeno un algoritmo in comune per poter stabilire una connessione sicura.
Da quanto detto è chiaro che esistono due fasi nella transazione:
- l’invio della chiave pubblica dell’host
- lo scambio di una chiave segreta per cifrare la sessione
Vediamo con un po’ più di dettaglio la fase di negoziazione.
Come si stabilisce una connessione sicura tra client e server con SSH
Una connessione SSH (Secure Shell) coinvolge diverse fasi per stabilire una comunicazione sicura e autenticata tra un client e un server remoto. Ecco le fasi principali di una connessione SSH:
- Inizializzazione della connessione: Il client SSH inizia la connessione al server SSH specificando l’host a cui desidera connettersi e autenticandosi, se necessario.
- Negoziazione delle chiavi crittografiche: Il client e il server SSH si scambiano informazioni sulle chiavi crittografiche supportate e selezionano una chiave per la sessione corrente.
- Scambio delle chiavi pubbliche: Il server invia la sua chiave pubblica al client per consentire al client di autenticare l’identità del server.
- Verifica dell’identità del server: Il client verifica che la chiave pubblica ricevuta dal server corrisponda a quella memorizzata localmente per il server a cui si sta connettendo.
- Generazione della chiave di sessione: Una volta che l’identità del server è stata verificata, client e server generano una chiave di sessione condivisa per crittografare i dati scambiati durante la connessione.
- Autenticazione: Se richiesta, il client si autentica con il server utilizzando password, chiavi SSH o altri metodi di autenticazione supportati.
- Stabilimento della connessione sicura: Una volta completate le fasi precedenti con successo, la connessione SSH è stabilita in modo sicuro e i dati trasmessi tra client e server sono crittografati per garantire la riservatezza e l’integrità.
- Interazione con il server: Una volta stabilita la connessione, il client può interagire con il server SSH per eseguire comandi remoti, trasferire file in modo sicuro o utilizzare altre funzionalità offerte dal protocollo SSH.
Il punto cruciale è il punto 5. Qui si decide la chiave da utilizzare da qui in avanti per cifrare il contenuto dei messaggi per questa sessione. Fino al punto 5 infatti la trasmissione avviene in chiaro. Del resto lo scambio della chiave pubblica dal server al client non è un segreto: è pubblica! Per il calcolo della chiave di sessione, che è una chiave simmetrica, di solito vengono utilizzati algoritmi di scambio di chiavi come il Diffie-Hellman o il suo derivato Elliptic Curve Diffie-Hellman (ECDH). Questi algoritmi consentono a client e server di concordare in modo sicuro una chiave di sessione condivisa senza dover trasmettere in chiaro la chiave attraverso la rete, garantendo così la riservatezza della chiave simmetrica. Una volta che la chiave di sessione è generata utilizzando l’algoritmo di scambio di chiavi concordato, viene utilizzata per crittografare i dati scambiati durante la connessione SSH. L’algortimo da usare per calcolare la chiave è esattamente quello indicato con i due parametri visti sopra.
il parametro KexAlgorithms
viene utilizzato per specificare gli algoritmi di scambio di chiavi (key exchange algorithms) che possono essere utilizzati per stabilire una connessione sicura tra il client e il server. Questi algoritmi sono utilizzati per generare la chiave di sessione condivisa, che è una chiave simmetrica utilizzata per crittografare i dati scambiati durante la connessione SSH.
D’altra parte, l’opzione HostKeyAlgorithms
specifica gli algoritmi di chiave pubblica che il server accetta per autenticarsi durante la procedura di handshake iniziale. Questi algoritmi sono utilizzati per verificare l’identità del server e stabilire una connessione sicura con esso.
Quindi, per generare la chiave simmetrica durante una connessione SSH, sono importanti sia gli algoritmi di scambio di chiavi specificati con KexAlgorithms
che gli algoritmi di chiave pubblica specificati con HostKeyAlgorithms
. Entrambi giocano un ruolo cruciale nella sicurezza e nell’efficienza della connessione SSH.
Diciamo, in ultima analisi, che
HostKeyAlgorithms
serve per stabilire quale algoritmo di chiave pubblica asimmetrica verrà usato per scambiarsi la chiave simmetrica di sessione.KexAlgorithms
serve per stabilire quale algoritmo di chiave simmetrica verrà usato per generare la chiave (simmetrica) di sessione.
Dunque
- prima si calcola la chiave simmetrica con l’algoritmo concordato con
KexAlgorithms
(nel mio caso:diffie-hellman-group1-sha
) e - poi il client invia al server la chiave di sessione, dopo averla cifrata con l’agoritmo di chiave asimmetrica concordato con
HostKeyAlgorithms
(nel mio casossh-rsa
) che utilizza la chiave pubblica del server. - Alla fine il server è in grado di confontare che la chiave simmetrica calcolata da lui è uguale a quella calcolata dal client e cifrata con la sua chiave pubblica. Questo consente al server di autenticare il client.
Fonti
È stato divertente cercare di capire l’argomento utilizzando tre sistemi di AI: ChatGpt, Aria (Opera) e Skype/Bing.
Ci sono arrivato per interpolazione e verificando su siti attendibili come ssh.com, nessuno spiegava veramente bene come funziona il tutto, ma si avvicinava comunque alla realtà.
Poi… sono cose studiate tanti anni fa e un ripassino è sempre utile.
Commenti recenti