Connettersi ad un server remoto via ssh utilizzando una chiave pubblica

Se vi siete mai trovati a gestire dei server da remoto, vi sarà sicuramente capitato di dover effettuare alcune procedure collegandovi via SSH ad altri server, come ad esempio sincronizzare dei file su macchine remote. E' possibile aprire una connessione remota protetta utilizzando SSH, ma solitamente quando lanciamo il comando di connessione, ci viene richiesta una password di accesso. A parte la piccola scomodità di inputarla manulmente, il fatto che sia necessario inserire la password ad ogni connessione, è un fattore piuttosto limitante, in quanto ci impedisce ad esempio di effettuare quelle operazioni in modo automatico. Una possibilità potrebbe essere quella di scrivere un comando che contenga la password, ma non è certo una buona idea inserire una password, magari di root, in chiaro all'interno di uno script. La soluzione c'è. Per poter effettuare una connessione SSH senza dover inserire la password, è sufficiente creare una chiave univoca che permetta alle due macchine di riconoscersi. Ecco come fare.

Per illustrare il procedimento, supponiamo che quello che vogliamo ottenre sia voler configuare una procedura automatica di backup via rsync tra due VPS da chiamare via cron.

Partiamo dalla macchina in cui desideriamo salvare i nostri dati che chiameremo vpsbackup e su questa macchina andiamo a generare la nostra coppia di chiavi: una privata che resterà sulla macchina ed una pubblica che copieremo sull'altra macchina che chiameremo vpsorigine. Le due macchine utilizzeranno queste chiavi per comunicare e riconoscersi.

Quello che ci interessa è poter accedere ad entrambe le macchine con i massimi privilegi, quindi andremo a generare le chiavi come utente root.

Su vpsbackup, ovvero sulla macchina dalla quale vogliamo lanciare la connessione, apriamo un terminale root ssh, e digitiamo:

ssh-keygen -t rsa

Si noti inoltre che oltre a rsa è possibile impostare differenti algoritmi di crittografia per la nostra chiave condivisa, quale ad esempio dsa che risulta più sicuro rispetto al precedente, ma che richiede risorse di sistema leggermente superiori durante il trasferimento dei file; il comando da eseguire diventerebbe ssh-keygen -t dsa.

Ci verrà chiesto dove salvare la chiave; per default questa verrà messa nella sottocartella della home .ssh e si chiamerà id_rsa (nel caso di root in /root/.ssh/); fate attenzione che non vi sia già un file con lo stesso nome perché verrebbe sovrascritto e vi obbligherebbe ad aggiornare anche la relativa chiave pubblica. In caso affermativo utilizzate un nome differente per il file.

Verrà chiesto di inserire una password, ma ovviamente non ne inseriremo nessuna visto che desideriamo effettuare una connessione senza password, quindi diamo invio finchè non ritorniamo al prompt:

Vengono generate due chiavi, una privata (id_rsa) ed la relativa coppia pubblica (id_rsa.pub). Impostiamo i permessi sulla chiave privata come leggibili solo da root (in teoria dovrebbe essere già così, quindi il comando potrebbe risultare superfluo, ma assicuriamoci comunque che solo root abbia accesso a tali file):

chmod go-r /root/.ssh/id_rsa

Ora che abbiamo generato la coppia di chiavi, il prossimo passo è quello di trasferire / copiare la chiave pubblica sul sever a cui vogliamo connetterci, ovvero su vpsorigine.

Copio id_rsa.pub sul server vpsorigine e rinomino il file come authorized_keys oppure nel caso esista già questo file ci aggiungo semplicemente il contenuto della nostra chiave pubblica id_rsa.pub, ovvero copio ed incollo qualcosa di simile:

