En ligne de commande
ssh -J user@bastion user@target
your machine -> SSH to bastion -> TCP from bastion to target -> SSH from your machine to target, inside it
L'hôte de rebond doit avoir une adresse joignable. Pas la cible. Son nom est résolu par l'hôte de rebond : un nom privé ou une adresse privée comme 10.0.0.5 fonctionne donc même si votre machine ne peut ni la résoudre ni l'atteindre. Un port personnalisé se place après deux-points : -J user@bastion:2222.
scp et sftp acceptent la même option, et rsync la transmet à 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/
Dans votre configuration 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
Désormais, il suffit de taper ssh target, et scp, sftp et rsync fonctionnent de la même façon. Pour l'appliquer à tout un réseau :
Host 10.0.*
ProxyJump bastion
N'écrivez pas de motif qui corresponde à l'hôte de rebond lui-même. Pour sauter le rebond pour une connexion, utilisez ssh -o ProxyJump=none target.
Pour aller plus loin avec les blocs Host, les motifs et Match, voir des exemples de fichier de configuration ssh.
Plusieurs sauts
Listez les hôtes de rebond dans l'ordre, séparés par des virgules :
ssh -J user@bastion,user@inner user@target
Host target
ProxyJump bastion,inner
Chaque nom de la liste après le premier est résolu depuis le saut précédent.
Les options de la ligne de commande n'atteignent pas l'hôte de rebond
C'est la surprise la plus courante. -i et -o ne s'appliquent qu'à la cible finale, car la connexion à l'hôte de rebond est un processus ssh distinct qui ne lit que votre configuration. Nous l'avons testé : avec la clé indiquée uniquement par -i, la connexion à l'hôte de rebond échouait, et le message était simplement :
Connection closed by UNKNOWN port 65535
Définissez donc l'utilisateur, le port et la clé de l'hôte de rebond dans un bloc Host de votre configuration. Pour voir chaque étape, utilisez ssh -v target. Il affiche la commande implicite, puis l'authentification auprès de l'hôte de rebond et ensuite auprès de la cible.
Pourquoi c'est plus sûr que la redirection d'agent
L'ancienne méthode consistait à se connecter à l'hôte de rebond avec ssh -A, puis à relancer ssh depuis là. Cela laisse sur l'hôte de rebond un socket vers votre agent tant que vous êtes connecté. Dans notre test, une commande sur l'hôte de rebond pouvait lister les clés de l'agent du portable :
ssh -A user@bastion 'ssh-add -l'
Toute personne ayant les droits root sur cet hôte de rebond peut utiliser ce socket pour se connecter à votre place, tant que vous êtes connecté. Elle ne peut pas copier la clé, mais n'en a pas besoin.
Avec ProxyJump, rien de vous ne se trouve sur l'hôte de rebond :
- Votre clé privée et votre agent restent sur votre machine, et l'hôte de rebond n'y a jamais accès.
- Votre machine effectue la connexion à la cible et vérifie sa clé d'hôte avec votre propre
known_hosts. - L'hôte de rebond voit des octets chiffrés, et sait à quel hôte et quel port vous vous êtes connecté, et quand. Il ne peut pas lire la session.
Un hôte de rebond compromis peut quand même vous bloquer ou observer ce profil de trafic, et peut attaquer le réseau où il se trouve. Gardez-le petit et à jour. Voir les risques de la redirection d'agent.
Anciennes versions : ProxyCommand avec -W
Pour les clients antérieurs à OpenSSH 7.3, utilisez ssh -W, qui existe depuis la version 5.4 :
Host target
HostName 10.0.0.5
ProxyCommand ssh -W %h:%p bastion
Utilisez l'une des deux options pour un hôte, pas les deux. Le manuel dit qu'elles se font concurrence, et que celle qui vient en premier empêche l'autre de prendre effet. ProxyCommand est aussi utile quand vous devez passer vos propres options au ssh interne, comme -i.
Ce que l'hôte de rebond doit autoriser
Le rebond utilise une redirection TCP sur l'hôte de rebond : la redirection doit donc être activée. Avec AllowTcpForwarding no, vous voyez :
stdio forwarding failed
Connection closed by UNKNOWN port 65535
Vous pouvez ne donner aux utilisateurs de rebond rien de plus que cela. Dans la configuration sshd de l'hôte de rebond :
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
Dans notre test, une connexion via cet utilisateur atteignait la cible listée, un hôte absent de la liste échouait avec stdio forwarding failed, et une connexion normale affichait This account is currently not available. PermitOpen compare le texte à l'identique et ne fait aucune résolution : ses entrées doivent donc correspondre au nom ou à l'adresse que demande le client.
Le pare-feu de la cible ne devrait accepter SSH que depuis l'hôte de rebond, sinon le rebond apporte peu de protection.
Questions
Quelle différence entre ProxyJump et l'agent forwarding ?
Avec ProxyJump, votre clé et votre agent restent sur votre machine et l'hôte de rebond ne transmet que des octets chiffrés. L'agent forwarding laisse sur l'hôte de rebond un socket que root peut utiliser tant que vous êtes connecté.
Peut-on passer par plusieurs hôtes de rebond ?
Oui. Listez-les dans l'ordre, séparés par des virgules : ssh -J user@bastion,user@inner user@target, ou ProxyJump bastion,inner dans la configuration.
Comment utiliser scp ou rsync via un hôte de rebond ?
scp et sftp acceptent la même option : scp -J user@bastion file.txt user@target:/tmp/. Pour rsync, passez-la à ssh avec -e "ssh -J user@bastion". Avec ProxyJump dans votre configuration, un simple scp target:... suffit aussi.
Pourquoi -i ne s'applique-t-il pas à l'hôte de rebond ?
Les options de la ligne de commande ne valent que pour la cible finale. Définissez l'utilisateur, le port et la clé de l'hôte de rebond dans son propre bloc Host.
Sources
- ssh(1), manuel OpenBSD
- ssh_config(5), manuel OpenBSD
- Notes de version d'OpenSSH 7.3, ProxyJump
- Notes de version d'OpenSSH 5.4, ssh -W