Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

port forwarding ssh / ipv4 ipv6

3 réponses
Avatar
cwpbl
Bonjour ,

J'ai eu récemment un pb de connexion ssh avec du port forwarding :

J'essaie d'accéder à un service de {serveur} à partir de {machine} via
un bête tunnel ssh. A noter que _{machine} a une ip publique_.

machine ------------> site --> serveur

Je fais donc :
machine # ssh -g -L {port}:{serveur}:{port} {user}@{site}
...ce qui marche bien.

Maintenant, j'ajoute entre machine et site une gateway {gw} (avec une
règle iptables adéquate) et c'est _désormais {gw} qui a l'ip publique_.
Machine ---> gw ------------> site --> serveur

machine # route add default {gw}
machine # ssh -g -L {port}:{serveur}:{port} {user}@{site}
me log bien sur {site} mais j'ai le message : "bind : address already in
use" et mon port forwarding ne marche pas.

J'ai résolu le problème en forçant de l'ipv4 :
machine # ssh -4 -g -L {port}:{serveur}:{port} {user}@{site}
après quelques tests et ayant lu qu'il y a avait une confusion ipv4/ipv6
sur le serveur ssh de {site}.

Quelqu'un pourrait-il m'expliquer en détail ce qui se passe. Je ne
comprends pas pourquoi le fait d'insérer {gw} produit l'erreur?
Et comment (et où) ipv6 intervient dans cette connexion ?

Merci pour vos lumières...

3 réponses

Avatar
Pascal Hambourg
Salut,

cwpbl a écrit :

J'ai eu récemment un pb de connexion ssh avec du port forwarding :

J'essaie d'accéder à un service de {serveur} à partir de {machine} via
un bête tunnel ssh. A noter que _{machine} a une ip publique_.



En quoi c'est important qu'elle ait une adresse IP publique ?

machine ------------> site --> serveur

Je fais donc :
machine # ssh -g -L {port}:{serveur}:{port} {user}@{site}
...ce qui marche bien.

Maintenant, j'ajoute entre machine et site une gateway {gw} (avec une
règle iptables adéquate) et c'est _désormais {gw} qui a l'ip publique_.
Machine ---> gw ------------> site --> serveur

machine # route add default {gw}
machine # ssh -g -L {port}:{serveur}:{port} {user}@{site}
me log bien sur {site} mais j'ai le message : "bind : address already in
use" et mon port forwarding ne marche pas.

J'ai résolu le problème en forçant de l'ipv4 :
machine # ssh -4 -g -L {port}:{serveur}:{port} {user}@{site}
après quelques tests et ayant lu qu'il y a avait une confusion ipv4/ipv6
sur le serveur ssh de {site}.

Quelqu'un pourrait-il m'expliquer en détail ce qui se passe. Je ne
comprends pas pourquoi le fait d'insérer {gw} produit l'erreur?
Et comment (et où) ipv6 intervient dans cette connexion ?



Le client {machine} tourne sous GNU/Linux ? Quelle distribution ?

Linux a une particularité lorsque IPv4 et IPv6 sont simultanément
activés : une socket IPv6 en écoute sur un port sur toutes les adresses
IPv6 locales (::, notation abrégée de 0:0:0:0:0:0:0:0) écoute aussi sur
le même port en IPv4 sur toutes les adresses IPv4 locales (0.0.0.0), et
de fait, "réserve" ce port en IPv4, ce qui empêche d'ouvrir le même port
en IPv4.

Par défaut ssh utilise à la fois IPv4 et IPv6 s'ils sont disponibles.
Ceci concerne la redirection de port local avec -L. ssh ouvre une socket
IPv6 et une socket IPv4 en écoute sur ce port. Sans l'option -g, il lie
ces sockets respectivement aux adresses de loopback IPv6 ::1 et IPv4
127.0.0.1 pour n'accepter les connexions que depuis la machine locale :

$ ssh -L 12345:{serveur}:{port} {site}
$ netstat --inet --inet6 -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:12345 0.0.0.0:* LISTEN
tcp6 0 0 ::1:12345 :::* LISTEN

Avec l'option -g, ssh lie ces sockets respectivement aux adresses
"joker" IPv6 :: et IPv4 0.0.0.0 pour accepter les connexion depuis
n'importe où :

$ ssh -g -L 12345:{serveur}:{port} {site}
$ netstat --inet --inet6 -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:12345 0.0.0.0:* LISTEN
tcp6 0 0 :::12345 :::* LISTEN

Mais sous Linux en configuration par défaut, l'existence de la socket
IPv6 sur :: empêche la création de la socket IPv4 sur 0.0.0.0 pour le
même port. D'où le message d'erreur. Cependant la socket IPv6 accepte
les connexions en IPv4 donc la redirection devrait quand même
fonctionner. J'ai testé, chez moi ça marche.

L'option -4 force ssh à n'utiliser que des sockets IPv4, ce qui évite le
conflit avec la socket IPv6.

A noter que tout ceci est valable aussi pour le démon serveur sshd.

Note :
Moi, je triche. Je change le comportement de Linux pour séparer
complètement les sockets IPv4 et IPv6 et empêcher les sockets IPv6
d'écouter aussi en IPv4. Cela se fait avec le paramètre du noyau
net.ipv6.bindv6only, qui est par défaut à 0 :

# sysctl -w net.ipv6.bindv6only=1

Je précise que pour le test "chez moi ça marche", j'ai remis ce
paramètre à 0, j'ai bien eu le message d'erreur et la redirection a
quand même fonctionné.