ssh-rsa CCCCB3NzaC1yc2EACEEBIwAAAQEA1Amrlrt1SeTNniQOKWWinda7Uwroae4+/4fMprIrArX2D/Y123kjyR75Ysi6A1MUlmiiDbyNrgQhcoYd12wUp6vV1Su5usKQIIqtem2Gqma/er9g3RRg+tZqmVdayafSkqi5jqM5z+f0iIoH0XWfp1PxfCwljstCfP3BqpIq1ucdNUHvOZy1vmsdfsTXqpuBU04aMH37oY71Zvt1NGqw6+vSqX4FqhdsY/sG8EXyPcoNprzeQJGLLUX1EoG5N0EpGkT3WUAFEAVMpBDEcaSqwe/VRjn/IKJMoOAhBSjPV1VA03tg0uKV9lfIceE754e9iNlNIX7NIrSAnl/jb9EYcw== root@myserver

nel file authorized_keys sul server remoto a cui desidero connettermi. Salviamo il file ed impostiamo i permessi in lettura solo a root:

chmod 600 authorized_keys

Per finire, su vpsbackup, ovvero la macchina in cui andrò a lanciare il comando di sincronizzazione, creo il file /root/.ssh/config contenente i seguenti parametri

host vpsorigine 
  hostname 192.168.1.110 
  user root
  identityfile /root/.ssh/id_rsa_backup
  compression yes
  cipher blowfish
  protocol 2

Salviamo e chiudiamo il file.

Possiamo effettuare la prima prova di connessione, lanciando ad esempio la connessione via SSH:

ssh vpsorigine

e se tutto è andato per il verso giusto, mi dovrei riuscire a connettere senza bisogno di inserire la password.

Si noti che la prima volta che ci connettiamo alla macchina remota, ci verrà chiesto se considerare attendibili la connessione e se aggiungere la macchina remota agli host conosciuti (ovvero al file known_hosts); sarà quindi necessario effettuare almeno una volta una connessione manuale prima di poter usare la connessione appena configurata con una procedura automatica.

Si noti che nel file config sopra mostrato, è stata inserita la riga "user root". E' infatti possibile specificare l'utente da utilizzare al momento della connessione.

Consideriamo la seguente situazione.

Supponiamo di volerci connettere ad una macchina remota con utenti differenti rispetto a quella da cui lanciamo la connessione. Supponiamo ad esempio che sulla macchina locale da cui vogliamo lanciare la connessione (macchina chiamata Democrito), sia presente presente l'utente Andrea, utente non presente nella macchina remota. Possiamo ripetere quanto visto sopra per la generazione della coppia di chiavi privata / pubblica per l'utente Andrea sulla macchina locale Democrito.

Supponiamo di volerci connettere alla macchina remota di IP 192.168.1.111 con l'utente marco; dovremmo andare ad aggiungere la chiave pubblica generata sulla macchina locale al file authorized_keys dell'utente marco della macchina remota, file che nei sistemi Ubuntu Linux si troverà nella cartella /home/marco/.ssh/authorized_keys (se non ci fosse, basta crearlo). Una volta aggiunta la nostra chiave a quelle autorizzate per l'utente marco, possiamo aggiungere al file config dell'utente Andrea nella macchina locale la configurazione per la connessione alla macchina remota:

host remote
  hostname 192.168.1.111
  user marco
  identityfile /home/Andrea/.ssh/id_rsa_remote
  compression yes
  cipher blowfish
  protocol 2

A questo punto potremmo connetterci via SSH alla macchina remota semplicemente scrivendo:

ssh remote

e la nostra connessione inizierà senza bisogno di inserire una password. A questo punto tutto dovrebbe essere a posto per provare la procedura di sincronizzazione dei dati.

La struttura del comando rsync è del tipo:

sudo rsync -avz --rsync-path=/usr/bin/rsync myvps:/cartella/di/origine/ /cartella/di/destinazione/

Per quanto riguarda il nostro problema iniziale, ovvero effettuare un backup con rsync utilizzando cron, il comando di sincronizzazione per il backup dei file potrebbe essere qualcosa di simile al seguente, che andiamo ad eseguire almeno una volta per verificare che non vi siano problemi (sudo per eseguirlo come root sulla macchina locale):

