6 points par GN⁺ 2024-09-20 | 1 commentaires | Partager sur WhatsApp
  • Le tunneling SSH transporte du trafic TCP sur une connexion SSH sécurisée et sert à ouvrir en toute sécurité des chemins d’accès restreints, par exemple pour chiffrer des protocoles legacy, accéder à des panneaux d’administration ou joindre des serveurs derrière un NAT
  • Côté serveur, AllowTcpForwarding yes est nécessaire ; pour ouvrir un port sur une interface autre que loopback, il faut configurer GatewayPorts yes et redémarrer le serveur SSH
  • ssh -J, ssh -L, ssh -R et ssh -D servent respectivement au jump host, à la redirection locale, à la redirection distante et à la redirection dynamique basée sur SOCKS5
  • Pour garder un tunnel en arrière-plan, utilisez ssh -fN ; la détection des coupures se règle avec des paramètres de heartbeat comme ClientAliveInterval et ClientAliveCountMax
  • Le tunneling SSH ne prend pas directement en charge UDP, et TCP-over-TCP peut entraîner des problèmes de latence et de débit ; il s’agit donc davantage d’un outil pour ouvrir des chemins TCP précis que d’une alternative au VPN

Dans quels cas utiliser le tunneling SSH

  • Le tunneling SSH et la redirection de ports transmettent du trafic TCP via une connexion SSH, du client vers le serveur ou du serveur vers le client
  • Il est possible d’utiliser des ports TCP et des sockets UNIX, mais les exemples se concentrent sur les ports TCP
  • Les usages typiques se répartissent entre sécurité, dépannage et contournement de connexion
    • Sécurité
      • Chiffrer des connexions non sécurisées comme FTP ou des protocoles legacy
      • Accéder à un panneau d’administration web via un tunnel SSH basé sur l’authentification par clé publique
      • N’ouvrir que le port 22, sans exposer de ports supplémentaires comme 80/443
    • Dépannage
      • Contourner un pare-feu ou un filtre de contenu
      • Choisir un autre chemin réseau
    • Connexion
      • Accéder à un serveur situé derrière un NAT
      • Entrer depuis Internet vers un serveur interne via un jump host
      • Exposer un port local sur Internet

Paramètres à vérifier avant la redirection de ports

  • Les options des exemples peuvent être combinées et configurées selon l’environnement
  • Si bind_address n’est pas spécifié, la valeur par défaut est localhost
  • Les utilisateurs locaux et distants doivent disposer des droits nécessaires pour ouvrir des ports sur chaque machine
    • Les ports 0-1024 nécessitent des droits root en l’absence de configuration particulière
    • Les autres ports peuvent aussi être configurés par un utilisateur standard
    • Les pare-feu côté client et réseau doivent également être ouverts selon le chemin de redirection
  • La redirection de ports doit être activée sur le serveur SSH
    • AllowTcpForwarding yes
    • Elle est souvent activée par défaut, mais il faut vérifier la configuration du serveur
  • Pour rediriger un port vers une interface autre que 127.0.0.1, activez GatewayPorts sur le serveur SSH
    • GatewayPorts yes
    • Après modification, le service du serveur SSH doit être redémarré

Jump host SSH et tunnels à plusieurs sauts

  • ssh -J s’utilise pour se connecter de manière transparente à un hôte distant en passant par un ou plusieurs hôtes intermédiaires
ssh -J user@REMOTE-MACHINE:22 -p 22 user@10.99.99.1
  • Lorsque le port par défaut 22 est utilisé, l’indication du port peut être omise
  • En utilisant REMOTE-MACHINE comme jump host, la connexion apparaît comme suit
