Lequel vous faut-il ?
| Option | Le port s'ouvre sur | À utiliser pour |
|---|---|---|
-L local | Votre machine | Atteindre un service que seul le serveur peut atteindre, comme une base de données. |
-R distant | Le serveur | Laisser le serveur atteindre quelque chose sur votre machine, comme un site de développement. |
-D dynamique | Votre machine | Naviguer ou vous connecter à de nombreux hôtes comme si vous étiez sur le serveur. |
Pour s'en souvenir : -L écoute sur votre machine locale, -R écoute sur le serveur distant (remote), et -D est dynamique car l'application choisit la destination à chaque fois.
Redirection locale : -L
ssh -N -L 8080:localhost:80 user@server
your app -> your machine, port 8080 -> SSH -> server -> localhost:80 as seen by the server
Le format est port_local:destination:port_destination. Désormais, http://127.0.0.1:8080 sur votre machine affiche le serveur web qui n'écoute que sur l'adresse de bouclage du serveur.
Le point essentiel est que c'est le serveur qui résout la destination. localhost désigne le serveur lui-même, pas votre machine. La destination peut aussi être un autre hôte que le serveur peut atteindre, et ce dernier saut n'est pas chiffré par SSH :
ssh -N -L 8080:intranet.example.com:80 user@server
Redirection distante : -R
ssh -N -R 9000:localhost:3000 user@server
a program on the server -> server, port 9000 -> SSH -> your machine -> localhost:3000 as seen by your machine
Un programme sur le serveur peut maintenant ouvrir http://127.0.0.1:9000 et atteindre l'application qui tourne sur votre machine. Cela marche même quand votre machine est derrière un NAT, parce que c'est votre côté qui a démarré la connexion.
Redirection dynamique : -D
ssh -N -D 1080 user@server
your app -> SOCKS proxy on your machine, port 1080 -> SSH -> server -> any host:port the app asks for
Dirigez une application qui gère SOCKS vers 127.0.0.1:1080. Pour tester avec curl :
curl --socks5-hostname 127.0.0.1:1080 http://intranet.example.com/
--socks5-hostname fait faire la résolution DNS par le serveur : les noms internes fonctionnent et la requête ne fuit pas depuis votre propre réseau. Avec --socks5 seul, le nom est résolu sur votre machine.
Les réglages du navigateur et les fuites DNS sont traités dans utiliser SSH comme proxy SOCKS.
Plusieurs ports, ou via un hôte de rebond
Répétez l'option pour ouvrir plusieurs redirections sur une même connexion :
ssh -N -L 127.0.0.1:8080:localhost:80 -L 127.0.0.1:5433:localhost:5432 user@server
Quand le serveur se trouve derrière un bastion, ajoutez -J. La redirection part du dernier serveur de la chaîne, c'est donc lui qui résout la destination :
ssh -N -J user@bastion -L 127.0.0.1:5433:localhost:5432 user@db-server
Les chaînes de serveurs sont expliquées dans utiliser ProxyJump et un hôte de rebond.
Lancer un tunnel sans shell
-Nne lance aucune commande distante. La session ne porte que le tunnel.-fpasse en arrière-plan après la connexion, vous pouvez donc encore saisir une phrase secrète avant.-o ExitOnForwardFailure=yesse termine avec une erreur si la redirection ne peut pas être établie.
ssh -f -N -o ExitOnForwardFailure=yes -L 127.0.0.1:8080:localhost:80 user@server
Sans ExitOnForwardFailure, ssh affiche un avertissement et reste connecté sans tunnel fonctionnel, ce qui prête à confusion dans un script. Avec cette option, un port local déjà utilisé se termine avec le code 255 et Could not request local forwarding, et un port distant déjà utilisé avec remote port forwarding failed for listen port.
Un piège vu dans nos tests : avec un simple -L 8080:..., ssh écoute à la fois sur 127.0.0.1 et sur ::1. Si un seul des deux est pris, par exemple par un autre programme en IPv4, ssh affiche bind [127.0.0.1]:8080: Address already in use et continue de tourner même avec ExitOnForwardFailure=yes. Votre app peut alors atteindre cet autre programme. Écrire l'adresse, comme dans -L 127.0.0.1:8080:..., en fait un vrai échec : utilisez cette forme dans les scripts.
Pour arrêter un tunnel en arrière-plan, trouvez son processus et tuez-le :
pgrep -f 'L 127.0.0.1:8080'
kill PID
Pour les tunnels que vous lancez souvent, un socket de contrôle permet de les arrêter par leur nom avec ssh -O exit. Voir enregistrer, lancer et arrêter des tunnels SSH.
Pour garder un tunnel dans votre configuration, utilisez LocalForward, RemoteForward et DynamicForward :
Host dbtunnel
HostName 203.0.113.10
User user
LocalForward 127.0.0.1:8080 localhost:80
ExitOnForwardFailure yes
Lier à localhost uniquement
Un port redirigé est ouvert à quiconque peut l'atteindre, et le service derrière lui peut faire confiance aux connexions venant du serveur. Par défaut, ssh ne se lie qu'à l'adresse de bouclage : gardez ce comportement sauf raison contraire.
Ces commandes ouvrent le port local à tout votre réseau. Nous avons confirmé que les deux écoutent sur toutes les interfaces :
ssh -N -L 0.0.0.0:8080:localhost:80 user@server
ssh -N -g -L 8080:localhost:80 user@server
Pour -R, c'est le serveur qui décide, avec GatewayPorts dans sa configuration sshd :
| GatewayPorts | -R 9000:... | -R 0.0.0.0:9000:... |
|---|---|---|
no (par défaut) | Bouclage uniquement | Bouclage uniquement, sans erreur |
clientspecified | Bouclage uniquement | Toutes les interfaces |
yes | Toutes les interfaces | Toutes les interfaces, et 127.0.0.1:9000 s'ouvre aussi sur toutes les interfaces |
Si votre port -R n'est pas joignable de l'extérieur, GatewayPorts en est donc la raison habituelle. Exposer le service de votre portable à internet de cette façon est rarement ce que vous voulez. Préférez clientspecified si vous en avez besoin, et ajoutez une règle de pare-feu.
Quand le serveur refuse
AllowTcpForwarding dans la configuration sshd du serveur contrôle cela. Les valeurs sont yes (par défaut), no, local (autorise -L et -D) et remote (autorise -R).
- Un
-Lou-Dbloqué se connecte normalement. L'erreur n'arrive que quand quelque chose utilise le port :channel 2: open failed: administratively prohibited: open failed. - Un
-Rbloqué afficheremote port forwarding failed for listen port.
La page de manuel note que désactiver les redirections apporte peu si les utilisateurs ont aussi un shell, puisqu'ils peuvent lancer leur propre redirecteur. Pour vraiment limiter quelqu'un, retirez aussi le shell, comme dans un utilisateur réservé au tunnel pour une base de données.
Deux autres erreurs reviennent souvent. Quand le port local ou distant est pris, voir Address already in use et remote port forwarding failed. Quand les connexions à travers le tunnel sont refusées, voir administratively prohibited: open failed.
Questions
Quelle différence entre ssh -L et ssh -R ?
-L ouvre un port sur votre machine qui mène à ce que le serveur peut joindre. -R ouvre un port sur le serveur qui ramène vers quelque chose sur votre machine.
Comment rediriger plusieurs ports avec une seule commande ssh ?
Répétez l'option : ssh -N -L 127.0.0.1:8080:localhost:80 -L 127.0.0.1:5433:localhost:5432 user@server. Une seule connexion les transporte toutes. Dans ~/.ssh/config, ajoutez une ligne LocalForward par port.
Comment garder un tunnel SSH actif ?
Lancez-le avec -N et -o ExitOnForwardFailure=yes, et laissez autossh ou un service systemd le relancer après une coupure. Voir autossh et systemd.
Pourquoi mon tunnel se connecte sans que rien ne marche ?
Le serveur peut interdire la redirection avec AllowTcpForwarding. Un -L ou -D bloqué se connecte quand même et n'échoue qu'à l'usage du port, avec administratively prohibited: open failed.
La redirection de port SSH est-elle sûre ?
Le trafic est chiffré entre votre machine et le serveur SSH. Le tronçon du serveur à la destination ne l'est pas, et un port qui écoute sur 0.0.0.0 peut servir à n'importe qui sur votre réseau : gardez l'adresse d'écoute sur 127.0.0.1.