Par contre a priori la machine serveur SSH n'a rien à voir là-dedans, et
je ne vois pas non plus en quoi la présence de la passerelle influe.
Avatar
cwpbl
Pascal Hambourg a écrit :
J'essaie d'accéder à un service de {serveur} à partir de {machine} via
un bête tunnel ssh. A noter que _{machine} a une ip publique_.



En quoi c'est important qu'elle ait une adresse IP publique ?



Voir plus bas.


Je fais donc :
machine # ssh -g -L {port}:{serveur}:{port} {user}@{site}
...ce qui marche bien.

Maintenant, j'ajoute entre machine et site une gateway {gw} (avec une
règle iptables adéquate) et c'est _désormais {gw} qui a l'ip publique_.
Machine ---> gw ------------> site --> serveur

machine # route add default {gw}
machine # ssh -g -L {port}:{serveur}:{port} {user}@{site}
me log bien sur {site} mais j'ai le message : "bind : address already
in use" et mon port forwarding ne marche pas.

J'ai résolu le problème en forçant de l'ipv4 :
machine # ssh -4 -g -L {port}:{serveur}:{port} {user}@{site}






Le client {machine} tourne sous GNU/Linux ? Quelle distribution ?


machine cliente : RHEL3 u 6 ou RHEL4 u 5. gateway : RHEL3 u 6. Serveur:
gentoo, kernel 2.6.


Linux a une particularité lorsque IPv4 et IPv6 sont simultanément
activés : une socket IPv6 en écoute sur un port sur toutes les adresses
IPv6 locales (::, notation abrégée de 0:0:0:0:0:0:0:0) écoute aussi sur
le même port en IPv4 sur toutes les adresses IPv4 locales (0.0.0.0), et
de fait, "réserve" ce port en IPv4, ce qui empêche d'ouvrir le même port
en IPv4.

Par défaut ssh utilise à la fois IPv4 et IPv6 s'ils sont disponibles.
Ceci concerne la redirection de port local avec -L. ssh ouvre une socket
IPv6 et une socket IPv4 en écoute sur ce port. Sans l'option -g, il lie
ces sockets respectivement aux adresses de loopback IPv6 ::1 et IPv4
127.0.0.1 pour n'accepter les connexions que depuis la machine locale :

$ ssh -L 12345:{serveur}:{port} {site}
$ netstat --inet --inet6 -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:12345 0.0.0.0:* LISTEN
tcp6 0 0 ::1:12345 :::* LISTEN

Avec l'option -g, ssh lie ces sockets respectivement aux adresses
"joker" IPv6 :: et IPv4 0.0.0.0 pour accepter les connexion depuis
n'importe où :

$ ssh -g -L 12345:{serveur}:{port} {site}
$ netstat --inet --inet6 -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:12345 0.0.0.0:* LISTEN
tcp6 0 0 :::12345 :::* LISTEN

Mais sous Linux en configuration par défaut, l'existence de la socket
IPv6 sur :: empêche la création de la socket IPv4 sur 0.0.0.0 pour le
même port. D'où le message d'erreur. Cependant la socket IPv6 accepte
les connexions en IPv4 donc la redirection devrait quand même
fonctionner. J'ai testé, chez moi ça marche.

L'option -4 force ssh à n'utiliser que des sockets IPv4, ce qui évite le
conflit avec la socket IPv6.

A noter que tout ceci est valable aussi pour le démon serveur sshd.



Merci pour toutes ces explications détaillées. Les choses sont claires
sur cet aspect ipv4/ipv6.



Par contre a priori la machine serveur SSH n'a rien à voir là-dedans,


OK

je ne vois pas non plus en quoi la présence de la passerelle influe.



Pourtant c'est un fait : si j'insère la gw, le forçage ipv4 devient
nécessaire pour éliminer le message.
Sans machine gw (c'est donc la machine avec l'ip publique qui initie la
connexion) , et sans forçage ipv4 je n'ai pas le message...
Avatar
Pascal Hambourg
cwpbl a écrit :
Pascal Hambourg a écrit :

J'essaie d'accéder à un service de {serveur} à partir de {machine}
via un bête tunnel ssh. A noter que _{machine} a une ip publique_.



En quoi c'est important qu'elle ait une adresse IP publique ?



Voir plus bas.



J'ai lu. Mais même sans pouvoir l'expliquer j'aurais plus tendance à
attribuer cette bizarrerie à la présence de {gw} qu'à l'adresse IP
publique ou privée de {machine}.

Par contre a priori la machine serveur SSH n'a rien à voir là-dedans,



OK



Ceci dit, tu as écrit avoir "lu qu'il y a avait une confusion ipv4/ipv6
sur le serveur ssh de {site}". Pourrais-tu développer ?

je ne vois pas non plus en quoi la présence de la passerelle influe.



Pourtant c'est un fait : si j'insère la gw, le forçage ipv4 devient
nécessaire pour éliminer le message.
Sans machine gw (c'est donc la machine avec l'ip publique qui initie la
connexion) , et sans forçage ipv4 je n'ai pas le message...



Le truc bizarre, c'est qu'il devrait y avoir le message d'erreur dans
les deux cas, mais que la redirection devrait quand même marcher.

Tout ce que je peux proposer pour essayer de trouver une explication,
c'est de comparer la configuration IP de {machine} avec "ifconfig" ou
"ip addr", et les sockets TCP en écoute sur {port} créées par ssh avec
"netstat --inet --inet6 -tlnp |grep {port}" dans les deux situations.

Si tu pouvais publier les résultats ici, en maquillant les adresses IP
publiques éventuellement, ça m'intéresse. Merci.