Aller au contenu
Administration Linux medium

Tunnels SSH : -L, -R, -D et ProxyJump

11 min de lecture

Un tunnel SSH permet de faire transiter un flux réseau à travers une connexion SSH chiffrée. Résultat : vous accédez à une base de données interne comme si elle était locale, vous exposez un service de développement sur un serveur public, ou vous faites passer tout votre trafic par un serveur distant. Pas besoin de VPN, pas de port supplémentaire à ouvrir.

C'est un objectif LFCS (domaine Networking, "Use SSH tunneling and port forwarding").

  • Créer un tunnel local (-L) pour atteindre un service derrière un bastion
  • Créer un tunnel distant (-R) pour rendre un service local accessible depuis l'extérieur
  • Créer un tunnel dynamique (-D) comme proxy SOCKS pour tout le trafic
  • Utiliser ProxyJump pour traverser un ou plusieurs hôtes intermédiaires
  • Persister les tunnels dans ~/.ssh/config
  • Diagnostiquer un tunnel bloqué

Les tunnels SSH servent quand le réseau empêche un accès direct : une base de données sur un réseau privé inaccessible depuis l'extérieur, un service web interne visible seulement depuis un bastion, un environnement de développement local à partager temporairement avec un collègue. En une commande, SSH crée un canal chiffré qui contourne ces restrictions sans modifier les règles de pare-feu du serveur cible.


Un tunnel local redirige un port de votre machine vers un port sur (ou accessible depuis) le serveur SSH.

Syntaxe :

ssh -L [adresse_locale:]port_local:hôte_cible:port_cible user@bastion

Vous voulez vous connecter à un serveur MySQL sur 192.168.1.100:3306, accessible uniquement depuis le bastion bastion.example.com :

Fenêtre de terminal
ssh -L 3307:192.168.1.100:3306 bob@bastion.example.com

Ensuite, depuis votre machine locale :

Fenêtre de terminal
mysql -h 127.0.0.1 -P 3307 -u root -p

MySQL répond comme s'il était local. Le trafic circule en clair du client MySQL jusqu'à localhost:3307, puis chiffré par SSH jusqu'au bastion, et de nouveau en clair du bastion jusqu'à 192.168.1.100:3306.

Un tunnel ouvert dans un terminal disparaît dès que ce terminal se ferme. Les options -N et -f détachent le processus ssh du shell courant : la main est rendue immédiatement et le tunnel survit à la fermeture de la fenêtre. Contrepartie : plus aucun message d'erreur ne s'affiche, donc établissez d'abord le tunnel au premier plan pour valider qu'il fonctionne, puis relancez-le détaché.

Fenêtre de terminal
ssh -N -f -L 3307:192.168.1.100:3306 bob@bastion.example.com
  • -N : ne pas ouvrir de shell, juste le tunnel
  • -f : passer en arrière-plan avant l'exécution

Pour fermer le tunnel :

Fenêtre de terminal
# Trouver le PID
ps aux | grep "ssh -N"
kill <PID>

Retaper la redirection complète à chaque connexion finit par produire des erreurs de port. La directive LocalForward dans ~/.ssh/config fige la redirection dans le profil de l'hôte : la syntaxe y sépare le port local et la cible par une espace, là où la ligne de commande les colle avec un deux-points. Le fichier ne doit être inscriptible par personne d'autre que son propriétaire, sinon OpenSSH refuse de l'utiliser ; 600 est la valeur habituelle.

Host bastion-mysql
HostName bastion.example.com
User bob
LocalForward 3307 192.168.1.100:3306

Puis simplement :

Fenêtre de terminal
ssh -N bastion-mysql

Un tunnel distant redirige un port sur le serveur SSH vers un port de votre machine locale. C'est l'inverse du tunnel local.

Syntaxe :

ssh -R [adresse_distante:]port_distant:hôte_local:port_local user@serveur

Exemple : partager un serveur de développement local

Section intitulée « Exemple : partager un serveur de développement local »

Vous avez un serveur de développement sur localhost:8080 et vous voulez le rendre accessible via serveur.example.com:8080 :

Fenêtre de terminal
ssh -R 8080:localhost:8080 bob@serveur.example.com

Toute personne qui accède à http://serveur.example.com:8080 voit votre serveur local.


Un tunnel dynamique transforme la connexion SSH en proxy SOCKS. Au lieu de rediriger un seul port vers une cible fixe, tout le trafic envoyé au proxy est acheminé via le serveur SSH, qui décide de la destination.

Syntaxe :

Fenêtre de terminal
ssh -D 1080 bob@bastion.example.com

Ensuite, configurez votre application pour utiliser localhost:1080 comme proxy SOCKS5.

Chromium via la ligne de commande :

Fenêtre de terminal
chromium --proxy-server="socks5://localhost:1080"

Firefox n'accepte aucune option de proxy en ligne de commande : le réglage passe par about:preferences, section Paramètres réseau, en choisissant « Configuration manuelle du proxy » puis en renseignant l'hôte SOCKS localhost et le port 1080. Dans ce même écran, l'option qui délègue la résolution DNS au proxy SOCKS v5 (préférence network.proxy.socks_remote_dns) est indispensable : sans elle, les noms internes sont résolus par votre résolveur local, qui ne les connaît pas.

