Ce que fait -A
Sans redirection, vos clés ne servent à rien une fois que vous êtes sur un serveur : un deuxième saut depuis celui-ci ne peut pas les utiliser. ssh -A règle cela en reliant l'hôte distant à votre agent :
ssh -A user@server
echo "$SSH_AUTH_SOCK"
/tmp/ssh-G63yAM532X/agent.1441
Ce chemin est un socket Unix sur le serveur. Tout ce qui lui est envoyé retourne vers l'agent sur votre ordinateur, qui signe ce qu'on lui demande et renvoie le résultat. Le serveur ne reçoit jamais la clé privée.
L'emplacement dépend de la version du serveur. Nous avons vu /tmp/ssh-XXXXXXXXXX/agent.<pid> sur OpenSSH 10.0. La version 10.1 a déplacé les sockets d'agent vers ~/.ssh/agent/.
Pour charger d'abord vos clés dans un agent local, voir ssh-agent et le trousseau macOS.
Ce que root sur l'hôte distant peut faire
Les permissions de fichier protègent le socket des autres utilisateurs ordinaires, mais root ignore ces permissions. Nous l'avons testé sur un serveur pendant qu'un utilisateur était connecté avec -A. En root :
# find /tmp -type s -name 'agent.*'
/tmp/ssh-G63yAM532X/agent.1441
# SSH_AUTH_SOCK=/tmp/ssh-G63yAM532X/agent.1441 ssh-add -l
256 SHA256:IikDwOZxEooOrmm+d3MXJXlobc7rwEyUrQNIBXHzXaU key (ED25519)
# SSH_AUTH_SOCK=/tmp/ssh-G63yAM532X/agent.1441 ssh user@203.0.113.11 id -un
user
Root a donc utilisé la clé pour se connecter à une autre machine, sans aucune invite côté utilisateur. Voici le tableau complet :
- Il peut : utiliser chaque clé de votre agent, pour se connecter à tout serveur ou service qui les accepte, y compris un compte d'hébergement de code. Il peut aussi lister vos clés publiques et retirer des clés de votre agent :
ssh-add -Dlancé sur le serveur a vidé notre agent local. - Il ne peut pas : copier la clé privée. L'agent ne la fournit pas. Un socket volé cesse de fonctionner à la fin de votre session, et nous avons confirmé que le socket disparaît à ce moment.
- Un autre utilisateur ordinaire a été refusé :
Error connecting to agent: Permission denied.
« Root » inclut ici quiconque a pénétré dans le serveur et obtenu root. Une connexion faite pendant que vous êtes connecté peut déposer sa propre clé sur la cible et garder l'accès bien après votre départ. C'est pourquoi la courte durée de vie du socket rassure moins qu'il n'y paraît.
L'alternative : ProxyJump
La plupart des gens utilisent la redirection pour passer par un bastion. Avec -J, votre ordinateur ouvre une connexion chiffrée à travers l'hôte de rebond jusqu'au serveur final, et les clés ne sont utilisées que depuis votre ordinateur :
ssh -J user@bastion user@server
Ou dans ~/.ssh/config :
Host server
HostName 10.0.0.5
ProxyJump user@bastion
Dans notre test, la connexion a fonctionné, $SSH_AUTH_SOCK était vide sur la cible, et aucun socket d'agent n'existait sur l'hôte de rebond. Un bastion compromis n'a rien à exploiter. Voir ProxyJump et les hôtes de rebond.
Si vous avez vraiment besoin de la redirection
Un cas typique : lancer git pull sur un serveur avec vos identifiants personnels. Demandez-vous d'abord si une clé de déploiement pour ce seul dépôt, gardée sur le serveur, suffirait. Si vous avez toujours besoin de la redirection, réduisez ce qu'elle expose.
Demander une confirmation à chaque usage : ssh-add -c
ssh-add -c ~/.ssh/id_ed25519
Votre agent demande désormais confirmation sur votre propre écran à chaque utilisation de la clé, ce qui rend visible une demande inattendue. Si vous refusez, la connexion échoue :
sign_and_send_pubkey: signing failed for ED25519 "key" from agent: agent refused operation
Cela demande un programme ssh-askpass sur votre ordinateur, que vous devrez peut-être installer. Sous macOS, nous n'en avons trouvé aucun par défaut. Sans lui, testez avant de vous y fier.
Exposer moins de clés
- Lancez un agent séparé qui ne contient que la clé nécessaire, et redirigez celui-là avec
ForwardAgent /path/to/agent.sockdans le bloc de l'hôte. - Limitez la durée pendant laquelle les clés restent chargées avec
ssh-add -t 1h ~/.ssh/id_ed25519. - Utilisez une clé qui n'ouvre que ce dont ce travail a besoin, et pas votre clé principale.
- Regardez les contraintes de destination,
ssh-add -h, qui limitent où une clé peut être utilisée.
Rediriger uniquement vers des hôtes nommés
Host build-box
ForwardAgent yes
Ne mettez jamais ForwardAgent yes sous Host *. C'est désactivé par défaut, et c'est très bien ainsi. Un seul ssh négligent vers un serveur auquel vous ne faites pas entièrement confiance donnerait à ce serveur votre agent pour la durée de la session.
Quand c'est acceptable
C'est un compromis raisonnable quand toutes ces conditions sont réunies : vous faites confiance à tous ceux qui ont root sur cet hôte, et vous êtes sûr que l'hôte n'est pas compromis ; la session est courte ; et vous ne pouviez pas faire le travail avec -J ou une clé de déploiement. Évitez-le sur les serveurs partagés, sur les hôtes exposés à Internet gérés par d'autres, et sur tout ce à quoi vous ne confieriez pas votre portable déverrouillé.
Le désactiver sur un serveur
AllowAgentForwarding no
Avec cette ligne dans sshd_config, ssh -A s'est connecté normalement dans notre test, mais aucun socket n'est apparu. Le manuel précise que les utilisateurs ayant un accès shell peuvent encore installer leurs propres relais : voyez-y un réglage par défaut qui évite les accidents, et non une barrière solide.
Questions
Le transfert d'agent SSH est-il sûr ?
Seulement sur les serveurs où vous faites confiance à toute personne ayant root. Tant que vous êtes connecté, root peut utiliser vos clés pour se connecter ailleurs en votre nom. Il ne peut pas copier la clé privée.
Quelle différence entre ssh -A et ssh -J ?
-A laisse l'hôte distant utiliser votre agent. -J passe par un hôte de rebond jusqu'à la cible, et vos clés ne servent que depuis votre ordinateur : l'hôte de rebond n'a rien à exploiter.
Comment désactiver le transfert d'agent sur un serveur ?
Mettez AllowAgentForwarding no dans sshd_config et rechargez sshd. Un utilisateur avec un shell peut monter son propre relais, c'est donc un réglage contre les accidents, pas une barrière.
Sources
- ssh(1), l'option -A
- ssh_config(5), ForwardAgent
- ssh-add(1), manuel OpenBSD
- ssh-agent(1), manuel OpenBSD
- Notes de version d'OpenSSH 10.1 : emplacement du socket de l'agent