Auf der Kommandozeile
ssh -J user@bastion user@target
your machine -> SSH to bastion -> TCP from bastion to target -> SSH from your machine to target, inside it
Der Jump-Host braucht eine erreichbare Adresse. Das Ziel nicht. Sein Name wird vom Jump-Host aufgelöst, ein privater Name oder eine private Adresse wie 10.0.0.5 funktioniert also auch dann, wenn Ihr Rechner sie nicht auflösen oder erreichen kann. Ein eigener Port steht nach einem Doppelpunkt: -J user@bastion:2222.
scp und sftp kennen dieselbe Option, und rsync reicht sie an ssh weiter:
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/
In Ihrer ssh config
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
Jetzt tippen Sie nur noch ssh target, und scp, sftp und rsync funktionieren genauso. Um es auf ein ganzes Netz anzuwenden:
Host 10.0.*
ProxyJump bastion
Schreiben Sie kein Muster, das auf den Jump-Host selbst passt. Um den Jump für eine Verbindung zu überspringen, nutzen Sie ssh -o ProxyJump=none target.
Mehr zu Host-Blöcken, Mustern und Match finden Sie in den Beispielen zur SSH-Konfigurationsdatei.
Mehrere Hops
Listen Sie die Jump-Hosts der Reihe nach, durch Kommas getrennt:
ssh -J user@bastion,user@inner user@target
Host target
ProxyJump bastion,inner
Jeder Name in der Liste nach dem ersten wird vom vorherigen Hop aus aufgelöst.
Kommandozeilenoptionen erreichen den Jump-Host nicht
Das ist die häufigste Überraschung. -i und -o gelten nur für das endgültige Ziel, weil die Verbindung zum Jump-Host ein separater ssh-Prozess ist, der nur Ihre Konfiguration liest. Wir haben es getestet: Mit dem nur per -i genannten Schlüssel scheiterte die Anmeldung am Jump-Host, und die Meldung lautete nur:
Connection closed by UNKNOWN port 65535
Definieren Sie also Benutzer, Port und Schlüssel des Jump-Hosts in einem Host-Block Ihrer Konfiguration. Um jeden Schritt zu sehen, nutzen Sie ssh -v target. Es gibt den implizierten Befehl aus und zeigt die Authentifizierung beim Jump-Host und dann beim Ziel.
Warum es sicherer ist als Agent-Weiterleitung
Der ältere Weg war, sich mit ssh -A am Jump-Host anzumelden und von dort erneut ssh auszuführen. Das hinterlässt einen Socket zu Ihrem Agent auf dem Jump-Host, solange Sie verbunden sind. In unserem Test konnte ein Befehl auf dem Jump-Host die Schlüssel des Agents vom Laptop auflisten:
ssh -A user@bastion 'ssh-add -l'
Jeder mit root auf diesem Jump-Host kann diesen Socket nutzen, um sich als Sie anzumelden, solange Sie verbunden sind. Den Schlüssel kopieren kann er nicht, aber er braucht das nicht.
Mit ProxyJump liegt nichts von Ihnen auf dem Jump-Host:
- Ihr privater Schlüssel und Ihr Agent bleiben auf Ihrem Rechner, und der Jump-Host hat nie Zugriff darauf.
- Ihr Rechner übernimmt die Anmeldung am Ziel und prüft dessen Host-Schlüssel gegen Ihr eigenes
known_hosts. - Der Jump-Host sieht verschlüsselte Bytes und weiß, mit welchem Host und Port Sie sich wann verbunden haben. Die Sitzung kann er nicht lesen.
Ein kompromittierter Jump-Host kann Sie trotzdem blockieren oder dieses Verkehrsmuster beobachten, und er kann das Netz angreifen, in dem er steht. Halten Sie ihn klein und aktuell. Siehe die Risiken der Agent-Weiterleitung.
Alte Versionen: ProxyCommand mit -W
Für Clients älter als OpenSSH 7.3 nutzen Sie ssh -W, das es seit Version 5.4 gibt:
Host target
HostName 10.0.0.5
ProxyCommand ssh -W %h:%p bastion
Nutzen Sie für einen Host eine der beiden Optionen, nicht beide. Das Handbuch sagt, dass sie konkurrieren, und was zuerst kommt, verhindert die Wirkung der anderen. ProxyCommand ist auch nützlich, wenn Sie dem inneren ssh eigene Optionen mitgeben müssen, etwa -i.
Was der Jump-Host erlauben muss
Das Springen nutzt eine TCP-Weiterleitung auf dem Jump-Host, die Weiterleitung muss also an sein. Mit AllowTcpForwarding no sehen Sie:
stdio forwarding failed
Connection closed by UNKNOWN port 65535
Jump-Benutzern können Sie nicht mehr als das erlauben. In der sshd-Konfiguration des Jump-Hosts:
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
In unserem Test erreichte eine Anmeldung über diesen Benutzer das aufgeführte Ziel, ein Host, der nicht auf der Liste stand, scheiterte mit stdio forwarding failed, und eine normale Anmeldung gab This account is currently not available. aus. PermitOpen vergleicht Text exakt und führt keine Abfragen durch, seine Einträge müssen also dem Namen oder der Adresse entsprechen, die der Client anfragt.
Die Firewall des Ziels sollte SSH nur vom Jump-Host annehmen, sonst bringt der Jump wenig Schutz.
Fragen
Was unterscheidet ProxyJump von Agent Forwarding?
Mit ProxyJump bleiben Schlüssel und Agent auf Ihrem Rechner, und der Jump-Host reicht nur verschlüsselte Bytes weiter. Agent Forwarding hinterlässt auf dem Jump-Host einen Socket, den root dort nutzen kann, solange Sie verbunden sind.
Kann ich mehrere Jump-Hosts verwenden?
Ja. Geben Sie sie der Reihe nach durch Kommas getrennt an: ssh -J user@bastion,user@inner user@target, oder ProxyJump bastion,inner in der Konfiguration.
Wie nutze ich scp oder rsync über einen Jump-Host?
scp und sftp kennen dieselbe Option: scp -J user@bastion file.txt user@target:/tmp/. Bei rsync geben Sie sie mit -e "ssh -J user@bastion" an ssh weiter. Mit ProxyJump in Ihrer Konfiguration genügt auch ein einfaches scp target:...
Warum gilt -i nicht für den Jump-Host?
Optionen auf der Kommandozeile gelten nur für das Endziel. Legen Sie Benutzer, Port und Schlüssel des Jump-Hosts in seinem eigenen Host-Block fest.
Quellen
- ssh(1), OpenBSD-Handbuch
- ssh_config(5), OpenBSD-Handbuch
- OpenSSH 7.3 Release Notes, ProxyJump
- OpenSSH 5.4 Release Notes, ssh -W