357 votes

Comment maintenir de manière fiable un tunnel SSH ouvert ?

J'utilise un tunnel SSH depuis le travail pour contourner divers pare-feu idiots (cela ne pose pas de problème avec mon patron :)). Le problème est que, après un certain temps, la connexion ssh se fige généralement et le tunnel est interrompu.

Si je pouvais au moins surveiller le tunnel automatiquement, je pourrais le redémarrer lorsqu'il se fige, mais je n'ai même pas trouvé de moyen de le faire.

Des points bonus pour celui qui peut me dire comment empêcher ma connexion ssh de se figer, bien sûr !

0 votes

Est-ce que votre tunnel est mort à cause de l'inactivité? J'ai eu ce problème lorsque je transférais des ports depuis mon téléphone, alors j'ai finalement commencé à générer des commandes factices sur la connexion pour le maintenir "en vie" en utilisant la commande watch comme ceci : watch -n1 60 echo "wiiiii". Le tunnel ne mourra pas à moins que le réseau ne soit coupé ou que vous ne l'utilisiez pas.

2 votes

408voto

Mike Green Points 607

Il semble que vous avez besoin de autossh. Cela surveillera un tunnel ssh et le redémarrera si nécessaire. Nous l'avons utilisé pendant quelques années et il semble bien fonctionner.

autossh -M 20000 -f -N your_public_server -R 1234:localhost:22 -C

Plus de détails sur le paramètre -M ici

3 votes

+1 pour autossh, il fait ce qu'il annonce. Je crois qu'une partie de sa fonctionnalité consiste également à envoyer des paquets de style keep-alive pour éviter tout type de déconnexion.

19 votes

autossh -f -nNT -i ~/keypair.pem -R 2000:localhost:22 username@myoutsidebox.com Vous remarquerez que j'ai configuré cela en utilisant -nNT, ce qui ne crée pas de terminal distant pour que je puisse mettre autossh en arrière-plan, et l'option -i pour SSH afin d'utiliser un fichier .pem. Si vous prévoyez de maintenir une connexion ouverte en permanence, je recommande vraiment de passer par la configuration supplémentaire.

3 votes

Pour ce que ça vaut, il semble généralement préférable d'omettre le paramètre -M: bugs.debian.org/cgi-bin/bugreport.cgi?bug=351162

51voto

IanB Points 507

Systemd est idéalement adapté pour cela.

Créez un fichier de service /etc/systemd/system/sshtunnel.service contenant :

[Unit]
Description=Tunnel SSH
After=network.target

[Service]
Restart=always
RestartSec=20
User=sshtunnel
ExecStart=/bin/ssh -NT -o ServerAliveInterval=60 -L 5900:localhost:5900 user@otherserver

[Install]
WantedBy=multi-user.target

(Modifiez la commande ssh selon vos besoins)

  • cela s'exécutera en tant qu'utilisateur sshtunnel donc assurez-vous que cet utilisateur existe d'abord
  • exécutez systemctl enable sshtunnel pour le démarrer au démarrage
  • exécutez systemctl start sshtunnel pour le démarrer immédiatement

Mise à jour Jan 2018: Certaines distributions (par exemple Fedora 27) peuvent utiliser la politique SELinux pour empêcher l'utilisation de SSH à partir de l'init de systemd, auquel cas une politique personnalisée devra être créée pour fournir les exemptions nécessaires.

6 votes

Cela ressemble beaucoup à mon gist: gist.github.com/guettli/… Vos retours sont les bienvenus!

2 votes

Excellent pour un système systemd. Si on utilise Restart=on-failure, alors tuer manuellement le client SSH ne provoquera pas de redémarrage par systemd car le client SSH se terminera avec succès.

1 votes

Si vous souhaitez démarrer ssh à partir d'un script (bash) donné en argument à ExecStart, par exemple pour construire la liste d'arguments ssh, effectuer des vérifications de base, etc., puis l'appeler à partir du script comme suit exec /bin/ssh -N .... Voici ma commande: exec /bin/ssh -N -oExitOnForwardFailure=Yes -oTCPKeepAlive=no -oServerAliveInterval=5 -oServerAliveCountMax=6 -i "${LOCAL_PRIVATE_KEY}" -L "${TUNNEL_INLET}:${TUNNEL_OUTLET}" "${REMOTE_USER}@${REMOTE_MACHINE}"TUNNEL_INLET="127.0.0.1:3307" et TUNNEL_OUTLET="127.0.0.1:3306"

