Da riga di comando
ssh -J user@bastion user@target
your machine -> SSH to bastion -> TCP from bastion to target -> SSH from your machine to target, inside it
Il jump host ha bisogno di un indirizzo raggiungibile. Il target no. Il suo nome viene risolto dal jump host, quindi un nome privato o un indirizzo privato come 10.0.0.5 funziona anche quando la tua macchina non può risolverlo né raggiungerlo. Una porta diversa si scrive dopo i due punti: -J user@bastion:2222.
scp e sftp accettano la stessa opzione, e rsync la passa a ssh:
scp -J user@bastion file.txt user@target:/tmp/
sftp -J user@bastion user@target
rsync -av -e "ssh -J user@bastion" ./site/ user@target:/var/www/site/
Nella tua configurazione ssh
Host bastion
HostName 203.0.113.10
User user
IdentityFile ~/.ssh/id_ed25519
Host target
HostName 10.0.0.5
User user
ProxyJump bastion
IdentityFile ~/.ssh/id_ed25519
Ora ti basta digitare ssh target, e scp, sftp e rsync funzionano allo stesso modo. Per applicarlo a un'intera rete:
Host 10.0.*
ProxyJump bastion
Non scrivere un pattern che corrisponda al jump host stesso. Per saltare il jump in una connessione, usa ssh -o ProxyJump=none target.
Per blocchi Host, schemi e Match, vedi gli esempi del file di configurazione ssh.
Più salti
Elenca i jump host in ordine, separati da virgole:
ssh -J user@bastion,user@inner user@target
Host target
ProxyJump bastion,inner
Ogni nome dell'elenco dopo il primo viene risolto a partire dal salto precedente.
Le opzioni da riga di comando non arrivano al jump host
È la sorpresa più comune. -i e -o si applicano solo al target finale, perché la connessione al jump host è un processo ssh separato che legge solo la tua configurazione. L'abbiamo provato: con la chiave indicata solo da -i, il login al jump host è fallito, e il messaggio era soltanto questo:
Connection closed by UNKNOWN port 65535
Quindi definisci utente, porta e chiave del jump host in un blocco Host della tua configurazione. Per vedere ogni passaggio, usa ssh -v target. Stampa il comando implicito e mostra l'autenticazione al jump host e poi al target.
Perché è più sicuro dell'agent forwarding
Il modo più vecchio era fare il login al jump host con ssh -A ed eseguire ssh di nuovo da lì. Questo lascia sul jump host un socket verso il tuo agent mentre sei connesso. Nel nostro test, un comando sul jump host poteva elencare le chiavi dell'agent del portatile:
ssh -A user@bastion 'ssh-add -l'
Chiunque abbia root su quel jump host può usare quel socket per fare il login come te, finché sei connesso. Non può copiare la chiave, ma non gli serve.
Con ProxyJump, sul jump host non c'è nulla di tuo:
- La tua chiave privata e il tuo agent restano sulla tua macchina, e il jump host non vi ha mai accesso.
- La tua macchina esegue il login al target e controlla la sua chiave host con il tuo
known_hosts. - Il jump host vede byte cifrati e sa a quale host e porta ti sei connesso, e quando. Non può leggere la sessione.
Un jump host compromesso può comunque bloccarti o osservare lo schema di quel traffico, e può attaccare la rete in cui si trova. Tienilo piccolo e aggiornato. Vedi i rischi dell'agent forwarding.
Versioni vecchie: ProxyCommand con -W
Per i client precedenti a OpenSSH 7.3, usa ssh -W, che esiste dalla versione 5.4:
Host target
HostName 10.0.0.5
ProxyCommand ssh -W %h:%p bastion
Usa una sola delle due opzioni per un host, non entrambe. Il manuale dice che sono in conflitto, e quella che viene per prima impedisce all'altra di avere effetto. ProxyCommand è utile anche quando devi passare opzioni tue a ssh interno, come -i.
Cosa deve consentire il jump host
Il salto usa un inoltro TCP sul jump host, quindi serve l'inoltro attivo. Con AllowTcpForwarding no vedi:
stdio forwarding failed
Connection closed by UNKNOWN port 65535
Agli utenti jump puoi concedere questo e nient'altro. Nella configurazione sshd del jump host:
Match User jump
PermitTTY no
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding local
PermitOpen 10.0.0.5:22 10.0.0.6:22
ForceCommand /usr/sbin/nologin
Nel nostro test, un login tramite questo utente raggiungeva il target elencato, un host non in elenco falliva con stdio forwarding failed e un login normale stampava This account is currently not available. PermitOpen confronta il testo esattamente e non fa ricerche, quindi le sue voci devono corrispondere al nome o all'indirizzo richiesto dal client.
Il firewall del target dovrebbe accettare SSH solo dal jump host, altrimenti il salto aggiunge poca protezione.
Domande
Che differenza c'è fra ProxyJump e agent forwarding?
Con ProxyJump chiave e agente restano sulla tua macchina e il jump host passa solo byte cifrati. L'agent forwarding lascia sul jump host un socket che root può usare finché sei connesso.
Posso usare più di un jump host?
Sì. Elencali in ordine, separati da virgole: ssh -J user@bastion,user@inner user@target, oppure ProxyJump bastion,inner nella configurazione.
Come uso scp o rsync attraverso un jump host?
scp e sftp accettano la stessa opzione: scp -J user@bastion file.txt user@target:/tmp/. Con rsync passala a ssh con -e "ssh -J user@bastion". Con ProxyJump nella configurazione basta anche il semplice scp target:...
Perché -i non vale per il jump host?
Le opzioni da riga di comando valgono solo per la destinazione finale. Imposta utente, porta e chiave del jump host nel suo blocco Host.
Fonti
- ssh(1), manuale OpenBSD
- ssh_config(5), manuale OpenBSD
- Note di rilascio di OpenSSH 7.3, ProxyJump
- Note di rilascio di OpenSSH 5.4, ssh -W