Implémentation du transfert de port SSH local et distant pour le tunneling
Déverrouillez un accès réseau sécurisé et le contournement de pare-feu à l'aide du transfert de port SSH. Ce guide complet détaille la mise en œuvre pratique des techniques de tunneling SSH local (`-L`) et distant (`-R`). Apprenez la syntaxe essentielle, comprenez les différences clés entre l'accès aux services distants et l'exposition de services locaux, et découvrez des exemples clairs pour des tâches telles que la sécurisation des connexions de base de données ou le partage d'environnements de développement. Inclut les meilleures pratiques critiques pour créer des tunnels d'arrière-plan persistants et sécurisés à l'aide de l'authentification par clé.
Implémentation du transfert de port SSH local et distant pour le tunneling
Le transfert de port SSH est l'un de ces outils que vous oubliez jusqu'à ce qu'un pare-feu, un sous-réseau privé ou un réseau fournisseur maladroit bloque le chemin simple. Ensuite, il devient la solution propre la plus rapide. Vous pouvez l'utiliser pour atteindre une base de données via un hôte bastion, tester une page d'administration privée depuis votre ordinateur portable, ou exposer un serveur de développement local à une machine qui ne peut pas atteindre directement votre ordinateur portable.
L'idée de base est simple : SSH ouvre un port d'écoute d'un côté de la connexion et achemine le trafic via la session SSH cryptée vers une destination de l'autre côté. La partie qui pose problème aux gens est la direction. Le transfert local avec -L permet à votre machine d'atteindre quelque chose près du serveur SSH. Le transfert distant avec -R permet à quelque chose près du serveur SSH d'atteindre quelque chose près de votre machine.
Transfert local : amener un service distant sur votre ordinateur portable
Utilisez le transfert local lorsque le service dont vous avez besoin est accessible depuis le serveur SSH, mais pas depuis votre poste de travail.
ssh -L 15432:db.internal.example:5432 [email protected]
Après cette connexion, votre ordinateur portable écoute sur 127.0.0.1:15432. Lorsque vous pointez psql, DBeaver ou une configuration d'application vers ce port local, SSH envoie le trafic vers bastion.example.com, et le bastion ouvre une connexion vers db.internal.example:5432.
Lisez la commande de gauche à droite :
port local sur ma machine : hôte de destination tel que vu par le serveur SSH : port de destination
Ce "tel que vu par le serveur SSH" est important. Si la base de données s'appelle db.internal.example uniquement à l'intérieur du réseau privé, votre ordinateur portable n'a pas besoin de résoudre ce nom. Le bastion le fait. Si la base de données écoute uniquement sur localhost sur le bastion, utilisez plutôt ceci :
ssh -L 15432:127.0.0.1:5432 [email protected]
Le transfert local est généralement la valeur par défaut la plus sûre car le port d'écoute se trouve sur votre poste de travail. Par défaut, OpenSSH lie les ports transférés localement à l'interface de bouclage, donc les autres machines sur votre Wi-Fi ou votre réseau de bureau ne peuvent pas utiliser le tunnel. Vous pouvez être explicite :
ssh -L 127.0.0.1:15432:db.internal.example:5432 [email protected]
Évitez de lier à 0.0.0.0 sauf si vous voulez vraiment partager le tunnel avec d'autres hôtes. Une commande comme celle-ci fait de votre ordinateur portable un proxy vers la base de données privée pour quiconque peut atteindre le port 15432 sur votre ordinateur portable :
ssh -L 0.0.0.0:15432:db.internal.example:5432 [email protected]
Cela peut être utile dans un laboratoire. C'est rarement ce que vous voulez sur un poste de travail normal.
Transfert distant : exposer un service local via le serveur
Le transfert distant inverse le côté d'écoute. Utilisez-le lorsqu'un service s'exécute sur votre machine, mais que quelqu'un ou quelque chose près du serveur SSH doit l'atteindre.
ssh -R 18080:127.0.0.1:3000 [email protected]
Cela demande à public.example.com d'écouter sur le port 18080. Les connexions à ce port sont renvoyées via SSH vers 127.0.0.1:3000 sur votre ordinateur portable. C'est pratique lorsque vous testez un récepteur de webhook, partagez une démo temporaire ou déboguez un rappel d'un système de staging qui ne peut pas appeler directement votre ordinateur portable.
Il y a une surprise courante : les ports transférés à distance se lient généralement à la boucle locale sur le serveur SSH par défaut. Cela signifie que curl http://127.0.0.1:18080 fonctionne lorsqu'il est exécuté sur public.example.com, mais http://public.example.com:18080 depuis votre navigateur peut ne pas fonctionner.
Pour rendre un port transféré à distance accessible depuis d'autres machines, le serveur SSH doit le permettre. Dans /etc/ssh/sshd_config, le paramètre pertinent est généralement :
GatewayPorts clientspecified
Ensuite, vous pouvez demander une liaison publique :
ssh -R 0.0.0.0:18080:127.0.0.1:3000 [email protected]
Utilisez cela avec précaution. Vous publiez un service local via le serveur. Mettez un pare-feu devant, utilisez un port aléatoire élevé et n'exposez pas d'outils d'administration, de bases de données de développement ou d'applications non authentifiées à Internet.
Gardez les tunnels ennuyeux et fiables
Pour un tunnel de longue durée, vous ne voulez généralement pas de shell sur l'hôte distant :
ssh -N -L 15432:db.internal.example:5432 [email protected]
-N signifie "n'exécutez pas de commande distante." Ajoutez des keepalives lorsque le tunnel traverse NAT, VPN ou des équilibreurs de charge cloud qui abandonnent les sessions TCP inactives :
ssh -N \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-L 15432:db.internal.example:5432 \
[email protected]
Pour une utilisation sans surveillance, préférez un service systemd utilisateur, autossh ou votre superviseur de processus plutôt qu'une commande ssh -f nue. L'exécution en arrière-plan avec -f fonctionne, mais elle rend les démarrages échoués et les tunnels obsolètes plus difficiles à remarquer.
ssh -fN -L 15432:db.internal.example:5432 [email protected]
Si vous utilisez -fN, testez d'abord la même commande sans -f. Les invites de mot de passe, les invites de clé d'hôte inconnue et les conflits de ports sont beaucoup plus faciles à diagnostiquer au premier plan.
Liste de vérification de dépannage
Lorsqu'un tunnel se connecte mais que l'application échoue toujours, vérifiez chaque saut au lieu de deviner.
D'abord, confirmez que l'écouteur local existe :
ss -ltnp | grep 15432
Ensuite, testez la destination depuis le serveur SSH :
ssh [email protected] 'nc -vz db.internal.example 5432'
Si cela échoue, le transfert SSH n'est pas le problème. Le bastion ne peut pas atteindre le service, le nom ne se résout pas là, un groupe de sécurité bloque le port, ou le service est lié à la mauvaise interface.
Si l'écouteur ne démarre pas, le port local peut déjà être utilisé :
lsof -iTCP:15432 -sTCP:LISTEN
Si le transfert distant échoue avec un message comme remote port forwarding failed, le serveur peut bloquer le transfert TCP. Vérifiez AllowTcpForwarding dans sshd_config, et vérifiez si le port demandé est déjà pris.
Habitudes de sécurité qui valent la peine d'être conservées
Utilisez l'authentification par clé et restreignez le compte utilisé pour les tunnels. Pour un utilisateur de tunnel dédié, vous pouvez combiner un accès shell limité, des règles de pare-feu et des options SSH telles que PermitOpen ou PermitListen selon la direction dont vous avez besoin. Ces contrôles empêchent un tunnel de commodité de se transformer en accès réseau large.
Nommez les tunnels dans vos notes ou runbooks par intention, pas seulement par commande. "Ordinateur portable 15432 vers réplica de rapport de production via bastion" est plus facile à auditer qu'une ligne ssh -L mystérieuse dans l'historique du shell.
Le transfert local vous aide à atteindre l'intérieur. Le transfert distant permet aux autres de revenir vers vous. Une fois que cette distinction est claire, la plupart des problèmes de tunneling SSH deviennent une question de vérifier quel côté écoute, quel côté résout la destination et quel pare-feu se trouve entre eux.
Quelques modèles réels que vous verrez
Un modèle de production courant est le tunnel de maintenance de base de données. Vous avez un réplica de rapport dans un sous-réseau privé, un hôte bastion avec un accès SSH strict et un outil d'analyse sur votre ordinateur portable. Le transfert local s'adapte parfaitement :
ssh -N -L 127.0.0.1:15432:reporting-db.internal:5432 [email protected]
L'application sur votre ordinateur portable doit utiliser 127.0.0.1, pas le nom d'hôte de la base de données privée. Si l'outil insiste sur la vérification du nom d'hôte SSL par rapport à l'hôte de la base de données, vous devrez peut-être vous connecter avec le nom d'hôte de la base de données et ajouter une entrée d'hôtes locale, ou configurer le client avec le bon mode SSL. Le tunnel ne déplace que les octets TCP ; il ne réécrit pas les détails du protocole de base de données.
Un autre modèle est un récepteur de webhook temporaire :
ssh -N -R 127.0.0.1:19090:127.0.0.1:9090 [email protected]
Dans cette version, le port transféré est intentionnellement utilisable uniquement depuis la passerelle elle-même. Vous pourriez ensuite configurer un service de staging sur la passerelle pour appeler http://127.0.0.1:19090/hook. C'est plus sûr que de publier le port sur tout le réseau.
Pour une démo publique courte, utilisez une liaison publique uniquement après avoir ajouté une règle de pare-feu :
ssh -N -R 0.0.0.0:19090:127.0.0.1:3000 [email protected]
Ensuite, restreignez la passerelle :
sudo ufw allow from 203.0.113.40 to any port 19090 proto tcp
Sans cette restriction, quiconque peut atteindre la passerelle peut essayer le service transféré.
Ce que le tunneling SSH ne résout pas
Le transfert SSH ne remplace pas l'authentification de service. Si la base de données accepte les connexions locales sans mot de passe, un tunnel peut étendre cette limite de confiance faible plus loin que prévu. Si une application de développement locale n'a pas de page de connexion, le transfert distant peut la publier telle quelle.
Il ne rend pas non plus une destination instable fiable. Si le bastion ne peut pas résoudre le nom interne, si le service est en panne, ou si un groupe de sécurité bloque le chemin, le tunnel peut toujours s'établir avec succès pendant que l'application échoue. C'est pourquoi tester depuis le serveur SSH est si utile.
Enfin, les tunnels sont faciles à oublier. Un tunnel obsolète sur un hôte de saut partagé peut laisser un port inattendu ouvert. Pour tout ce qui est de longue durée, mettez la commande dans un fichier de service avec un nom, un propriétaire et une politique de redémarrage clairs. Pour tout ce qui est temporaire, fermez-le lorsque le travail est terminé et vérifiez que l'écouteur a disparu avec ss -ltnp.