curl avec SOCKS :

Fenêtre de terminal
curl --socks5 localhost:1080 http://service-interne.example.com/api/status

ProxyJump (-J) établit la connexion via un ou plusieurs hôtes intermédiaires. C'est la méthode moderne, plus sûre que ProxyCommand, et c'est un tunnel implicite.

Le point important est que l'authentification finale se fait contre la cible, pas contre le bastion. Le bastion ne sert que de relais TCP : il ne voit passer que du trafic chiffré de bout en bout entre votre poste et 10.0.1.15. Un administrateur du bastion ne peut donc pas lire votre session, contrairement à un enchaînement de deux ssh où le second part depuis le bastion.

Fenêtre de terminal
ssh -J bob@bastion.example.com alice@10.0.1.15

Les hôtes se déclarent dans l'ordre de traversée, séparés par des virgules, et le dernier argument reste la destination finale. Chaque saut ouvre une nouvelle session imbriquée : une latence de quelques centaines de millisecondes est normale sur trois niveaux. Si un saut intermédiaire échoue, le message d'erreur cite l'hôte fautif, ce qui permet de localiser la coupure sans tester chaque machine à la main.

Fenêtre de terminal
ssh -J bob@bastion.example.com,carol@10.0.1.5 alice@10.0.2.20

-J et -L se cumulent sans conflit parce qu'ils agissent à deux niveaux différents : -J construit le chemin d'accès, -L ouvre la redirection une fois arrivé. Le piège tient au localhost de la redirection : il désigne 10.0.2.20, l'hôte final, pas votre poste. Le -N évite d'ouvrir un shell inutile sur la machine de production.

Fenêtre de terminal
# Accéder à la BDD sur 10.0.2.20 via deux hôtes intermédiaires
ssh -J bob@bastion.example.com,carol@10.0.1.5 \
-L 5432:localhost:5432 \
alice@10.0.2.20 -N

La même chaîne écrite une fois dans le fichier de configuration se rejoue avec ssh -N prod-db. La directive ProxyJump accepte la liste de sauts avec la même syntaxe que l'option en ligne de commande, et LocalForward s'applique à l'hôte final. Cette forme est celle à privilégier dès qu'un accès est répété : les outils qui s'appuient sur SSH, comme scp, rsync ou git, lisent le même fichier et héritent automatiquement du chemin.

Host prod-db
HostName 10.0.2.20
User alice
ProxyJump bob@bastion.example.com,carol@10.0.1.5
LocalForward 5432 localhost:5432

Pour un tunnel qui se reconnecte automatiquement si la connexion est perdue :

Fenêtre de terminal
# Installation
sudo apt install autossh # Debian/Ubuntu
sudo dnf install autossh # RHEL/Fedora
# Tunnel local persistant
autossh -M 0 -N -f \
-o "ServerAliveInterval 30" \
-o "ServerAliveCountMax 3" \
-L 3307:192.168.1.100:3306 \
bob@bastion.example.com

-M 0 désactive le port de monitoring d'autossh et délègue la détection de rupture aux options ServerAlive.


Le réflexe qui fait gagner le plus de temps : relancer la commande avec -v, voire -vvv. La sortie indique à quelle étape le tunnel casse, et la distinction est décisive. Un message émis par le client signale un problème local (port occupé, clé refusée) ; un message préfixé channel N: vient du serveur SSH et désigne un problème de joignabilité côté distant. Lisez le tableau avec cette grille : la colonne « Cause probable » indique de quel côté du tunnel chercher.

SymptômeCause probableAction
bind: Address already in usePort local déjà utiliséChanger le port local ou tuer le processus occupant ce port
Tunnel établi mais connexion refuséeGatewayPorts no côté serveurAjouter GatewayPorts yes dans sshd_config (tunnel -R)
Tunnel -D : les applications ne passent pasProxy SOCKS mal configuré dans l'appVérifier que l'app utilise SOCKS5, pas SOCKS4 ou HTTP
Tunnel se ferme après quelques minutesTimeout SSH côté serveurAjouter ServerAliveInterval 60 dans ~/.ssh/config ou utiliser autossh
channel 2: open failed: connect failedLe serveur cible du tunnel est injoignable depuis le bastionVérifier que 192.168.1.100:3306 est accessible depuis le bastion, pas depuis votre machine
ProxyJump : Permission deniedClé SSH absente sur l'hôte intermédiaireCopier la clé sur chaque hôte intermédiaire ou activer ForwardAgent yes

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  • -L port_local:cible:port_cible : atteindre un service distant comme s'il était local
  • -R port_distant:cible:port_cible : exposer un service local sur le serveur SSH
  • -D port : proxy SOCKS pour tout le trafic d'une application
  • -N -f : tunnel sans shell, en arrière-plan
  • ProxyJump remplace ProxyCommand et supporte les sauts multiples
  • Pour les tunnels critiques, autossh assure la reconnexion automatique

Les questions les plus posées sur les tunnels SSH, du choix entre -L, -R et -D jusqu'à la persistance avec autossh.

  • Durcir l'accès SSH : Restreindre les tunnels, désactiver le forwarding inutile, AllowTcpForwarding.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn