Con ssh si apre un terminale su un altro computer attraverso la rete, come se si fosse seduti davanti a quella macchina. È lo strumento di lavoro di chiunque gestisca server, VPS e dispositivi remoti: tutto il traffico è cifrato e l'accesso può essere protetto da chiavi invece che da password.
Cos'è
ssh sta per Secure SHell. È il programma client del protocollo SSH: si collega al server SSH (sshd) in ascolto sulla macchina remota, di norma sulla porta 22. Ha sostituito programmi più vecchi come telnet e rsh, che inviavano tutto, password comprese, in chiaro. Il client è già presente nella maggior parte delle distribuzioni; sul computer a cui ci si vuole collegare serve il server: sudo apt install openssh-server su Debian e Ubuntu (sulle VPS è quasi sempre già installato).
Cosa fa
Stabilisce una connessione cifrata con il server, verifica che sia davvero quello giusto, ti autentica (con password o con una chiave) e ti dà una shell sulla macchina remota. Ma non si limita a questo: lo stesso collegamento può eseguire un singolo comando, trasferire file (con scp, sftp e rsync) e fare da "tunnel" per altri servizi.
Come si usa
$ ssh [opzioni] [utente@]host [comando]Gli indirizzi negli esempi (server.example.org, 203.0.113.10, l'utente enzo) sono d'esempio: sostituiscili con i tuoi.
Esempio 1: il primo collegamento
$ ssh enzo@server.example.org
The authenticity of host 'server.example.org (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:Xk3...esempio...Qw8.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'server.example.org' (ED25519) to the list of known hosts.
enzo@server.example.org's password:
Welcome to Ubuntu 24.04 LTS
enzo@server:~$La prima volta ssh ti mostra l'impronta (fingerprint) della chiave del server e chiede se fidarti. Rispondendo yes l'impronta viene salvata nel file ~/.ssh/known_hosts. Se possibile, confrontala con quella che ti dà il fornitore del server: è la protezione contro chi si finge il server. Dopo la password il prompt cambia: ora i comandi che scrivi vengono eseguiti sulla macchina remota. Per uscire basta exit oppure Ctrl+D.
Esempio 2: l'utente, la porta e l'indirizzo
$ ssh server.example.org
$ ssh enzo@server.example.org
$ ssh -p 2222 enzo@server.example.org
$ ssh enzo@203.0.113.10Senza utente@ si usa il nome dell'utente con cui sei collegato sul computer locale. Con -p (minuscola) si indica una porta diversa dalla 22, cosa comune sui server che la cambiano per ridurre i tentativi automatici di accesso. Al posto del nome si può usare l'indirizzo IP.
Esempio 3: eseguire un solo comando
$ ssh enzo@server.example.org 'uptime'
04:41:07 up 63 days, 2:15, 1 user, load average: 0,08, 0,03, 0,01
$ ssh enzo@server.example.org 'df -h /'
File system Dim. Usati Dispon. Uso% Montato su
/dev/vda1 40G 12G 26G 32% /Se dopo l'indirizzo scrivi un comando, ssh lo esegue sul server, ne mostra l'output e ti ridà subito il terminale locale. Il comando va tra apici, così sarà il server, e non la tua shell, a interpretarlo (pipe, variabili e * compresi). Il codice di uscita del comando remoto diventa quello di ssh, quindi si presta agli script.
Esempio 4: creare una chiave e copiarla sul server
$ ssh-keygen -t ed25519 -C "enzo@portatile"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/enzo/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/enzo/.ssh/id_ed25519
Your public key has been saved in /home/enzo/.ssh/id_ed25519.pub
$ ssh-copy-id enzo@server.example.org
Number of key(s) added: 1
$ ssh enzo@server.example.org
enzo@server:~$L'accesso con chiave è più sicuro e più comodo di quello con password. ssh-keygen crea una coppia di chiavi: la chiave privata (id_ed25519) resta sul tuo computer e non va mai condivisa; la chiave pubblica (id_ed25519.pub) si può dare a chiunque. ssh-copy-id aggiunge quella pubblica al file ~/.ssh/authorized_keys sul server. Da quel momento il server ti riconosce senza chiedere la password dell'account. Conviene proteggere la chiave privata con una passphrase: se qualcuno ne copiasse il file, non potrebbe usarla.
Esempio 5: non digitare la passphrase ogni volta con ssh-agent
$ eval "$(ssh-agent -s)"
Agent pid 4821
$ ssh-add
Enter passphrase for /home/enzo/.ssh/id_ed25519:
Identity added: /home/enzo/.ssh/id_ed25519 (enzo@portatile)
$ ssh-add -l
256 SHA256:Rt5...esempio...Zp1 enzo@portatile (ED25519)ssh-agent tiene la chiave sbloccata in memoria per la durata della sessione, e ssh-add ve la carica. Su molti ambienti desktop l'agente è già attivo e fa questo lavoro in automatico.
Esempio 6: il file di configurazione ~/.ssh/config
$ cat ~/.ssh/config
Host web
HostName server.example.org
User enzo
Port 2222
IdentityFile ~/.ssh/id_ed25519
Host *
ServerAliveInterval 60
$ ssh web
enzo@server:~$Invece di ricordare utente, porta e indirizzo, li scrivi una volta nel file ~/.ssh/config e dai un nome breve a ogni server. Il nome vale anche per scp, sftp e rsync. ServerAliveInterval 60 invia un segnale ogni 60 secondi per evitare che la connessione cada per inattività. Il file deve poter essere scritto solo da te: chmod 600 ~/.ssh/config.
Esempio 7: copiare file con scp
$ scp relazione.pdf enzo@server.example.org:/home/enzo/
relazione.pdf 100% 842KB 3,1MB/s 00:00
$ scp enzo@server.example.org:/var/log/nginx/error.log .
$ scp -r cartella/ web:/tmp/scp copia file attraverso SSH con una sintassi simile a cp, in cui la parte remota si scrive utente@host:percorso. Con -r copia intere cartelle. Per trasferimenti ripetuti o molto grandi, rsync (che vedremo in un altro articolo) è più efficiente, perché invia solo ciò che è cambiato. Per un collegamento interattivo ai file, sftp enzo@server.example.org apre una sessione dove si usano ls, get e put.
Esempio 8: combinare ssh con le pipe
$ ssh web 'tail -n 100 /var/log/nginx/access.log' | grep ' 404 ' | wc -l
17
$ tar czf - cartella/ | ssh web 'cat > /tmp/cartella.tar.gz'
$ ssh web 'sudo tar czf - /etc/nginx' > nginx-backup.tar.gzL'output di un comando remoto si può mandare a comandi locali e viceversa. Nel primo esempio il filtro con grep e il conteggio con wc avvengono sul tuo computer. Il secondo invia un archivio creato in locale e lo scrive in un file remoto. Il terzo crea un archivio sul server e lo salva in locale, grazie alla redirezione > che avviene sul tuo computer. In questi casi sudo sul server deve poter funzionare senza chiedere la password (o essere configurato per quel comando), perché non c'è un terminale su cui scriverla.
Esempio 9: tunnel per raggiungere un servizio remoto (-L)
$ ssh -L 8080:localhost:5678 web
# ora, in un browser sul tuo computer: http://localhost:8080Con -L porta_locale:destinazione:porta_remota il collegamento diventa un tunnel: ciò che arriva alla porta 8080 del tuo computer viene inoltrato, attraverso SSH, a localhost:5678 visto dal server. È un modo sicuro per usare servizi che sul server ascoltano solo in locale (pannelli di amministrazione, database, un'applicazione web in prova) senza esporli su Internet. Per tenere solo il tunnel, senza aprire una shell, si aggiungono -N e, per mandarlo in secondo piano, -f: ssh -fNL 8080:localhost:5678 web.
Esempio 10: passare da un server intermedio con -J
$ ssh -J enzo@bastione.example.org enzo@10.0.0.20Alcuni server interni non sono raggiungibili da Internet, ma solo passando da un computer "di salto" (bastion o jump host). Con -J la connessione attraversa il computer intermedio in un solo comando. Nel file ~/.ssh/config lo stesso risultato si ottiene con ProxyJump.
Esempio 11: quando qualcosa non va con -v
$ ssh -v enzo@server.example.org
OpenSSH_9.6p1 Ubuntu-3ubuntu13, OpenSSL 3.0.13 30 Jan 2024
debug1: Connecting to server.example.org [203.0.113.10] port 22.
debug1: Connection established.
debug1: Offering public key: /home/enzo/.ssh/id_ed25519 ED25519 SHA256:...
debug1: Authentications that can continue: publickey,password
...Con -v (anche -vv e -vvv per più dettagli) ssh racconta tutto ciò che fa: quale chiave prova, quali metodi di accesso accetta il server, dove si blocca. È il primo strumento per capire un Permission denied o un blocco della connessione. Se la connessione non parte nemmeno, ping aiuta a controllare che la macchina sia raggiungibile (anche se alcuni server non rispondono al ping).
Esempio 12: uso negli script
#!/bin/bash
SERVER="web"
if ssh -o BatchMode=yes -o ConnectTimeout=5 "$SERVER" 'true'; then
echo "$SERVER raggiungibile via SSH"
else
echo "Impossibile collegarsi a $SERVER" >&2
exit 1
fi
for s in web1 web2 web3; do
echo "== $s =="
ssh -o BatchMode=yes "$s" 'uptime' || echo "(errore su $s)" >&2
doneBatchMode=yes impedisce a ssh di chiedere password o passphrase: negli script, o se la chiave non è disponibile, fallisce subito invece di restare in attesa. ConnectTimeout=5 rinuncia dopo 5 secondi se il server non risponde. Il codice di uscita di ssh è quello del comando remoto, oppure 255 se il problema è la connessione stessa.
Attenzione: dentro un ciclo while read ssh consuma l'input standard e interrompe il ciclo dopo la prima riga. In quel caso si aggiunge l'opzione -n (ssh -n host comando), che gli impedisce di leggere dallo standard input.
Opzioni utili
-p porta: usa una porta diversa dalla 22 (conscpl'opzione è-Pmaiuscola).-i file: indica quale chiave privata usare.-v: diagnostica dettagliata;-q: silenzioso.-L/-R/-D: tunnel locale, remoto e proxy SOCKS dinamico.-N: non esegue comandi (solo tunnel);-f: manda la connessione in secondo piano.-J host: passa da un computer intermedio.-A: inoltra l'agente delle chiavi al server (da usare solo con server di cui ti fidi).-X/-Y: permette di aprire programmi grafici remoti sul proprio schermo.-t: forza un terminale interattivo, necessario per programmi comesudo,htoponanolanciati come comando remoto.-o Opzione=valore: imposta qualsiasi opzione del file di configurazione dalla riga di comando.-4/-6: forza IPv4 o IPv6.-C: comprime i dati (utile su connessioni lente).
Attenzione a
- La chiave privata è un segreto: non va mai copiata sui server, inviata per email o inserita in un repository. Il file deve avere permessi
600(chmod 600 ~/.ssh/id_ed25519), altrimentisshlo rifiuta con l'avviso UNPROTECTED PRIVATE KEY FILE. La cartella~/.sshdovrebbe essere700. - Non confondere chiave pubblica e privata: sul server va quella con estensione
.pub. - Avvertimento "REMOTE HOST IDENTIFICATION HAS CHANGED": l'impronta del server non corrisponde più a quella salvata. Può dipendere da una reinstallazione del server o da un cambio di indirizzo, ma anche da qualcuno che si finge il server. Prima di procedere verifica con chi gestisce la macchina. Se è tutto regolare, togli la vecchia voce con
ssh-keygen -R server.example.org. - Mai ignorare il controllo delle impronte: opzioni come
StrictHostKeyChecking=notolgono la protezione contro gli impostori. Va bene al massimo su macchine di prova che si ricreano di continuo. - "Permission denied (publickey)": il server non accetta la tua chiave. Controlla che quella pubblica sia in
~/.ssh/authorized_keyssul server, che i permessi di~/.ssh(700) e diauthorized_keys(600) siano corretti e che stai usando l'utente giusto. Conssh -vsi vede quale chiave viene offerta. - "Connection refused" o "Connection timed out": nel primo caso il server è raggiungibile, ma nessun servizio SSH risponde su quella porta; nel secondo i pacchetti non arrivano, e di solito il responsabile è un firewall, un indirizzo sbagliato o il server spento.
- Prima di chiudere l'accesso con password, prova la chiave: se disattivi l'accesso con password sul server (
PasswordAuthentication noin/etc/ssh/sshd_config) e la chiave non funziona, rischi di restare fuori. Tieni aperta una sessione già collegata e prova da una seconda finestra prima di chiudere. - Accesso root: sui server è prassi disattivare l'accesso diretto come
root(PermitRootLogin no) e collegarsi con un utente normale che usasudo. - Server esposti a Internet: la porta 22 riceve di continuo tentativi automatici di accesso. Chiavi al posto delle password e uno strumento come
fail2banriducono molto il rischio; cambiare porta riduce il rumore nei registri, ma non è una vera protezione. - Comandi remoti e virgolette:
ssh host ls *.txtespande l'asterisco in locale, prima dell'invio. Per farlo valutare al server scrivissh host 'ls *.txt'. Lo stesso vale per le variabili:"$HOME"tra virgolette doppie è quella locale, tra apici singoli quella del server. - Operazioni lunghe: se la connessione cade, i programmi avviati nella sessione si interrompono. Per lavori lunghi usa
tmuxoscreensul server (onohupper un singolo comando), così continuano anche se ti scolleghi. - Sapere dove si è: con più finestre aperte è facile eseguire un comando distruttivo (
rm,reboot,shutdown) sulla macchina sbagliata. Controlla il prompt, o il nome mostrato dahostname, prima dei comandi delicati. - Inoltro dell'agente (
-A): chi ha accesso come amministratore al server può usare le tue chiavi finché sei collegato. Meglio il salto con-J.
Riepilogo
| Comando | Cosa fa |
|---|---|
ssh utente@host | Apre una shell sul computer remoto |
ssh -p 2222 utente@host | Usa una porta diversa dalla 22 |
ssh host 'comando' | Esegue un solo comando sul server |
ssh-keygen -t ed25519 | Crea una coppia di chiavi |
ssh-copy-id utente@host | Installa la chiave pubblica sul server |
ssh-add | Carica la chiave nell'agente (niente passphrase ripetuta) |
~/.ssh/config | Nomi brevi e impostazioni per ogni server |
scp file utente@host:percorso | Copia file verso (o da) il server |
ssh -L 8080:localhost:5678 host | Tunnel verso un servizio remoto |
ssh -J bastione host | Passa da un computer intermedio |
ssh -v host | Diagnostica dettagliata della connessione |
ssh-keygen -R host | Rimuove un'impronta salvata |
exit / Ctrl+D | Chiude la sessione remota |