357 votes

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

Je utilise un tunnel SSH depuis le travail pour contourner divers pare-feu idiots (mon patron est d'accord :)). Le problème est que, après un certain temps, la connexion SSH se bloque généralement et le tunnel est rompu.

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

Points bonus pour celui qui peut me dire comment éviter que ma connexion SSH se bloque, bien sûr !

0 votes

Est-ce que votre tunnel est mort à cause de l'inactivité? J'ai rencontré ce problème lors du tunneling des ports depuis mon téléphone, j'ai donc finalement lancé des commandes factices sur la connexion pour le maintenir "actif" en utilisant la commande watch comme ceci : watch -n1 60 echo "wiiiii". Le tunnel ne mourra pas à moins que le réseau soit compromis 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 votre_serveur_public -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 dit sur l'étain. Je crois qu'une partie de sa fonctionnalité consiste également à envoyer des paquets de style keep-alive pour éviter tout type de délai d'attente.

19 votes

autossh -f -nNT -i ~/keypair.pem -R 2000:localhost:22 username@myoutsidebox.com Vous remarquerez que j'ai configuré ceci 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 allez maintenir une connexion ouverte en permanence, je recommande vivement 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 l'utilisateur existe d'abord
  • exécutez systemctl enable sshtunnel pour le configurer pour démarrer au démarrage
  • exécutez systemctl start sshtunnel pour démarrer immédiatement

Mise à jour janv. 2018 : certaines distributions (par ex. Fedora 27) peuvent utiliser une politique SELinux pour empêcher l'utilisation de SSH depuis 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 commentaires sont les bienvenus!

2 votes

Excellent pour un système systemd. Si on utilise Restart=on-failure, tuer manuellement le client SSH ne déclenchera pas un redémarrage par systemd car le client SSH se fermera 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 depuis le script comme ceci 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 étatiques oublient une connexion après un certain temps sans voir de paquet pour cette connexion (pour éviter que les tables d'état ne se remplissent de connexions où les deux extrémités sont mortes sans fermer la connexion). La plupart des implémentations TCP enverront un paquet de maintien de la connexion après un long moment sans nouvelles de l'autre côté (2 heures est une valeur commune). Cependant, s'il y a un pare-feu étatique qui oublie la connexion avant que les paquets de maintien de la connexion puissent être envoyés, une connexion longue mais inactive mourra.

Si c'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 éviter que la connexion ne reste inactive trop longtemps (en bonus, elle détectera quand le pair est mort plus tôt même si la connexion est inactive).

0 votes

L'intervalle spécifié est en secondes, donc vous pouvez effectuer quelques ajustements fins. Si votre pare-feu stateful 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 constater que ssh se déconnecte intentionnellement plus tôt que vous ne le vouliez.

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  [user@]hostname
  sleep 15
done

Remarquez que cela nécessite un fichier de clé pour établir la connexion automatiquement, mais c'est aussi 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 qu'il est plus facile de cette manière?

5 votes

Ça ne servirait à rien si ssh se fige lui-même, n'est-ce pas?

8 votes

Il est utile si vous ne pouvez pas installer des 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 actif toutes les 3 minutes. Ouvrez un terminal et allez dans votre dossier invisible .ssh dans votre dossier personnel :

cd ~/.ssh/ 

puis créez un fichier de configuration en une seule ligne avec :

echo "ServerAliveInterval 180" >> config

Vous devriez également ajouter :

ServerAliveCountMax xxxx (nombre élevé)

la valeur par défaut est de 3 donc ServerAliveInterval 180 cessera d'envoyer après 9 minutes (3 x l'intervalle de 3 minutes spécifié par ServerAliveInterval).

3 votes

Notez que la 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 ServerAliveInterval 180 nous donne-t-il 6 minutes? L'intuition me pousse à 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 est de 3, ce qui 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