Comment atteindre une base de donnĂ©es qui n’Ă©coute que sur localhost ?

Une instance Postgres sur un serveur distant est liĂ©e Ă  127.0.0.1 volontairement. Rien sur le rĂ©seau ne peut l’atteindre, seuls les processus qui tournent sur cette mĂŞme machine le peuvent. Votre ordinateur portable n’est pas cette machine, donc psql -h remote-server -p 5432 Ă©choue avant mĂŞme d’arriver Ă  l’authentification. Ouvrir le port au monde entier annulerait la raison mĂŞme pour laquelle il a Ă©tĂ© liĂ© au loopback.

Ce que vous voulez, c’est emprunter, pour quelques minutes, la vue que la machine distante a de 127.0.0.1, depuis votre propre terminal. Dès que vous vous connectez, SSH a dĂ©jĂ  ouvert une connexion chiffrĂ©e et authentifiĂ©e entre les deux machines. Le port forwarding rĂ©utilise cette connexion pour transporter un trafic autre que celui de votre shell.

Comment fonctionne le port forwarding SSH sous le capot ?

Une session SSH classique ressemble à un simple tuyau : les touches entrent, la sortie du terminal revient. En dessous, le protocole multiplexe plusieurs canaux indépendants sur cette unique connexion chiffrée. Le shell est un canal. Une connexion TCP redirigée en est un autre.

Demandez Ă  ssh de rediriger un port : il ouvre un nouveau canal pour chaque connexion Ă©tablie vers ce port, transporte les octets bruts Ă  travers la session existante et les remet de l’autre cĂ´tĂ©. Pas de nouveau certificat, pas de second login. Le tunnel hĂ©rite de l’accès que possède dĂ©jĂ  le login SSH.

Gardez cela en tête avant de regarder les options. -L, -R et -D ne sont pas trois mécanismes différents. Ils orientent le même mécanisme de channel-forwarding dans des directions différentes.

Comment utiliser la redirection de port locale SSH (-L) ?

1
ssh -L 5432:localhost:5432 [email protected]

Lisez l’argument de -L comme local_port:destination_host:destination_port. Cela ouvre le port 5432 sur votre ordinateur portable. Tout ce qui s’y connecte est redirigĂ© Ă  travers le tunnel vers localhost:5432 tel que vu depuis db-host, c’est-Ă -dire l’instance Postgres liĂ©e Ă  son propre loopback. Dans un second terminal :

1
psql -h localhost -p 5432 -U app appdb

psql pense parler Ă  une base de donnĂ©es locale. Il parle en rĂ©alitĂ© Ă  l’interface de loopback de db-host Ă  travers SSH.

L’hĂ´te de destination au milieu n’a pas besoin d’ĂŞtre le serveur SSH lui-mĂŞme :

1
ssh -L 5432:internal-db.corp:5432 jumpbox.example.com

Cela redirige via jumpbox vers une troisième machine que jumpbox peut atteindre et que vous ne pouvez pas. C’est la forme que la plupart des gens ont en tĂŞte en parlant de « tunnel SSH » : une machine qui a l’accès que vous n’avez pas, redirigeant vers un rĂ©seau que vous ne pourriez pas toucher autrement. Si Postgres tourne dĂ©jĂ  en local, le port 5432 de votre portable est pris ; choisissez un autre port local comme 15432 et passez -p 15432 Ă  psql.

Comment exposer un port local avec la redirection distante SSH (-R) ?

-R fait la mĂŞme chose Ă  l’envers. La syntaxe est remote_port:destination_host:destination_port, mais le listener s’ouvre cĂ´tĂ© distant.

1
ssh -R 8080:localhost:3000 [email protected]

public-host Ă©coute maintenant sur le port 8080, et toute connexion vers ce port revient Ă  travers le tunnel jusqu’Ă  localhost:3000 sur votre machine : votre serveur de dĂ©veloppement local. Vous obtenez une adresse joignable pour un fournisseur de webhooks ou un collègue sans ouvrir de port sur votre propre pare-feu, en empruntant une machine qui en a dĂ©jĂ  un.

Un comportement par dĂ©faut surprend souvent. sshd lie les ports redirigĂ©s Ă  distance Ă  l’interface de loopback de l’hĂ´te distant, donc curl public-host:8080 depuis une troisième machine Ă©choue mĂŞme si la redirection tourne. Seuls les processus sur public-host lui-mĂŞme peuvent l’atteindre. Changer cela nĂ©cessite GatewayPorts yes dans le sshd_config de ce serveur, un rĂ©glage que seul l’administrateur du serveur peut changer. Aucune option sur votre commande ssh ne le contourne.

Comment transformer un tunnel SSH en proxy SOCKS (-D) ?

-L et -R redirigent chacun vers une destination fixe, décidée au lancement de la commande. -D ne choisit aucune destination :

1
ssh -D 1080 [email protected]

Cela ouvre un proxy SOCKS sur localhost:1080. Toute application pointée vers ce port choisit la destination pour chaque connexion, et ssh la relaie depuis la position de remote-host sur le réseau :

1
curl --socks5-hostname localhost:1080 https://internal-service.corp/status

La partie -hostname compte. Avec le simple --socks5, curl rĂ©sout internal-service.corp sur votre portable, oĂą ce nom n’existe pas, et Ă©choue avant mĂŞme que le proxy ne soit utilisĂ©. --socks5-hostname envoie le nom Ă  travers le tunnel pour que ce soit remote-host qui le rĂ©solve.