46voto

Jim Harte Points 101

Tous les pare-feu conservent l'état oublient une connexion après un certain temps sans recevoir de paquet pour cette connexion (pour éviter que les tables d'état ne soient pleines de connexions où les deux extrémités se sont déconnectées sans fermer la connexion). La plupart des implémentations TCP enverront un paquet keepalive après un long moment sans nouvelles de l'autre partie (2 heures est une valeur courante). Cependant, s'il y a un pare-feu étatique qui oublie la connexion avant que les paquets keepalive ne puissent être envoyés, une connexion longue mais inactive mourra.

Si tel est le cas, la solution est d'empêcher la connexion de devenir inactive. OpenSSH a une option appelée ServerAliveInterval qui peut être utilisée pour empêcher la connexion de rester inactive trop longtemps (en bonus, cela permet de détecter plus rapidement si le pair est déconnecté même si la connexion est inactive).

0 votes

L'intervalle spécifié est en secondes, vous pouvez donc effectuer un réglage fin. Si votre pare-feu étatique a un délai d'inactivité de 5 minutes, alors 60 ou 120 secondes suffisent pour maintenir la connexion ouverte. C'est l'une des façons dont je garde mes sessions ssh ouvertes à travers mon routeur domestique.

1 votes

Merci, cela a aidé. Mais notez (à partir d'une réponse de rang inférieur ici, superutilisateur.com/a/146641/115515) que si vous spécifiez ServerAliveInterval et non ServerAliveCountMax, vous pouvez trouver ssh se déconnectant intentionnellement plus tôt que prévu.

7 votes

@metamatt, la réponse moins bien classée à laquelle vous faites référence est moins bien classée pour une bonne raison : ELLE EST FAUSSE.

38voto

Mak Points 173

J'ai utilisé le script Bash suivant pour continuer à lancer de nouveaux tunnels ssh lorsque le précédent meurt. Utiliser un script est pratique lorsque vous ne voulez pas ou ne pouvez pas installer de packages supplémentaires ou utiliser un compilateur.

while true
do
  ssh  [utilisateur@]nom_hôte
  sleep 15
done

Remarquez que cela nécessite un fichier de clé pour établir la connexion automatiquement, mais c'est également le cas avec autossh.

3 votes

Vous devriez ajouter toutes les raisons pour lesquelles vous utiliseriez ce script plutôt que autossh, ou est-ce simplement que c'est plus facile de cette manière?

5 votes

Cela ne servirait à rien si ssh se figeait lui-même, n'est-ce pas?

8 votes

Il est utile si vous ne pouvez pas installer de choses sur le serveur. autossh n'est pas préinstallé et la bureaucratie est parfois très obtuse.

23voto

user1950278 Points 401

Sur votre propre machine Mac ou Linux, configurez votre ssh pour maintenir le serveur ssh en vie toutes les 3 minutes. Ouvrez un terminal et allez dans votre dossier .ssh invisible dans votre répertoire personnel :

cd ~/.ssh/ 

puis créez un fichier de configuration d'une ligne avec :

echo "ServerAliveInterval 180" >> config

vous devriez également ajouter :

ServerAliveCountMax xxxx (nombre élevé)

la valeur par défaut étant 3, donc ServerAliveInterval 180 cessera d'envoyer après 9 minutes (3 des intervalles de 3 minutes spécifiés par ServerAliveInterval).

3 votes

Notez que l'utilisation de cette commande n'est pas recommandée si vous avez déjà un fichier de configuration. Utiliser >> pour la redirection serait bien meilleur !

0 votes

Pourquoi est-ce que ServerAliveInterval 180 nous donne 6 minutes ? L'intuition me fait essayer ceci : 180/60 == 3. Donc, est-ce que ServerAliveInterval fonctionne en multiples de 30 secondes ?

0 votes

@mcnemesis : ServerAliveInterval 180 signifie 3 minutes. ServerAliveCountMax par défaut de 3 signifie 3 de ces intervalles, donc 9 minutes.

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