termal.in

← Blog

La redirection de port SSH, expliquée : tunnels locaux, distants et dynamiques

· Termalin Team sshport-forwardingtunnelingtutorial

La redirection de port SSH fait partie de ces fonctionnalités que l’on copie depuis Stack Overflow, que l’on fait marcher une fois, et que l’on ne comprend jamais tout à fait — si bien qu’à la fois suivante, on en revient à deviner laquelle utiliser entre -L, -R et -D. Les trois options ne sont pas difficiles ; elles sont juste mal nommées. Voici le modèle mental unique qui les rend évidentes, un exemple pour chacune, et les options et pièges qui décident si le tunnel survit à l’après-midi.

La seule question qui désigne l’option

Tout tunnel SSH ouvre un port d’écoute sur une machine et achemine discrètement ce qui l’atteint vers un point joignable depuis l’autre machine. La seule question est donc : quel côté ouvre le port auquel vous vous connectez ?

  • -L (locale) — le port s’ouvre sur votre machine. Vous vous connectez localement ; le trafic ressort du côté du serveur.
  • -R (distante) — le port s’ouvre sur le serveur. Quelqu’un s’y connecte ; le trafic ressort de votre côté.
  • -D (dynamique) — le port s’ouvre sur votre machine, mais c’est un proxy SOCKS : la destination se décide par connexion, pas une fois pour toutes.

Tout le reste est du détail. Gardez en tête « quel côté ouvre le port » et vous ne vous tromperez plus jamais d’option.

Redirection locale (-L) — ramener un service distant vers localhost

La plus courante. Une base de données, un tableau de bord interne, une interface de métriques — quelque chose lié à 127.0.0.1 sur le serveur, ou sur une machine que seul le serveur peut joindre. Vous le voulez sur votre portable comme s’il était local.

ssh -L 5432:localhost:5432 deploy@db.example.com

Lisez de gauche à droite : ouvre 5432 sur ma machine, et redirige tout ce qui y arrive vers localhost:5432 tel que vu depuis le serveur. Désormais, psql -h 127.0.0.1 sur votre portable dialogue avec le Postgres du serveur (en anglais) — via la connexion SSH chiffrée, sans exposer la base au réseau le moins du monde.

L’hôte du milieu est résolu côté serveur, et c’est ce qui rend la chose puissante :

# reach a database that only the bastion can see
ssh -L 5432:10.0.0.9:5432 deploy@bastion.example.com

Ici, 10.0.0.9 est une adresse privée que votre portable ne sait pas router — mais le bastion, si. Le tunnel comble l’écart.

Redirection distante (-R) — exposer votre machine au côté serveur

L’image en miroir, et celle que l’on comprend à l’envers (elle a son propre dossier approfondi — Les tunnels SSH inverses). Le port s’ouvre sur le serveur ; les connexions qui l’atteignent ressortent de votre côté. Deux usages classiques :

# let the server (or its network) reach a dev server running on your laptop
ssh -R 8080:localhost:3000 deploy@app.example.com

Désormais, tout ce qui frappe localhost:8080 sur le serveur est renvoyé vers localhost:3000 sur votre portable — pratique pour montrer votre travail en cours à un collègue connecté à la machine, ou pour laisser un service distant rappeler quelque chose que vous seul exécutez.

C’est aussi l’astuce pour atteindre une machine coincée derrière un NAT, sans accès entrant : faites en sorte que ce soit elle qui ouvre un tunnel inverse vers un serveur que vous contrôlez, et vous vous connectez à travers le serveur. La machine qui ne peut pas accepter de connexions établit la connexion sortante à la place.

Un piège : par défaut, le serveur lie le port redirigé à localhost, si bien que seul le serveur lui-même peut l’utiliser. Pour que d’autres machines du réseau du serveur l’atteignent, le sshd_config du serveur doit contenir GatewayPorts yes (ou clientspecified) — un réglage côté serveur, pas quelque chose que vous pouvez forcer depuis le client.

Redirection dynamique (-D) — un proxy SOCKS en une option

-L redirige vers une seule destination fixe. -D ouvre plutôt un proxy SOCKS, de sorte que la destination est choisie à chaque requête :

ssh -D 1080 deploy@jump.example.com

Pointez votre navigateur (ou curl --socks5 127.0.0.1:1080) vers 127.0.0.1:1080 et chaque requête est acheminée depuis le serveur. C’est le moyen rapide de parcourir un réseau interne, de tester l’apparence d’un service depuis l’IP d’un centre de données, ou d’atteindre une poignée d’hôtes internes sans un -L pour chacun.

Les options qui le rendent utilisable