[user@REMOTE-MACHINE]$ ss | grep -i ssh
tcp ESTAB 0 0 167.135.173.108:ssh 192.160.140.207:45960
tcp ESTAB 0 0 10.99.99.2:49770 10.99.99.1:ssh
  • Les rôles des adresses de l’exemple sont les suivants
    • 167.135.173.108 : IP publique de REMOTE-MACHINE
    • 192.160.140.207 : IP publique de LOCAL-MACHINE
    • 10.99.99.2 : IP interne de REMOTE-MACHINE
    • 10.99.99.1 : IP interne de REMOTE-WEBAPP
  • Pour utiliser plusieurs jump hosts, séparez-les par des virgules
ssh -J user@REMOTE-MACHINE:22,user@ANOTHER-REMOTE-MACHINE:22 -p 22 user@10.99.99.1

Redirection de port locale

  • La redirection de port locale utilise l’option ssh -L
  • Le premier exemple transmet 10.10.10.1:8001 de LOCAL-MACHINE vers localhost:8000 sur REMOTE-MACHINE
ssh -L 10.10.10.1:8001:localhost:8000 user@REMOTE-MACHINE
  • Sur REMOTE-MACHINE, le journal d’accès d’un serveur web lié uniquement à 127.0.0.1 ressemble à ceci
127.0.0.1 - - [30/Dec/2022 18:05:15] "GET / HTTP/1.1" 200
  • Cette requête est initiée depuis LOCAL-MACHINE
  • Le second exemple transmet le port local 8001 vers 10.99.99.1:8000 via REMOTE-MACHINE
ssh -L 8001:10.99.99.1:8000 user@REMOTE-MACHINE
  • Dans le journal d’accès du serveur web de REMOTE-WEBAPP, la requête apparaît comme venant de l’IP interne de REMOTE-MACHINE
10.99.99.2 - - [30/Dec/2022 21:28:42] "GET / HTTP/1.1" 200

Redirection de port distante

  • La redirection de port distante utilise l’option ssh -R
  • L’exemple transmet le port 8000 de REMOTE-MACHINE vers localhost:8001 ou 10.10.10.2:8001 côté local
ssh -R 8000:localhost:8001 user@REMOTE-MACHINE
ssh -R 8000:10.10.10.2:8001 user@REMOTE-MACHINE
  • Il est aussi possible de configurer l’écoute sur une interface distante précise, 10.99.99.2:8000
ssh -R 10.99.99.2:8000:10.10.10.2:8001 user@REMOTE-MACHINE
  • Pour écouter ailleurs que sur l’interface loopback, GatewayPorts yes doit être activé sur le serveur SSH

Redirection de port dynamique et SOCKS5

  • Pour transmettre plusieurs ports, SSH utilise le protocole SOCKS
  • SOCKS est un protocole de proxy transparent, et SSH utilise sa version moderne, SOCKS5
  • Le port par défaut d’un serveur SOCKS5 est 1080, défini dans la RFC 1928
  • Le client doit être configuré pour utiliser le proxy SOCKS au niveau de l’application ou de l’OS
  • L’exemple ssh -D ouvre un proxy SOCKS sur 10.10.10.1:5555
ssh -D 10.10.10.1:5555 user@REMOTE-MACHINE
  • Sur le client LOCAL, curl permet de tester le chemin de connexion
curl -L -x socks5://10.10.10.1:5555 brrl.net/ip
  • Si tout fonctionne correctement, l’IP publique de REMOTE-MACHINE est renvoyée

Tunneling SSH TUN/TAP

  • Le flag -w permet de créer un tunnel bidirectionnel
  • Les interfaces doivent avoir été créées au préalable
  • Cette méthode conserve la réserve qu’elle n’a pas été testée
-w local_tun[:remote_tun]

Exécution en arrière-plan et arrêt

  • Pour lancer un tunnel en arrière-plan de façon native, utilisez -fN
    • -f : exécution en arrière-plan
    • -N : ne pas ouvrir de shell
ssh -fN -L 8001:127.0.0.1:8000 user@REMOTE-MACHINE
  • Sinon, il est possible d’utiliser screen ou d’autres outils
  • Pour arrêter un SSH exécuté en arrière-plan, trouvez le processus et terminez-le via son PID
user@pleasejustwork:~$ ps -ef | grep ssh
[...]
user 19255 1 0 11:40 ? 00:00:00 ssh -fN -L 8001:127.0.0.1:8000 user@REMOTE-MACHINE
[...]
kill 19255

Maintien de connexion SSH et reconnexion

  • Il existe plusieurs façons de maintenir une connexion SSH
  • Les options de heartbeat pour gérer les timeouts peuvent être configurées côté client, côté serveur ou des deux côtés
  • ClientAliveInterval envoie une requête toutes les n secondes pour maintenir la connexion
ClientAliveInterval 15
  • ClientAliveCountMax correspond au nombre de requêtes heartbeat envoyées avant de fermer la connexion après absence de réponse de l’autre côté
ClientAliveCountMax 3
  • 3 est la valeur par défaut ; avec 0, la fermeture de la connexion est désactivée
  • Dans cet exemple de configuration, la connexion est coupée après environ 45 secondes sans réponse
  • Pour se reconnecter après une coupure, on peut utiliser autossh, un script, un cronjob, etc.

Limites et précautions de sécurité

  • UDP

    • SSH s’appuie sur un transport fiable pour un déchiffrement correct
    • UDP ne fournit pas cette fiabilité ; il n’est donc pas pris en charge dans un tunnel SSH et n’est pas recommandé
    • Il existe une méthode couvrant UDP over SSH tunneling, mais elle conserve la réserve qu’elle n’a pas été testée
  • TCP-over-TCP

    • L’overhead réduit le débit et augmente la latence
    • Sur les connexions avec perte de paquets ou forte latence, un TCP meltdown peut se produire
    • On peut consulter cet article sur TCP over TCP
    • Lors d’une utilisation d’OpenVPN-over-TCP pendant un certain temps, le débit était inférieur à celui d’UDP, mais le fonctionnement était stable ; les résultats dépendent fortement de la configuration
  • Limites en tant qu’alternative au VPN

    • Le tunneling SSH peut être utilisé comme un VPN, mais un VPN est plus adapté pour de meilleures performances
  • Risques de sécurité

    • Si cette fonctionnalité n’est pas nécessaire, il est recommandé de la désactiver
    • Un attaquant peut utiliser le tunneling SSH et la redirection de ports pour contourner les pare-feu et d’autres mesures de sécurité
  • Documentation de référence