sudo /usr/bin/rsync -avz --delete --rsync-path=/usr/bin/rsync vpsorigine:/var/www/site/ /var/www/site/

Anche qui se tutto è stato configurato correttamente dovremmo riuscire ad effettuare il backup senza bisogno di inserire nessuna password. L'opzione --delete elimina dalla macchina locale i file che sono stati cancellati da quella remota.

Vediamo ora come inserire il comando perché venga eseguito in un processo cron. Semplicemente creiamo un file con il seguente contenuto (il file va posizionato in /etc/cron.d):

# Effettua il mirror giornaliero in locale della cartella site presente
# su vpsorigine e cancella i file in locale non più presenti nell'origine
30 3 * * * root /usr/bin/rsync -avz --rsync-path=/usr/bin/rsync --exclude-from '/root/rsync-exclude/mirror.txt' --delete vpsorigine:/var/www/site/ /var/www/site/ | mail miamail [chiocciola] email [dot] it -s "Log backup"
#

Dove /root/rsync-exclude/mirror.txt è un file di testo contenente un elenco di cartelle e file da escludere dalla sincronizzazione (ad esempio cartelle temporanee)  potrebbe essere simile al seguente:

tmp temp files/*/tmp .htacces

Aumentare il livello di sicurezza

Per aumentare il livello di sicurezza, sarebbe interessante limitare quello che è possibile effettuare quando ci si connette utilizzando questa determinata chiave. Se in authorized_keys semplicemente scriviamo

ssh-rsa CCCCB3NzaC1yc2EACEEBIwAAAQEA1Amrlrt1SeTNniQOKWWinda7Uwroae4+/4fMprIrArX2D/Y123kjyR75Ysi6A1MUlmiiDbyNrgQhcoYd12wUp6vV1Su5usKQIIqtem2Gqma/er9g3RRg+tZqmVdayafSkqi5jqM5z+f0iIoH0XWfp1PxfCwljstCfP3BqpIq1ucdNUHvOZy1vmsdfsTXqpuBU04aMH37oY71Zvt1NGqw6+vSqX4FqhdsY/sG8EXyPcoNprzeQJGLLUX1EoG5N0EpGkT3WUAFEAVMpBDEcaSqwe/VRjn/IKJMoOAhBSjPV1VA03tg0uKV9lfIceE754e9iNlNIX7NIrSAnl/jb9EYcw== root@ubuntu

Significa che possiamo connetterci a questa macchina ed effettuare ogni tipo di operazione semplicemente se ci chiamiamo root@ubuntu (ed ovviamente se siamo in possesso della chiave confivisa).

Ad esempio un livello di sicurezza aggiuntivo è quello di consentire la connessione tramite la nostra chiave solo dal nostro server, utilizzando il parametro from. Se ad esempio supponiamo che il nostro server si chiami my.server.com, andremmo a modificare quanto scritto in authorized_keys anteponendo from="my.server.com" come mostrato di seguito:

from="my.server.com" ssh-rsa CCCCB3NzC1yc2EACEEBIwAAAQEA1Amrlrt1SeTNniQOKWWinda7Uwroae4+/4fMprIrArX2D/Y123kjyR75Ysi6A1MUlmiiDbyNrgQhcoYd12wUp6vV1Su5usKQIIqtem2Gqma/er9g3RRg+tZqmVdayafSkqi5jqM5z+f0iIoH0XWfp1PxfCwljstCfP3BqpIq1ucdNUHvOZy1vmsdfsTXqpuBU04aMH37oY71Zvt1NGqw6+vSqX4FqhdsY/sG8EXyPcoNprzeQJGLLUX1EoG5N0EpGkT3WUAFEAVMpBDEcaSqwe/VRjn/IKJMoOAhBSjPV1VA03tg0uKV9lfIceE754e9iN lNIX7NIrSAnl/jb9EYcw== root@myserver