Suivi: Il semble que la série rapide de déconnexions coïncidant avec quelques mois de fonctionnement de chaque serveur soit probablement fortuite et ne fasse que révéler le problème réel. La raison pour laquelle il n'a pas réussi à se reconnecter est presque certainement due aux valeurs AliveInterval (réponse de Kasperd). L'utilisation de l'option ExitOnForwardFailure devrait permettre au délai d'exécuter correctement avant de se reconnecter, ce qui devrait résoudre le problème dans la plupart des cas. La suggestion de MadHatter (le script kill) 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 lance 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 régulièrement 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 sur un autre fournisseur de VPS - des mois de fonctionnement parfait, puis soudainement plusieurs pannes 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, dit-il 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 nécessite le redémarrage du VPS. D'ici là, toutes les tentatives de reconnexion donneront le message "échec de la redirection de port distant" et ne fonctionneront pas. C'est maintenant au point où le tunnel ne dure que 4 heures environ avant de s'arrêter.
Rien n'a changé sur le VPS, et il s'agit d'une machine à usage unique et à utilisateur unique qui ne sert que de point de terminaison de 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 n'arrive pas à expliquer pourquoi, ou pourquoi cela se produirait 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 laissant les ports ouverts et ne les fermant jamais. Cela semble être le principal problème. Je ne suis tout simplement pas sûr de ce qui pourrait le faire se comporter de cette façon après des mois de comportement comme je m'y attendais (c'est-à-dire fermer les ports immédiatement et permettre au script de se reconnecter).
la source
Réponses:
Je suis d'accord avec MadHatter, qu'il s'agit probablement de redirection de port à partir de connexions ssh disparues. Même si votre problème actuel se révèle être autre chose, vous pouvez vous attendre à rencontrer de telles connexions ssh disparues tôt ou tard.
Il existe trois façons dont ces connexions disparues peuvent se produire:
Déterminer lequel des trois ci-dessus se produit n'est pas très important, car il existe une méthode qui répondra aux trois. C'est l'utilisation de messages keepalive.
Vous devriez rechercher le
ClientAliveInterval
mot - clé poursshd_config
et l'ServerAliveInterval
intervalle pourssh_config
ou~/.ssh/config
.L'exécution de la
ssh
commande en boucle peut fonctionner correctement. C'est également une bonne idée d'insérer un sommeil dans la boucle afin de ne pas inonder le serveur lorsque la connexion échoue pour une raison quelconque.Si le client se reconnecte avant la fin de la connexion sur le serveur, vous pouvez vous retrouver dans une situation où la nouvelle connexion ssh est active, mais sans redirection de port. Pour éviter cela, vous devez utiliser le
ExitOnForwardFailure
mot - clé côté client.la source
-o ExitOnForwardFailure yes
c'est exactement ce dont j'avais besoin. C'est donc une chose de moins que je dois comprendre. Pour penser, j'allais écrire un script Python pour analyser ces messages d'avertissement. C'est beaucoup plus simple. : DExitOnForwardFailure
quand j'ai écrit ma réponse. Je l'ai ajouté à la réponse maintenant.-o ExitOnForwardFailure=yes
(notez le signe égal). Donc, si quelqu'un rencontre cela, ne copiez pas et ne collez pas mon commentaire précédent, cela ne fonctionnera pas. : PVous pouvez trouver le processus qui lie le port sur ce serveur avec
Il semble très probable que ce soit le demi-disparu
sshd
, mais pourquoi faire des hypothèses lorsque vous pouvez avoir des données? C'est également un bon moyen pour un script de trouver un PID auquel envoyer le signal 9 avant d'essayer de réactiver le tunnel.la source
Pour moi, lorsqu'un
ssh
tunnel se déconnecte, il faut un certain temps pour que la connexion se réinitialise, lessh
processus continue de se bloquer, me laissant sans tunnel actif et je ne sais pas pourquoi. Une solution de contournement consiste à mettressh
en arrière-plan avec-f
et à générer de nouvelles connexions sans attendre la réinitialisation des anciennes connexions. Le-o ExitOnForwardFailure=yes
peut être utilisé pour limiter le nombre de nouveaux processus. La-o ServerAliveInterval=60
améliore la fiabilité de votre connexion actuelle.Vous pouvez répéter la
ssh
commande fréquemment, par exemple, dans uncron
, ou, dans une boucle de votre script, par exemple, dans ce qui suit, nous exécutons lassh
commande toutes les 3 minutes:la source
-o ExitOnForwardFailure=yes
était ce que je cherchais, merci beaucoup!D'après mon expérience, ssh a une habitude un peu gênante de ne pas quitter proprement si «quelque chose» fonctionne toujours sur le système distant. Par exemple, a commencé en arrière-plan. Vous pouvez le reproduire en:
Votre ssh se déconnectera, mais ne fermera pas réellement la session - jusqu'à ce que le processus distant se termine (ce qui ne sera pas le cas, 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 généré par ssh. Le port reste utilisé et ne peut donc pas être réutilisé par votre processus local.
la source
ssh -o ConnectTimeout=10 -o BatchMode=yes -gnN -R *:X:localhost:X root@$TUNSRV 1>>tunnel.log 2>&1 &
donc rien n'est exécuté par SSH sauf le tunnel lui-même, spécifiquement en raison de l'option -N. Tout ce qui est maintenu ouvert se fait sur le serveur distant B à l'aide de sshd lui-même.