36 votes

Échec du transfert de port distant SSH

Suivi : Il semble que la série rapide de déconnexions coïncidant avec quelques mois de fonctionnement de chaque serveur soit probablement une coïncidence et ait juste servi à révéler le problème réel. La raison de l'échec de la reconnexion est presque certainement due aux valeurs de AliveInterval (réponse de kasperd). L'utilisation de l'option ExitOnForwardFailure devrait permettre au délai d'attente de se produire correctement avant la reconnexion, ce qui devrait résoudre le problème dans la plupart des cas. La suggestion de MadHatter (le kill script) est probablement le meilleur moyen de s'assurer que le tunnel peut se reconnecter même si tout le reste échoue.

J'ai un serveur (A) derrière un pare-feu qui initie un tunnel inverse sur plusieurs ports vers un petit VPS DigitalOcean (B) afin que je puisse me connecter à A via l'adresse IP de B. Le tunnel fonctionne de manière constante depuis environ 3 mois, mais a soudainement échoué quatre fois au cours des dernières 24 heures. La même chose s'est produite il y a quelque temps chez un autre fournisseur de VPS - des mois de fonctionnement parfait, puis soudainement de multiples défaillances rapides.

J'ai un script sur la machine A qui exécute automatiquement la commande tunnel ( ssh -R *:X:localhost:X address_of_B pour chaque port X) mais quand il s'exécute, il dit Warning: remote port forwarding failed for listen port X .

Entrer dans le sshd /var/log/secure sur le serveur montre ces erreurs :

bind: Address already in use
error: bind: Address already in use
error: channel_setup_fwd_listener: cannot listen to port: X

La résolution de ce problème nécessite le redémarrage du VPS. En attendant, toutes les tentatives de reconnexion donnent le message "remote port forwarding failed" et ne fonctionnent pas. Le tunnel ne dure plus qu'environ 4 heures avant de s'arrêter.

Rien n'a changé sur le VPS, et il s'agit d'une machine à usage unique, à utilisateur unique, qui sert uniquement de point de terminaison du tunnel inverse. Il exécute OpenSSH_5.3p1 sur CentOS 6.5. Il semble que sshd ne ferme pas les ports de son côté lorsque la connexion est perdue. Je suis incapable d'expliquer pourquoi, ou pourquoi cela se produit soudainement après des mois de fonctionnement presque parfait.

Pour clarifier, je dois d'abord comprendre pourquoi sshd refuse d'écouter sur les ports après l'échec du tunnel, ce qui semble être causé par sshd qui laisse les ports ouverts et ne les ferme jamais. Cela semble être le problème principal. Je ne suis simplement pas sûr de ce qui pourrait le faire se comporter de cette manière après des mois de comportement comme je l'attends (c'est-à-dire fermer les ports immédiatement et permettre au script de se reconnecter).

37voto

martin Points 49

Je suis d'accord avec MadHatter, il s'agit probablement d'une redirection de port provenant de connexions ssh défuntes. Même si votre problème actuel s'avère être autre chose, vous pouvez vous attendre à rencontrer de telles connexions ssh défuntes tôt ou tard.

Ces connexions défectueuses peuvent se produire de trois façons :

  • L'un des deux points d'extrémité a été redémarré alors que l'autre extrémité de la connexion était complètement inactive.
  • L'un des deux points d'extrémité a fermé la connexion, mais au moment où la connexion a été fermée, il y a eu une interruption temporaire de la connexion. La panne a duré quelques minutes après la fermeture de la connexion, et l'autre extrémité n'a donc jamais appris que la connexion était fermée.
  • La connexion est toujours parfaitement fonctionnelle aux deux extrémités de la connexion ssh, mais quelqu'un a placé un dispositif à état quelque part entre les deux, ce qui a interrompu la connexion pour cause d'inactivité. Ce dispositif dynamique peut être un NAT ou un pare-feu, le pare-feu que vous avez déjà mentionné étant le principal suspect.

Il n'est pas très important de déterminer lequel des trois cas ci-dessus se produit, car il existe une méthode qui permet de les traiter tous les trois. Il s'agit de l'utilisation des messages keepalive.

Vous devriez vous pencher sur le ClientAliveInterval mot-clé pour sshd_config et le ServerAliveInterval intervalle pour ssh_config o ~/.ssh/config .

L'exécution du ssh dans une boucle peut fonctionner correctement. C'est une bonne idée d'insérer également un sleep dans la boucle afin de ne pas inonder le serveur lorsque la connexion échoue pour une raison quelconque.

Si le client se reconnecte avant que la connexion ne soit terminée sur le serveur, vous pouvez vous retrouver dans une situation où la nouvelle connexion ssh est active, mais n'a pas de transfert de port. Afin d'éviter cela, vous devez utiliser la fonction ExitOnForwardFailure du côté client.

5voto

ibisum Points 101

Pour moi, quand un ssh tunnel se déconnecte, il faut un certain temps pour que la connexion soit rétablie. ssh continue de se bloquer, ce qui fait que je n'ai aucun tunnel actif et je ne sais pas pourquoi. Une solution de contournement consiste à mettre ssh en arrière-plan avec -f et de créer de nouvelles connexions sans attendre la réinitialisation des anciennes connexions. Le site -o ExitOnForwardFailure=yes peut être utilisé pour limiter le nombre de nouveaux processus. Le site -o ServerAliveInterval=60 améliore la fiabilité de votre connexion actuelle.

Vous pouvez répéter le ssh fréquemment, par exemple dans une cron ou, dans une boucle de votre script, par exemple, dans ce qui suit, nous exécutons la commande ssh toutes les 3 minutes :

while (1)
do
    ssh -f user@hostname -Rport:host:hostport -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=60
    sleep 180
done

4voto

MadHatter Points 77602

Vous pouvez trouver le processus qui lie le port sur ce serveur avec

sudo netstat -apn|grep -w X

Il semble très probable qu'il s'agisse de l'entreprise à moitié disparue. sshd mais pourquoi faire des hypothèses quand on peut avoir des données ? C'est aussi un bon moyen pour un script de trouver un PID auquel envoyer le signal 9 avant d'essayer de faire remonter le tunnel.

2voto

Garo Points 141

À en juger par votre description, les autres réponses ici sont plus utiles.
Mais pour les autres qui remarquent des problèmes de transfert de port vers un serveur spécifique et qui se retrouvent sur cette page :

Dans de nombreux cas, le problème est que le serveur ssh est configuré pour bloquer le transfert de port. Pour changer cela :

  • Ouvrez le fichier sshd-configuration ( /etc/ssh/sshd_config sur la plupart des systèmes)
  • S'il y a une ligne AllowTcpForwarding no enlevez-le.
    En fonction de votre version d'openssh, vous devrez également ajouter explicitement AllowTcpForwarding yes
    (Dans le doute : faites-le)
  • Redémarrez le serveur ssh

0voto

Sobrique Points 3695

D'après mon expérience, ssh a la fâcheuse habitude de ne pas se terminer proprement si "quelque chose" est encore en cours d'exécution sur le système distant. Par exemple, démarré en arrière-plan. Vous pouvez reproduire cela en :

ssh <server>
while true; do  sleep 60; done&
exit

Votre ssh se déconnectera, mais ne fermera pas réellement la session - jusqu'à ce que le processus distant se termine (ce qu'il ne fera pas, car il s'agit d'une boucle 'while true'). Il se peut que quelque chose de similaire se produise - votre session a un processus 'bloqué' qui est créé par ssh. Le port reste utilisé et ne peut donc pas être réutilisé par votre processus local.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X