1 commentaires

 
GN⁺ 2024-09-20
Avis sur Hacker News
  • En 2024, mieux vaut configurer LocalForward, RemoteForward et ProxyJump dans ~/.ssh/config plutôt que d’écrire à la main de longues commandes SSH
    Cela fait gagner beaucoup de temps quand on accède avec ssh, scp ou rsync à un serveur distant qui nécessite de passer par plusieurs connexions SSH intermédiaires
    Par exemple, il suffit d’enchaîner jump-host-1, jump-host-2 et jump-host-3 avec ProxyJump, puis de se connecter à target-server via un alias
    LocalForward 0.0.0.0:8080 0.0.0.0:80 transfère le port distant 80 vers le port local 8080, et RemoteForward 0.0.0.0:9022 0.0.0.0:22 transfère les requêtes SSH arrivant sur le port distant 9022 vers le port local 22
    Avec LocalForward et RemoteForward, la partie de gauche correspond au serveur cible et celle de droite au local ; il y a aussi l’astuce consistant à utiliser 0.0.0.0 plutôt que localhost ou 127.0.0.1

    • Pour partager une astuce ssh_config, une configuration utile consiste à se connecter directement en SSH aux machines quand on est à la maison ou dans son VPN auto-hébergé, et à passer automatiquement par un jump host quand on est à l’extérieur
      On peut d’abord détecter si l’on est à la maison/sur le VPN via l’adresse du routeur, avec quelque chose comme Match host *.example.org exec "getent ahosts router.example.org | grep -q ^10.0.0.1", puis utiliser ProxyJump jump.example.org si l’adresse MAC obtenue via arp ne correspond pas à la valeur attendue
      L’ordre est important : il faut d’abord détecter le réseau VPN/domestique, puis appliquer le jump host si l’on est à l’extérieur
    • Parfois, c’est juste pour un usage ponctuel et on n’a pas forcément envie de créer un fichier de configuration
      Si l’on crée un VPS de courte durée pour utiliser SSH comme proxy SOCKS afin de contourner une restriction géographique, ou si l’on aide temporairement une autre équipe et qu’on doit se connecter une seule fois à un serveur auquel on n’accède pas d’habitude, les options en ligne de commande me semblent préférables
    • Utiliser 0.0.0.0 peut être risqué
      Cela peut ouvrir le port sur toutes les interfaces réseau et, surtout si le serveur distant n’a pas de pare-feu, exposer quelque chose à tout Internet
      Pour du tunneling ou du port forwarding fréquent, un fichier de configuration est une bonne solution, mais pour une tâche ponctuelle ou rare, les options en ligne de commande me semblent préférables
    • Je me demande comment gérer ce genre de configuration SSH pour la standardiser et la déployer sur plusieurs machines locales
      Je cherche une solution un peu à la GitOps, adaptée à un seul utilisateur avec plusieurs machines, qui récupérerait la configuration depuis un endroit comme GitHub sans nécessiter de serveur séparé toujours allumé
    • Je ne veux pas toujours qu’un shell s’ouvre, donc j’ai créé de simples fonctions bash/fish pour n’avoir à retenir qu’un minimum d’arguments
      Si j’oublie, je consulte les définitions de fonctions que j’ai documentées
  • Dans l’environnement d’entreprise absurde où je travaille, le tunneling SSH est indispensable
    À cause de la bureaucratie, obtenir un accès, ouvrir un port ou obtenir une exception pare-feu/VPN peut prendre des semaines
    L’article mentionne -D, mais n’en explique pas suffisamment la puissance
    Si vous exécutez ssh -D 8888 someserver et configurez le proxy SOCKS du navigateur sur localhost:8888, tout le trafic du navigateur est routé via someserver
    Firefox est encore capable de faire cela sans modifier les paramètres système par défaut, ce qui est très utile

    • Au milieu des années 2000, c’était quasiment la méthode standard que j’utilisais pour naviguer sur le Web hors de chez moi
      Mais en arrivant en entreprise, j’ai découvert qu’à cause des listes d’IP autorisées, je ne pouvais même pas établir de connexion SSH vers un serveur quelconque sur Internet ; c’était tellement pénible que j’ai même cherché comment créer un tunnel HTTP et faire ajouter à la liste blanche un serveur que je contrôlais, avant de finalement changer de travail
    • Contourner le réseau d’entreprise n’est pas une bonne idée
      Ces restrictions existent pour une raison, et les contourner peut passer pour un manque d’expertise et un mépris des procédures et de la sécurité de l’organisation
      Si obtenir un accès prend des semaines ou des mois, il faut attendre ; personne ne veut être responsable d’avoir ouvert une porte dérobée vers des informations confidentielles ou d’avoir compromis la sécurité
  • Le bricolage de tunneling SSH le plus sale que j’aie fait à 3 h du matin consistait à relier trois datacenters
    Les trois sites, situés dans la même zone métropolitaine, étaient connectés à l’Internet backbone, mais à cause de règles de routage bizarres, A ne pouvait se connecter qu’à B, et seul B pouvait se connecter à C
    Au final, pour déplacer les données de A vers C en passant par B, il a fallu mélanger rsync + tunnel SSH + clés + astuces de routage ; après avoir ajusté plusieurs fois cette commande digne d’une incantation, voir tout l’ensemble fonctionner d’un seul coup avait quelque chose de magique
    Avec le recul, la manière de faire me paraît évidente, mais pour le débutant que j’étais à l’époque, c’était une grande réussite, et je me souviens encore de l’excitation en constatant que la synchronisation était terminée

    • Avec ~/.ssh/config et ProxyJump, on peut en pratique sauter autant d’étapes que nécessaire, comme A, B, C, D, E
  • Les détails de la visualisation sont bons
    En réseau, j’aimerais surtout qu’il existe beaucoup plus d’outils pour représenter visuellement le trafic, notamment aux niveaux de connexion les plus bas

    • Les diagrammes ici valent aussi le coup d’œil : https://www.nathanhandy.blog/articles/osi-model-revisited.ht...
      Bien sûr, ce n’est qu’une représentation statique de concepts, et la plupart des fournisseurs réseau proposent eux aussi une forme de visualisation du trafic, mais cela se limite généralement à des métriques ou graphiques individuels
  • Si un serveur Linux ou un appareil IoT se trouve derrière un pare-feu, sans IP fixe, et que vous voulez vous y connecter en SSH, vous pouvez utiliser un service de tunneling comme https://sshreach.me

  • J’ai pas mal utilisé le tunneling pendant des années, mais je ne connaissais pas l’option -J
    Plutôt que de passer 30 minutes à configurer un tunnel chaque fois que j’en ai besoin tous les quelques mois, j’aimerais bien qu’il existe un outil visuel pour configurer les tunnels

  • Il est expliqué que TCP-over-TCP augmente l’overhead, réduit le débit, accroît la latence et peut provoquer un effondrement TCP sur des connexions avec perte de paquets ou à forte latence, comme les liaisons satellite
    Mais avec un tunnel SSH, ce n’est en réalité pas un problème tant qu’on n’utilise pas TAP/TUN
    C’est parce que SSH désencapsule le flux TCP avant de le transmettre
    En revanche, lorsqu’on utilise plusieurs canaux, les performances peuvent se dégrader à cause du blocage en tête de ligne

  • Il y a environ 15 ans, j’ai appris les tunnels SSH pour contourner le pare-feu du réseau de mon université, et j’ai dû changer le port par défaut pour le 443
    Depuis, je continue à m’en servir pour bien plus de choses que le contournement de pare-feu

    • Je suis curieux de savoir quels usages intéressants vous en avez tirés, à part contourner un pare-feu ou exposer des services locaux au-delà du réseau
  • Avec sshuttle, le tunneling devient beaucoup plus pratique
    En l’utilisant par exemple comme sshuttle -r user@host 10.0.0.0/8, la plage 10/8 est automatiquement tunnelisée et cela fonctionne en pratique comme un VPN au-dessus de SSH

  • Je me demande si SSH dispose lui-même d’une fonction de redirection
    Par exemple, si A essaie de se connecter en SSH à B, B lui indique de se connecter à C, A se connecte directement et de façon transparente à C, et B ne reste plus sur le chemin principal des données

    • Il me semble qu’on peut faire quelque chose de similaire avec une IP virtuelle
      Mon pare-feu/routeur ne transmet pas correctement l’option DHCP 67 et envoie systématiquement sa propre adresse ; j’ai donc dû configurer une IP virtuelle/des règles pour que, lorsque le trafic de démarrage PXE sur ce port arrive à l’IP du routeur, il soit routé vers le vrai serveur de démarrage PXE
    • Si A ne sait pas que la véritable destination est C, cela peut prêter à confusion
      Sinon, il suffit d’utiliser la fonction de saut : ssh -J B C
      Si B n’a pas besoin d’être sur le chemin et qu’on peut se connecter directement à C, autant se connecter directement à C ; si ce n’est pas possible, B devra de toute façon servir de saut
    • B peut probablement faire du transfert de port vers C, c’est-à-dire du routage de paquets, mais il ne semble pas exister d’équivalent à une redirection permanente HTTP
      En expliquant davantage le problème, il pourrait y avoir une solution plus adaptée
      Pour des hôtes quelque peu embarqués, on peut faire en sorte que le DNS se charge du « routage », mais dans ce cas il faut gérer soi-même la vérification de l’empreinte de la clé d’hôte