Une commande de tunnel toute nue ouvre aussi un shell dont vous ne voulez pas et meurt dès que vous le fermez. En pratique :

ssh -N -L 5432:localhost:5432 deploy@db.example.com
  • -N — n’exécute pas de commande distante. Vous ne voulez que le tunnel, pas un shell.
  • -f — passe le processus en arrière-plan après la connexion (à associer à -N).
  • -o ExitOnForwardFailure=yes — si le port ne peut pas être lié (déjà utilisé, permission refusée), échoue bruyamment au lieu de se connecter quand même sans rien rediriger en silence.
  • Keepalives — un tunnel de longue durée meurt des délais d’inactivité sans ServerAliveInterval 30. Ajoutez-le, sinon le tunnel tombe dès que vous cessez de l’utiliser.

Le rendre permanent dans ssh_config

Tout ce que vous passeriez avec -L/-R/-D a une directive de configuration, de sorte qu’un hôte enregistré emporte ses tunnels :

Host db-tunnel
    HostName db.example.com
    User deploy
    LocalForward 5432 localhost:5432
    ServerAliveInterval 30
    RequestTTY no

Désormais, ssh -N db-tunnel amène la base sur 127.0.0.1:5432 sans aucune option à retenir. RemoteForward et DynamicForward fonctionnent de la même manière. (Plus de détails sur le fichier de configuration lui-même dans le guide ~/.ssh/config, en anglais.)

Trois pièges

  • L’adresse de liaison compte. -L 5432:... n’écoute que sur 127.0.0.1. Pour que d’autres appareils de votre réseau local utilisent le tunnel, préfixez une adresse de liaison : -L 0.0.0.0:5432:... — et comprenez que vous venez de l’exposer à votre réseau local.
  • « Address already in use » signifie que le port local est pris (souvent un tunnel précédent qui n’a pas quitté). Choisissez un autre port local ou tuez l’ancien ; ExitOnForwardFailure transforme l’échec silencieux en une erreur que vous remarquerez vraiment.
  • L’hôte du milieu est résolu de l’autre côté. localhost dans -L a:localhost:b désigne le localhost du serveur, pas le vôtre. Inverser cela est l’erreur la plus courante en redirection de port.

Quand le tunnel refuse de se lier

Si la commande échoue avec bind: Address already in use ou bind: Permission denied, l’écouteur ne s’est jamais ouvert — déroulez la courte liste. Déjà utilisé : quelque chose occupe le port, souvent le tunnel oublié d’hier — ss -tlnp nomme le processus, puis choisissez un autre port ou tuez l’ancien. Une permission refusée en local signifie en général un port privilégié : tout ce qui est en dessous de 1024 exige root, alors écoutez sur 8443 plutôt que sur 443. À l’autre bout (-R), le serveur a un droit de veto : AllowTcpForwarding no dans sshd_config bloque purement et simplement la redirection, et sans GatewayPorts, l’écouteur distant ne se lie qu’à localhost, quelle que soit l’adresse de liaison demandée. Et sur les hôtes durcis de la famille RHEL, SELinux peut refuser à sshd la liaison même quand la configuration l’autorise — consultez le journal d’audit avant d’accuser votre commande.

Quand jongler avec les tunnels à la main devient lassant

La redirection est une excellente primitive, et tout développeur devrait connaître les trois options sur le bout des doigts. La friction apparaît plus tard : vous tenez un brouillon de commandes ssh -N -L ... (en anglais), vous les relancez après chaque mise en veille, vous oubliez quel port local correspond à quel service, et vous ne pouvez pas dire d’un coup d’œil si un tunnel tient encore.

C’est là qu’un client doté d’un vrai gestionnaire de tunnels aide. Termalin garde les redirections locales, distantes et dynamiques rattachées à l’hôte comme configuration enregistrée — lancez-les d’un clic, voyez lesquelles sont actives, et laissez-les se rétablir avec la connexion au lieu de retaper la commande. La même liste d’hôtes (avec ses clés, hôtes de rebond et keepalives) se synchronise entre vos machines, chiffrée de bout en bout, et chaque serveur est vérifié à la première connexion. La ligne de commande vous apprend comment fonctionnent les tunnels ; un client vous évite de les reconstruire à la main chaque matin.

Dans tous les cas, le modèle est toute l’astuce : décidez quel côté ouvre le port, et le reste de l’option s’écrit tout seul.


Termalin est un client SSH gratuit et multiplateforme, avec tunnels intégrés, SFTP et gestionnaire de clés — téléchargez-le, ou voyez comment il gère vos clés en toute sécurité.

Essayez-le sur un hôte.

Termalin est un client SSH rapide pour vous — et pour vos agents.

Offre gratuite · 14 jours d’essai Pro · tarifs