Les navigateurs fonctionnent de la mĂŞme façon une fois le proxy configurĂ© dans leurs paramètres rĂ©seau (et « Proxy DNS lors de l’utilisation de SOCKS v5 » activĂ© dans Firefox). Chaque site voit alors l’IP de remote-host et passe par ses règles de pare-feu. C’est ainsi que vous atteignez tout un rĂ©seau interne Ă  travers un seul jump box, ou que vous vĂ©rifiez ce qu’un site sert Ă  une autre rĂ©gion, sans Ă©crire une redirection distincte pour chaque destination.

Quel type de redirection SSH choisir : -L, -R ou -D ?

-L locale-R distante-D dynamique
Le listener s’ouvre surVotre machineL’hĂ´te distantVotre machine
DestinationFixe, dĂ©finie sur la ligne de commandeFixe, dĂ©finie sur la ligne de commandeChoisie par connexion par l’application
Usage typiqueAtteindre un service que seul l’hĂ´te distant voitExposer votre service local au cĂ´tĂ© distantRouter un trafic arbitraire Ă  travers le rĂ©seau de l’hĂ´te distant
Besoin Ă  l’autre boutRien de plus qu’un login SSH normalGatewayPorts si d’autres doivent l’atteindreRien de plus qu’un login SSH normal

Comment garder un tunnel SSH ouvert en arrière-plan ?

Deux problèmes apparaissent vite : retaper la commande complète à chaque fois, et le tunnel qui meurt à la fermeture du terminal. ~/.ssh/config règle le premier :

1
2
3
4
5
Host db-tunnel
    HostName db-host.example.com
    User deploy
    LocalForward 5432 localhost:5432
    LocalForward 6379 localhost:6379

ssh db-tunnel ouvre désormais les deux redirections en une fois. LocalForward, RemoteForward et DynamicForward correspondent à -L, -R et -D, une ligne par redirection, autant que nécessaire dans un bloc Host.

Pour une redirection qui doit rester active sans surveillance, ajoutez -N (n’exĂ©cuter aucune commande distante, garder seulement le tunnel) et -f (passer en arrière-plan après authentification), plus un keepalive pour qu’une connexion coupĂ©e silencieusement soit dĂ©tectĂ©e au lieu de rester bloquĂ©e :

1
ssh -N -f -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" db-tunnel

Cela ne se reconnecte pas pour autant quand le réseau tombe. ssh se termine et la redirection disparaît. autossh enveloppe la même commande et la relance quand la connexion meurt :

1
autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -f db-tunnel

-M 0 dĂ©sactive le port de monitoring propre Ă  autossh et laisse le keepalive ServerAlive* dĂ©tecter une connexion morte. Sur OpenSSH moderne, c’est la configuration Ă  utiliser.

Quand ne pas utiliser les tunnels SSH ?

Un port redirigĂ© hĂ©rite de l’accès du login SSH qui l’a ouvert. Pratique quand c’est vous qui dĂ©tenez la clĂ©, et une exposition rĂ©elle si la clĂ© ou la session sont compromises, car le tunnel offre tout ce que ce login peut atteindre. AllowTcpForwarding dans sshd_config est l’interrupteur cĂ´tĂ© serveur (yes par dĂ©faut). Le passer Ă  no ferme cette voie, mais quiconque a un accès shell sur la machine peut toujours lancer son propre forwarder, donc cela n’aide que si vous restreignez aussi l’accès shell.

Les tunnels cessent aussi de passer Ă  l’Ă©chelle au-delĂ  d’une poignĂ©e de personnes ou de services. Chacun est un processus liĂ© Ă  un terminal ou Ă  une instance autossh. Il n’y a pas d’endroit central pour voir qui a un tunnel ouvert, rĂ©voquer l’accès sans toucher Ă  chaque configuration client, ou appliquer une politique unique Ă  tous les utilisateurs. Ă€ ce stade, un VPN, ou un proxy qui authentifie chaque utilisateur devant le service, devrait remplacer le tas de tunnels personnels.

Ce n’est pas non plus le mĂŞme outil qu’un reverse proxy ou Cloudflare Tunnel, mĂŞme si les trois rendent joignable quelque chose qui ne l’Ă©tait pas. Un reverse proxy se place en permanence devant un service et fait face Ă  l’internet public. Cloudflare Tunnel est plus proche de -R : une connexion sortante depuis votre cĂ´tĂ© qui devient joignable depuis l’extĂ©rieur, mais Ă  travers l’edge de Cloudflare, avec un hostname stable et aucun port serveur Ă  gĂ©rer. Et tandis qu’un reverse proxy ou Cloudflare Tunnel s’appuient sur des certificats, comme expliquĂ© dans comment fonctionne le handshake TLS, un tunnel SSH n’en a besoin d’aucun. Le chiffrement, c’est la session SSH elle-mĂŞme, authentifiĂ©e par votre clĂ© plutĂ´t que par un certificat auquel un navigateur ferait confiance.

Que configurer en premier ?

Prenez le tunnel que vous retapez le plus souvent et transformez-le dès aujourd’hui en bloc Host dans ~/.ssh/config. Atteindre quelque chose que seul un hĂ´te distant voit, c’est -L. Exposer un service local Ă  travers une machine avec une adresse publique, c’est -R. Router le trafic d’une application Ă  travers un rĂ©seau distant sans choisir les destinations Ă  l’avance, c’est -D. Une fois dans le config, ssh -N -f db-tunnel suffit, et vous arrĂŞtez de vous tromper de numĂ©ro de port Ă  23 heures.

Articles associés