Transfert de port SSH pour les agents autonomes : des tunnels plus sûrs
Le transfert de port SSH pour les agents autonomes exige des routes strictement limitées, des accès qui expirent et des approbations traçables, capables de résister à une revue d'incident.

Le transfert de port SSH pour les agents autonomes demande une conception plus stricte que l'accès habituel des développeurs. Un tunnel peut transformer une base de données accessible uniquement depuis localhost, un panneau d'administration ou un service de préproduction en ressource qu'un agent atteint avec une simple commande SSH. Si l'agent possède des identifiants SSH trop larges, le tunnel n'est qu'un symptôme. Le vrai problème est que personne n'a limité la destination, la durée ou l'autorité associée à cette commande.
J'ai vu des équipes qualifier un tunnel de « temporaire » parce que quelqu'un avait saisi ssh -L dans un terminal. Le terminal est ensuite resté actif pendant plusieurs jours, son port est devenu une dépendance pour un autre processus et la personne qui l'avait ouvert était absente lorsque l'équipe de sécurité a demandé pourquoi un service proche de la production possédait un écouteur inexpliqué. Le travail autonome aggrave ce schéma, car l'agent peut réessayer, se reconnecter et utiliser un tunnel beaucoup plus régulièrement qu'un humain distrait.
L'approche sûre est simple : donner à l'agent un chemin de connexion étroitement limité, approuver une exposition temporaire précise, conserver assez de contexte pour la reconstituer plus tard et faire de la fermeture un événement contrôlable plutôt qu'une simple intention.
Un tunnel modifie l'accessibilité réseau, pas seulement le comportement de SSH
Un transfert de port SSH crée un écouteur à une extrémité de la connexion SSH et transporte son trafic vers une destination accessible depuis l'autre extrémité. Cet écouteur est un chemin d'accès. Le traiter comme un simple « accès SSH » fait disparaître la partie qui crée le risque : qui peut se connecter, où le trafic aboutit et ce qui peut y circuler.
Imaginons un agent exécuté sur un hôte de compilation qui doit interroger db-admin.internal.example sur le port 5432. Un transfert local peut rendre ce service accessible sous 127.0.0.1:15432 sur l'hôte de compilation. La base reste privée vis-à-vis d'Internet, mais chaque processus de cet hôte capable d'atteindre l'écouteur peut maintenant tenter une connexion. Le serveur SSH devient aussi une route autorisée vers la base.
Cela peut être acceptable. Ce n'est pas équivalent à autoriser l'agent à « utiliser SSH pour la maintenance ». L'approbation doit décrire exactement cette route :
- la charge de travail et l'hôte à l'origine de la connexion
- l'adresse et le port d'écoute
- l'hôte et le port de destination
- la raison de la route
- l'expiration et la personne qui approuve
Un transfert distant inverse l'emplacement de l'écouteur. Si un agent se connecte à une bastion et demande à celle-ci d'écouter sur le port 18080, un processus qui atteint cet écouteur peut recevoir du trafic renvoyé vers l'hôte de l'agent. Les transferts distants surprennent souvent les équipes, car ils peuvent exposer un service situé derrière un pare-feu sans ouvrir de règle entrante.
OpenSSH documente séparément ces modes dans ssh(1) : -L crée des transferts locaux, -R des transferts distants et -D un proxy SOCKS. Cette distinction est utile pour l'exploitation. N'approuvez pas le « transfert de port » comme une permission unique. Chaque mode expose un écouteur différent et exige des restrictions différentes.
Les transferts locaux, distants et dynamiques appellent des décisions différentes
Un transfert local convient généralement à une tâche d'agent lorsque celui-ci doit atteindre un service précis par l'intermédiaire d'un hôte relais contrôlé. L'écouteur se trouve du côté de l'agent et le serveur SSH se connecte à la destination interne. La commande est connue :
ssh -N \
-L 127.0.0.1:15432:db-admin.internal.example:5432 \
[email protected]
-N demande à SSH de ne pas exécuter de commande distante. Cela ne rend pas la connexion inoffensive. L'adresse 127.0.0.1 limite l'écouteur à l'hôte local, tandis que db-admin.internal.example:5432 indique la destination demandée. Ce sont deux propriétés distinctes et elles doivent toutes deux figurer dans l'enregistrement d'approbation.
Un transfert distant ne convient que si quelqu'un a explicitement choisi de créer un écouteur du côté distant. La commande suivante demande à la bastion d'écouter sur sa propre interface de bouclage et de transporter le trafic vers le port 8080 de la machine de l'agent :
ssh -N \
-R 127.0.0.1:18080:127.0.0.1:8080 \
[email protected]
Ne considérez pas automatiquement comme sûr un écouteur distant lié à l'interface de bouclage. Un processus local sur la bastion peut avoir bien plus de droits que la machine source de l'agent, et un autre utilisateur d'une bastion partagée peut l'atteindre. Examinez les utilisateurs et les processus locaux de l'hôte distant avant de l'autoriser.
Le transfert dynamique devrait être refusé par défaut aux agents autonomes :
ssh -N -D 127.0.0.1:1080 [email protected]
Cette commande démarre un écouteur SOCKS. Le client choisit ensuite les destinations au moyen de requêtes SOCKS, au lieu d'en nommer une dans la commande SSH. Les équipes apprécient cette solution parce qu'elle permet rapidement de faire fonctionner une interface web interne dans un navigateur ou un banc de test. Mais cette commodité supprime la limite de destination nécessaire au travail sans surveillance. Une personne chargée de la revue ne peut pas approuver une route unique et les restrictions SSH habituelles ne permettent pas de définir une liste utile pour un trafic SOCKS arbitraire.
Ne résolvez pas ce problème avec un formulaire d'approbation plus long. Refusez le transfert dynamique au compte de l'agent. Si la tâche exige plusieurs destinations, définissez chaque transfert séparément ou placez devant les services un proxy conçu pour cet usage, avec sa propre authentification et ses propres journaux.
L'adresse de liaison détermine qui peut utiliser l'écouteur
L'adresse de liaison fait partie de la décision de sécurité, car elle détermine quelles machines peuvent se connecter à l'écouteur du tunnel. Un transfert lié à l'interface de bouclage et un transfert lié à toutes les interfaces peuvent utiliser la même cible tout en créant des expositions complètement différentes.
Pour un transfert local, utilisez une adresse de bouclage explicite :
-L 127.0.0.1:15432:db-admin.internal.example:5432
Évitez de dépendre de la valeur par défaut. OpenSSH lie normalement les transferts locaux à l'interface de bouclage lorsqu'aucune adresse n'est indiquée, mais une adresse explicite rend la revue, les journaux et l'analyse d'incident moins ambigus. Elle évite aussi qu'une modification ultérieure de la configuration client change discrètement la portée de l'écouteur.
Voici la version dangereuse :
-L 0.0.0.0:15432:db-admin.internal.example:5432
Elle expose le port 15432 sur toutes les interfaces IPv4 de l'hôte client. Tout hôte capable d'atteindre le client peut tenter d'utiliser le tunnel. Un exécuteur de compilation situé dans un sous-réseau partagé peut ainsi devenir un pont vers une base interne, même si cette base n'accepte des connexions que depuis la bastion.
IPv6 demande la même attention. ::1 est l'adresse de bouclage, tandis que :: écoute sur toutes les interfaces IPv6. Vérifiez les deux familles d'adresses. J'ai vu des équipes confirmer que 127.0.0.1 était sûr, puis découvrir que l'automatisation avait aussi ouvert un écouteur IPv6 par une autre voie de configuration.
Pour les transferts distants, c'est le serveur SSH qui contrôle les adresses de liaison acceptées. Dans sshd_config, GatewayPorts influence le comportement de liaison des transferts distants. OpenSSH précise que ces transferts sont sinon liés à l'interface de bouclage par défaut, sous réserve de l'adresse demandée et de la politique du serveur. Conservez GatewayPorts no, sauf raison examinée d'autoriser des écouteurs distants plus larges. GatewayPorts clientspecified donne trop de contrôle aux clients pour un compte d'agent.
Après l'ouverture d'un transfert, inspectez l'écouteur sur la machine qui le possède. Sous macOS ou Linux, ce contrôle local est utile :
lsof -nP -iTCP:15432 -sTCP:LISTEN
La sortie doit afficher un processus ssh avec une adresse telle que 127.0.0.1:15432 ou ::1:15432. Si elle affiche *:15432, arrêtez la tâche et examinez la commande ainsi que la configuration client. Cette commande prouve uniquement l'adresse de l'écouteur local. Elle ne prouve pas que l'extrémité distante est limitée à la destination prévue.
Un compte SSH dédié doit exprimer la route autorisée
Un compte SSH dédié, accompagné de restrictions côté serveur, constitue la limite minimale raisonnable pour les tunnels d'agents. Un fichier de configuration client ne peut rien imposer à un agent capable de modifier ses propres arguments. Placez les limites là où le serveur SSH accepte la connexion.
Pour un compte limité aux transferts locaux, commencez par un bloc de correspondance comme celui-ci dans sshd_config :
Match User agent-db-tunnel
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitTTY no
X11Forwarding no
AllowAgentForwarding no
AllowStreamLocalForwarding no
AllowTcpForwarding local
PermitOpen db-admin.internal.example:5432
GatewayPorts no
PermitUserEnvironment no
AllowTcpForwarding local autorise les transferts locaux et refuse les transferts distants. PermitOpen indique la destination que ce compte peut demander. Cette restriction est importante, car une commande de transfert local peut sinon viser n'importe quel hôte et port accessibles depuis la bastion. Sans PermitOpen, un agent qui a légitimement besoin de la base peut aussi demander un transfert vers une API d'administration, un cache, un service de métadonnées ou un autre serveur SSH.
Utilisez les noms d'hôte avec prudence. Le serveur SSH résout la destination, donc le nom de PermitOpen doit être résolu de son côté. Faites en sorte que ce nom soit stable et géré par votre infrastructure. Si un nom DNS peut pointer vers des adresses arbitraires, la configuration semble restrictive alors que sa destination réelle change. Une adresse IP peut être plus claire pour un équipement fixe, mais un nom d'hôte convient lorsque le contrôle du DNS interne et la propriété du service sont rigoureux.
Le manuel sshd_config(5) d'OpenSSH décrit PermitOpen comme une restriction de destination sous la forme host:port. Cette directive ne transforme pas le compte en moteur de politiques. Elle remplit précisément une fonction : refuser toute demande de transfert dont la destination ne figure pas dans la liste. Gardez la même précision dans la conception du compte.
Ne donnez pas de shell à ce compte sous prétexte que « l'agent ne l'utilisera pas ». Supprimez réellement cette possibilité. Un compte dédié doit correspondre à un seul rôle de connexion. Vous pouvez configurer sa clé publique autorisée avec une commande forcée qui quitte immédiatement si le compte a besoin d'une protection supplémentaire contre l'utilisation interactive, mais testez cette décision avec les transferts de votre environnement. Certains modèles de commande forcée et certains wrappers perturbent les sessions SSH attendues. Une restriction défectueuse conduit souvent quelqu'un à supprimer tout le bloc dans l'urgence.
Évitez également le transfert d'agent. AllowAgentForwarding no empêche le serveur connecté de demander à l'agent SSH du client de signer des demandes d'authentification. Un compte de tunnel SSH doit transporter du trafic, pas devenir un point de passage vers d'autres hôtes.
Pour une cible qui expose deux services légitimes, indiquez deux entrées PermitOpen explicites. N'utilisez pas de caractère générique et ne remplacez pas le compte par une bastion générale simplement pour éviter de créer un compte supplémentaire. Un compte de plus coûte moins cher que l'explication d'un agent de développement capable d'atteindre tout un sous-réseau interne.
Temporaire signifie expiration imposée et fermeture propre
Un tunnel n'est temporaire que si quelque chose, en plus des bonnes intentions, le ferme. SSH maintient une connexion jusqu'à ce que le client la ferme, que le réseau tombe ou qu'un délai d'attente l'interrompe. Un agent autonome peut laisser un processus actif après la réussite, l'échec ou l'expiration d'un test.
Imposez à chaque tâche une durée maximale de session, hors du contrôle de l'agent. Un exécuteur peut utiliser timeout lorsque cette commande est disponible :
timeout 20m ssh -N \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-L 127.0.0.1:15432:db-admin.internal.example:5432 \
[email protected]
ExitOnForwardFailure=yes empêche la tâche de continuer lorsque SSH ne peut pas créer l'écouteur demandé. Sans cette option, l'agent peut continuer et signaler une erreur applicative confuse au lieu d'un échec de configuration du tunnel. Les paramètres de maintien de connexion font quitter SSH après plusieurs réponses manquantes, ce qui aide lorsqu'une machine cliente perd silencieusement sa connectivité réseau. Ils ne remplacent pas la limite de 20 minutes.
macOS ne fournit pas par défaut la commande GNU timeout. Utilisez le mécanisme de délai de votre exécuteur, un processus supervisé avec une échéance ou un petit wrapper qui envoie TERM puis vérifie la fermeture du processus. Ne remplacez pas une échéance absente par une tâche cron qui tue les « anciens SSH ». Elle interromprait des travaux sans rapport et vous empêcherait de prouver quelle connexion a été arrêtée.
Demandez aussi à la tâche de fermer son tunnel dans son propre nettoyage. Pour un processus qu'elle a démarré, conservez son PID, envoyez TERM à la fin de la tâche, attendez brièvement puis vérifiez que l'écouteur a disparu avec lsof ou ss. L'échéance couvre les plantages ; le nettoyage gère la fin normale.
Le multiplexage des connexions exige une attention particulière. Avec ControlMaster et un ControlPath partagé, plusieurs appels SSH peuvent réutiliser une même connexion maître. Cela accélère une session dans un terminal humain. Pour un agent, cela brouille la propriété et l'expiration : une tâche peut hériter d'une connexion approuvée pour une autre et la fermeture d'un client peut ne pas fermer le maître. Désactivez le multiplexage pour le compte du tunnel ou générez un chemin de contrôle unique pour chaque tâche approuvée.
Un processus de maintenance qui a besoin d'un accès récurrent doit demander des sessions récurrentes mais limitées séparément. Ne laissez pas un tunnel ouvert parce qu'il serait pénible de le recréer. Les quelques secondes économisées au démarrage deviennent une source d'ambiguïté chaque fois qu'une personne enquête sur une connexion inattendue.
Une approbation doit décrire une connexion reconstituable
Un enregistrement d'approbation doit permettre de répondre à trois questions : qui a autorisé la route, ce qui l'a ouverte et si elle est restée dans les limites annoncées. Un commentaire générique tel que « accès agent approuvé » n'est pas une preuve. Il n'identifie ni l'écouteur, ni la destination, ni la durée.
Enregistrez l'approbation avant le démarrage du tunnel. Capturez l'identité de la personne qui approuve, l'horodatage, l'identifiant de la tâche ou de l'exécution, l'identité du processus agent, la machine source, le compte SSH dédié et l'empreinte de la clé publique. Enregistrez ensuite le transfert demandé en entier : direction, adresse de liaison, port d'écoute, hôte de destination, port de destination, objectif et expiration.
L'enregistrement du résultat doit comporter ses propres champs. Indiquez si SSH a créé le transfert, l'identifiant du processus client, l'heure de début, le statut de sortie final, l'heure de fermeture et la raison de celle-ci. Une expiration, un nettoyage normal, une révocation par un opérateur et une défaillance réseau n'ont pas le même sens lors d'une revue.
Utilisez des enregistrements structurés plutôt qu'un texte qui oblige quelqu'un à déduire les champs. Cette structure suffit à de nombreux systèmes internes :
{
"run_id": "run-7c31",
"approved_by": "oncall-engineer",
"approved_at": "2025-04-12T14:03:00Z",
"ssh_account": "agent-db-tunnel",
"direction": "local",
"listen": "127.0.0.1:15432",
"destination": "db-admin.internal.example:5432",
"expires_at": "2025-04-12T14:23:00Z",
"purpose": "run migration compatibility check"
}
Les identifiants de cet exemple sont des valeurs fictives, pas un schéma à recopier exactement. La rigueur compte davantage que le nom des champs : un même enregistrement doit relier une personne, un processus, une route et une période.
Ne laissez pas le même agent générer l'approbation et la considérer comme une autorisation humaine. L'agent peut expliquer pourquoi il souhaite une connexion, mais une personne ou un processus gouverné séparément doit décider de l'autoriser. Si l'action est assez routinière pour être approuvée automatiquement, encodez cette décision dans une définition de tâche étroite avec une expiration et conservez la version de la règle qui l'a autorisée.
La fatigue liée aux approbations est un défaut de conception. Demander à quelqu'un de valider chaque paquet crée des clics dépourvus de sens. Une approbation par route temporaire et précise donne à la personne un objet concret à évaluer. Gardez la demande courte, mais incluez l'adresse de liaison et la destination exacte. Ces deux chaînes détectent un nombre étonnant de mauvaises demandes.
Gardez les identifiants hors de l'agent et l'autorité hors de son prompt
Un agent autonome doit demander une connexion, pas recevoir une clé privée capable de créer ensuite des connexions arbitraires. Dès qu'un agent possède une clé SSH générale dans son environnement de processus ou son espace de travail, il peut la copier, appeler un autre client SSH, l'utiliser après la fin de la tâche approuvée ou la transmettre à un outil que vous n'aviez pas prévu de faire fonctionner avec cette confiance. Un prompt qui dit « utilise-la uniquement pour la base » ne limite aucune de ces actions.
Une meilleure conception place les identifiants SSH dans une frontière d'exécution distincte. L'agent envoie une action demandée avec les champs de route. La frontière vérifie que le coffre est disponible, que la session est autorisée et que l'identifiant demandé dispose de l'approbation nécessaire. Elle effectue l'action SSH et renvoie le résultat sans transmettre la clé privée à l'agent.
Sallyport utilise ce modèle sous macOS : son utilitaire sp-ssh intégré effectue les actions SSH tandis que les clés restent dans le coffre chiffré de l'application et ne parviennent pas à l'agent MCP.
Cette distinction compte lors de l'analyse d'un échec. La conservation des identifiants répond à la question « l'agent pouvait-il réutiliser le secret ailleurs ? ». La restriction de route répond à « ce compte pouvait-il atteindre une destination non approuvée ? ». L'approbation répond à « qui a autorisé cette utilisation précise ? ». Les équipes réunissent souvent ces trois contrôles en un seul, puis découvrent que leur audit indique qu'une clé a été utilisée sans préciser la route qu'elle a rendue possible.
Rendez l'interface de demande plus étroite que les arguments SSH bruts. Acceptez des champs tels que destination_host, destination_port, listen_address, listen_port et max_duration. Refusez les options fournies par le client qui modifient le proxy, la direction du transfert, l'exécution de commandes distantes, les fichiers d'identité ou les sockets de contrôle. Si vous acceptez une chaîne de commande ssh arbitraire, vous déléguez l'interprétation de la politique à l'analyse de chaînes. Cette approche échoue dès que quelqu'un ajoute -R, -D, ProxyCommand ou un second transfert.
N'offrez pas de shell général comme solution de secours à un workflow de tunnel. L'agent n'a pas besoin d'exécuter ssh en mode interactif lorsque l'action consiste à créer un canal limité. Les actions étroites sont plus faciles à approuver et à révoquer.
Les preuves d'audit doivent résister à une revue hostile
Les journaux de tunnel ne sont utiles que si un agent compromis ou un processus local ne peut pas les réécrire après coup. Des journaux en texte brut à côté de l'espace de travail de l'agent sont pratiques, mais ils prouvent peu de choses lorsque le même acteur peut modifier à la fois la commande du tunnel et son historique.
Enregistrez séparément l'événement d'approbation, la demande, le résultat d'exécution et le résultat de fermeture, avec un identifiant d'exécution commun. Conservez les champs de la demande originale au lieu d'enregistrer uniquement une ligne de commande générée. Une ligne de commande peut dissimuler des valeurs dans un fichier de configuration ou omettre des valeurs par défaut qui ont influencé l'écouteur.
Recueillez des éléments de corroboration à plusieurs endroits. Les journaux SSH de la bastion peuvent montrer les authentifications acceptées et les échecs de transfert. L'exécuteur peut montrer la création et la fin du processus. Le service de destination peut montrer une connexion depuis la bastion. Aucun de ces éléments n'explique seul tout l'événement, mais leur rapprochement révèle les contradictions.
Par exemple, une approbation peut autoriser 127.0.0.1:15432 vers une base pendant 20 minutes. Si le journal client indique une fermeture à 14 h 23, mais que la destination observe du trafic à 15 h 10 depuis la bastion, enquêtez immédiatement. L'agent a peut-être ouvert une autre connexion, réutilisé une session maître partagée, ou quelqu'un utilise peut-être un autre chemin avec le même compte.
Sallyport projette les journaux de session et d'appels individuels depuis un journal d'audit chiffré et chaîné par hachage, et sp audit verify vérifie cette chaîne hors ligne sans exiger la clé du coffre. C'est une propriété plus solide qu'un fichier journal qu'un processus agent peut modifier, même si elle ne dispense pas de restrictions de compte strictes.
Effectuez la vérification pendant les revues, et pas uniquement après un incident. Une chaîne détectant les altérations indique si l'historique enregistré est continu. Elle ne peut pas vous dire si vous avez enregistré assez de champs au départ. Décidez de ce que vous devrez savoir lors d'une mauvaise journée, puis assurez-vous que ces champs entrent dans l'événement avant le début de la connexion.
Révoquez le chemin avant d'examiner l'histoire
Lorsque vous soupçonnez un tunnel incorrect ou détourné, interrompez d'abord le chemin de connexion. L'enquête peut attendre quelques minutes ; une route exposée peut transférer des données ou permettre un déplacement latéral pendant que les équipes débattent du journal faisant autorité.
Terminez le processus client et confirmez que son écouteur a disparu. Désactivez le compte SSH dédié ou supprimez sa clé publique du serveur qui accepte la connexion. Si le service cible utilise un identifiant qui a transité par le tunnel et qui a pu être exposé à un processus non fiable, faites tourner cet identifiant selon la procédure du service. Ne faites pas tourner des identifiants sans rapport simplement parce qu'un tunnel existait.
Préservez ensuite les preuves. Sauvegardez l'approbation, la route demandée, les journaux de processus, les journaux du serveur SSH, les enregistrements de connexion du service de destination et le résultat de la fermeture. Enregistrez les heures dans un même fuseau, de préférence UTC. Les revues d'incident perdent beaucoup de temps lorsqu'un exécuteur utilise l'heure locale, une bastion UTC et une application des horodatages sans fuseau.
Vérifiez l'existence d'un second écouteur avant de déclarer l'événement contenu. Sur l'hôte de l'agent, examinez le port demandé et les processus de transfert voisins. Sur la bastion, examinez les sessions SSH actives et les journaux d'authentification du compte dédié. À la destination, recherchez les connexions commencées après l'expiration prévue. Le but est de trouver les chemins d'accès encore actifs, pas de produire rapidement un récit bien ordonné.
Si une approbation humaine a permis la mauvaise route, corrigez d'abord la surface de demande. Un meilleur écran de revue qui accepte toujours des options SSH arbitraires reproduira la même erreur. Si une restriction serveur a échoué, testez la commande exacte qui devait être refusée après l'avoir corrigée et conservez la sortie d'échec. Les contrôles gagnent la confiance lorsque vous confirmez qu'ils refusent bien la route qu'ils doivent refuser.
Testez les refus avant qu'un agent ne dépende du tunnel
Une conception de tunnel n'est prête qu'après le test de la connexion approuvée et des variantes interdites. Les tests du parcours nominal détectent les fautes de frappe. Les tests de refus montrent si la frontière existe réellement.
Utilisez un compte hors production et tentez un transfert qui doit fonctionner :
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:15432:db-admin.internal.example:5432 \
[email protected]
Tentez ensuite une destination que PermitOpen n'autorise pas :
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:15433:admin-api.internal.example:443 \
[email protected]
La seconde commande doit échouer pendant la configuration du transfert. Capturez la sortie client et l'entrée du journal serveur. Tentez ensuite -R et -D ; les deux doivent échouer pour un compte configuré avec AllowTcpForwarding local. Enfin, demandez un écouteur non local avec 0.0.0.0 et vérifiez que votre frontière de demande le refuse avant l'exécution de SSH, ou que l'environnement local empêche l'exposition que vous voulez éviter.
Testez l'expiration avec une durée courte. Démarrez le tunnel approuvé, laissez l'échéance du superviseur se déclencher et vérifiez trois éléments : le processus SSH quitte, lsof ne trouve plus l'écouteur et l'enregistrement de fermeture indique l'échéance au lieu de prétendre que la tâche s'est terminée normalement. Ce petit exercice révèle le problème des processus orphelins avant qu'une tâche de production ne dépende d'un tunnel qui ne se ferme jamais.
Gardez une règle simple lorsque la pression monte : un agent autonome peut recevoir uniquement la route nécessaire à sa tâche actuelle, pendant une durée limitée et sous une approbation nominative. Si votre configuration ne peut pas énoncer cette route en une ligne et prouver ensuite sa fermeture, l'agent dispose de plus d'autorité réseau que la tâche ne le justifie.
FAQ
Quelle est la différence entre un transfert de port SSH local et distant ?
Un transfert local écoute sur la machine qui lance SSH et envoie les connexions via le serveur SSH vers une destination accessible depuis ce serveur. Un transfert distant fait l'inverse : le serveur SSH écoute et renvoie le trafic via le client. Considérez les deux comme des changements d'exposition réseau, car chaque direction peut franchir une limite que votre pare-feu n'était pas censé franchir.
Un tunnel SSH est-il sûr si je le lie à 127.0.0.1 ?
Non. Une liaison sur l'adresse de bouclage limite les machines qui peuvent se connecter au port d'écoute, mais elle ne limite pas ce que le serveur SSH peut atteindre de l'autre côté. Restreignez à la fois l'adresse d'écoute et la destination autorisée dans la configuration du compte SSH.
Faut-il autoriser un agent autonome à utiliser ssh -D ?
Le transfert dynamique crée un proxy SOCKS. Le client peut donc demander de nombreuses destinations au lieu d'un service précis. Cela rend le dispositif difficile à examiner, à journaliser correctement et à restreindre avec les règles SSH habituelles. Ne l'autorisez pas pour un agent autonome, sauf si vous disposez d'une passerelle distincte et strictement contrôlée à cette fin.
Comment limiter un compte SSH à un seul service interne ?
Utilisez un compte dédié, désactivez l'accès au shell et l'allocation d'un pseudo-terminal, désactivez le transfert d'agent et n'autorisez que des paires hôte-port précises avec PermitOpen. Définissez aussi une durée de session en dehors de SSH, car la configuration SSH ne décide pas à elle seule du moment où un tunnel légitime doit se fermer.
Que doit contenir l'enregistrement d'approbation d'un tunnel SSH ?
Enregistrez l'identité de la personne qui approuve, le processus ou la charge de travail de l'agent, la machine source, le compte SSH, la direction du tunnel, l'adresse d'écoute, l'hôte et le port de destination, l'heure d'ouverture, l'expiration prévue et le résultat de la fermeture. Une entrée qui dit seulement « SSH approuvé » ne sera d'aucune utilité lorsqu'une personne devra comprendre l'exposition créée.
Combien de temps un tunnel SSH temporaire doit-il rester ouvert ?
Utilisez un tunnel par tâche lorsque celle-ci a un objectif précis et une durée courte. Les tunnels longs sont plus difficiles à attribuer, favorisent la réutilisation par des tâches sans rapport et restent souvent ouverts après la modification qui les justifiait. Si un service a besoin d'une connectivité permanente, mettez en place un accès géré au lieu de considérer une session SSH permanente comme temporaire.
AllowTcpForwarding local empêche-t-il l'accès à tous les hôtes internes ?
AllowTcpForwarding local autorise les transferts locaux, mais bloque les transferts distants. Cette directive ne limite pas à elle seule les destinations. Associez-la donc à des entrées PermitOpen host:port. Placez ces restrictions sur le compte qui accepte la connexion, et pas uniquement dans une configuration client que l'agent peut modifier.
Puis-je donner un mot de passe SSH à un agent IA au lieu d'utiliser une passerelle ?
Un mot de passe ne fournit pas à l'agent un parcours d'action limité et auditable. Il lui permet généralement d'ouvrir un shell, de copier des données, de créer des transferts arbitraires et d'agir sans véritable trace d'approbation. Utilisez un compte dont les règles côté serveur expriment précisément la connexion que vous voulez autoriser.
Comment vérifier qu'un transfert de port SSH s'est réellement fermé ?
ss ou lsof indiquent si un processus écoute localement, et la sortie de débogage SSH peut confirmer le transfert demandé. Aucun de ces éléments ne prouve que le serveur n'a accepté qu'une destination approuvée ni que le tunnel s'est ensuite fermé. Vérifiez aussi la configuration du serveur, l'enregistrement de session et les journaux du service de destination.
Que faire si un agent ouvre le mauvais tunnel SSH ?
Tuez le processus client SSH, révoquez ou désactivez son compte dédié et supprimez l'accès au service de destination si vous soupçonnez un abus. Conservez ensuite les enregistrements d'approbation et de connexion avant de modifier d'autres paramètres. Ne faites pas tourner automatiquement tous les identifiants, sauf si le tunnel transportait un identifiant qu'un processus non fiable pouvait intercepter.