J'utilise un tunnel SSH depuis le travail pour contourner divers pare-feu idotiques (ça va avec mon patron :)). Le problème, c’est qu’après un certain temps, la connexion SSH se bloque et que le tunnel est rompu.
Si je pouvais au moins surveiller le tunnel automatiquement, je pourrais le redémarrer quand il se bloque, mais je n'ai même pas trouvé le moyen de le faire.
Des points bonus pour celui qui peut me dire comment empêcher ma connexion SSH de rester suspendue, bien sûr!
Tous les pare-feu avec état oublient une connexion après ne pas avoir vu un paquet pour cette connexion pendant un certain temps (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 keepalive après une longue période sans avoir à entendre l'autre côté (2 heures est une valeur commune). Si, toutefois, il existe un pare-feu avec état qui oublie la connexion avant que les paquets keepalive puissent être envoyés, une connexion longue durée mais inactive mourra.
Si tel est le cas, la solution consiste à éviter que la connexion ne devienne inactive. OpenSSH a une option appelée ServerAliveInterval qui peut être utilisée pour éviter que la connexion ne soit inactive trop longtemps (en prime, elle détectera le moment où l'homologue est mort plus tôt, même si la connexion est inactive).
Sur votre propre ordinateur Mac ou Linux, configurez votre SSH pour maintenir le serveur SSH en vie toutes les 3 minutes. Ouvrez un terminal et installez votre .ssh invisible chez vous:
cd ~/.ssh/
puis créez un fichier de configuration d'une ligne avec:
echo "ServerAliveInterval 180" >> config
vous devriez aussi ajouter:
ServerAliveCountMax xxxx (high number)
la valeur par défaut est 3; ServerAliveInterval 180 cesse alors d'envoyer après 9 minutes (3 des 3 minutes spécifiées par ServerAliveInterval).
J'ai utilisé le script Bash suivant pour continuer à générer de nouveaux tunnels SSH lorsque le précédent est mort. L'utilisation d'un script est pratique lorsque vous ne voulez pas ou ne pouvez pas installer de paquets supplémentaires ni utiliser le compilateur.
while true
do
ssh <ssh_options> [user@]hostname
sleep 15
done
Notez que cela nécessite un fichier de clés pour établir la connexion automatiquement, mais c'est également le cas avec autossh.
Systemd convient parfaitement pour cela.
Créez un fichier de service /etc/systemd/system/sshtunnel.service
contenant:
[Unit]
Description=SSH Tunnel
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 à votre convenance)
sshtunnel
alors assurez-vous que cet utilisateur existe en premiersystemctl enable sshtunnel
pour qu'il démarre au démarragesystemctl start sshtunnel
pour commencer immédiatementMise à jour janvier 2018 : certaines distributions (par exemple, Fedora 27) peuvent utiliser la stratégie SELinux pour empêcher l'utilisation de SSH depuis systemd init. prévoir les exemptions nécessaires.
Il me semble que vous interprétez mal ServerAliveCountMax. Si je comprends bien la documentation, c'est le nombre de messages actifs du serveur qui peuvent rester sans réponse sans que la connexion soit interrompue. Donc, dans les cas comme ceux dont nous discutons ici, définir une valeur élevée garantira simplement qu’une connexion bloquée ne sera ni détectée ni interrompue!
Le simple fait de définir ServerAliveInterval devrait suffire à résoudre le problème avec un pare-feu qui oublie la connexion. Si vous laissez ServerAliveCountMax low, l’auteur de l’origine peut constater l’échec et s’arrêter si la connexion échoue quand même.
Ce que vous voulez, c’est 1) que la connexion reste ouverte en permanence dans des circonstances normales, 2) que l’échec de la connexion soit détecté et que le côté d’origine quitte en cas d’échec, et 3) que la commande ssh soit ré-émise chaque fois exits (la manière dont vous faites cela dépend beaucoup de la plate-forme, le script "while true" suggéré par Jawa est un moyen, sous OS XI, de configurer un élément de lancement).
Utilisez toujours l'option ServerAliveInterval
SSH au cas où les problèmes de tunnel sont générés par des sessions expirées NAT.
Utilisez toujours une méthode de réapparition au cas où la connectivité cesserait complètement, vous avez au moins trois options ici:
while true do ssh ...; sleep 5; done
) ne supprime pas la commande de veille, ssh
peut échouer rapidement et vous devez réactiver trop de processus/etc/inittab
, pour avoir accès à une boîte livrée et installée dans un autre pays, derrière NAT, sans transfert de port à la boîte, vous pouvez le configurer pour créer un tunnel ssh de nouveau à vous:
tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip 'sleep 365d'
script upstart sur Ubuntu, où /etc/inittab
n'est pas disponible:
start on net-device-up IFACE=eth0
stop on runlevel [01S6]
respawn
respawn limit 180 900
exec ssh -i /path/to/rsaKey -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip
post-stop script
sleep 5
end script
ou utilisez toujours les deux méthodes.
J'ai résolu ce problème avec ceci:
Modifier
~/.ssh/config
Et ajouter
ServerAliveInterval 15
ServerAliveCountMax 4
Selon page de manuel pour ssh_config:
ServerAliveCountMax
Sets the number of server alive messages (see below) which may be
sent without ssh(1) receiving any messages back from the server.
If this threshold is reached while server alive messages are
being sent, ssh will disconnect from the server, terminating the
session. It is important to note that the use of server alive
messages is very different from TCPKeepAlive (below). The server
alive messages are sent through the encrypted channel and there‐
fore will not be spoofable. The TCP keepalive option enabled by
TCPKeepAlive is spoofable. The server alive mechanism is valu‐
able when the client or server depend on knowing when a connec‐
tion has become inactive.
The default value is 3. If, for example, ServerAliveInterval
(see below) is set to 15 and ServerAliveCountMax is left at the
default, if the server becomes unresponsive, ssh will disconnect
after approximately 45 seconds. This option applies to protocol
version 2 only.
ServerAliveInterval
Sets a timeout interval in seconds after which if no data has
been received from the server, ssh(1) will send a message through
the encrypted channel to request a response from the server. The
default is 0, indicating that these messages will not be sent to
the server. This option applies to protocol version 2 only.
ExitOnForwardFailure yes
est un bon complément aux autres suggestions. S'il se connecte mais ne peut pas établir la redirection de port, il vous sera tout aussi inutile que s'il ne s'était pas connecté du tout.
Un peu de bidouille, mais j'aime bien utiliser screen pour le garder. J'ai actuellement une avance à distance qui fonctionne depuis des semaines.
Exemple, en commençant localement:
screen
ssh -R ......
Lorsque le transfert à distance est appliqué et que vous avez un shell sur l'ordinateur distant:
screen
Ctrl + a + d
Vous avez maintenant un transfert à distance ininterrompu. L'astuce consiste à lancer l'écran des deux côtés
J'ai récemment eu ce problème moi-même, car ces solutions vous obligent à ressaisir le mot de passe chaque fois que vous utilisez un identifiant de mot de passe. J'ai utilisé sshpass dans une boucle avec une invite de texte pour éviter d'avoir le mot de passe dans le fichier de commandes.
Je pensais partager ma solution sur cette thead au cas où quelqu'un d'autre aurait le même problème:
#!/bin/bash
read -s -p "Password: " pass
while true
do
sshpass -p "$pass" ssh user@address -p port
sleep 1
done
J'ai eu besoin de maintenir un tunnel SSH à long terme. Ma solution fonctionnait à partir d'un serveur Linux, et il ne s'agit que d'un petit programme en C qui rappelle ssh en utilisant une authentification par clé.
Je ne suis pas sûr de la pendaison, mais des tunnels sont morts suite à des délais trop longs.
J'adorerais fournir le code au répondant, mais je n'arrive pas à le trouver pour le moment.
bien qu'il existe des outils comme autossh qui aident à redémarrer la session SSH ... ce que je trouve vraiment utile, c'est de lancer la commande "screen". Il vous permet de reprendre vos sessions SSH même après votre déconnexion. Particulièrement utile si votre connexion n’est pas aussi fiable qu’elle devrait l’être.
... n'oubliez pas de cocher la réponse "correcte" si cela vous aide à k! ;-)
Comme autossh
ne répond pas à nos besoins (il existe une erreur s'il ne parvient pas à se connecter au serveur dès la première tentative), nous avons écrit une application pure bash: https://github.com/aktos-io/link-with-server
Il crée un tunnel inverse pour le port sshd (22) du NODE sur le serveur par défaut. Si vous devez effectuer d'autres opérations (telles que le transfert de ports supplémentaires, l'envoi de mails en connexion, etc.), vous pouvez placer vos dossiers de scripts on-connect
et on-disconnect
.
J'ai eu des problèmes similaires avec mon précédent fournisseur de services Internet. Pour moi, c'était la même chose avec n'importe quelle connexion TCP, visite de sites Web ou envoi de courrier.
La solution consistait à configurer une connexion VPN sur UDP (j'utilisais OpenVPN). Cette connexion était plus tolérante vis-à-vis de la cause des déconnexions. Ensuite, vous pouvez exécuter n'importe quel service via cette connexion.
Il peut toujours y avoir des problèmes avec la connexion, mais puisque le tunnel sera plus tolérant, toute session SSH ressentira un bref blocage plutôt que d'être déconnectée.
Pour ce faire, vous aurez besoin d’un service VPN en ligne que vous pouvez configurer sur votre propre serveur.