arthur.bebou

Le site arthur.bebou.netlib.re - retour accueil

git clone git://bebou.netlib.re/arthur.bebou
Log | Files | Refs |

index.sh (7284B)


      1 #! page
      2 title: Mosh, IRC, les multi-connections ssh et NAT
      3 author: Arthur Pons
      4 description: Comment faire de la multiconnection ssh à travers mosh sur un serveur derrière un NAT
      5 publication: 2024-11-14
      6 
      7 sectionmd: main
      8 
      9 Sur bebou nous avons un serveur IRC. J'aime bien avoir une fenêtre ouverte en
     10 continu sur le serveur afin de répondre rapidement aux copaines. L'objectif est
     11 :
     12 
     13   * de ne rater aucun message sur le serveur IRC
     14   * de ne pas avoir à se reconnecter et relancer la session quand on coupe la
     15     connexion
     16   * de profiter de cette session constamment ouverte pour accélerer toutes les
     17     commandes ssh qu'on lance ensuite
     18 
     19 ## Ne rien rater de ce qui se raconte sur IRC
     20 
     21 À la création d'un compte, le serveur lance automatiquement une session
     22 [tmux](https://github.com/tmux/tmux/wiki) avec un client IRC dedans. De cette
     23 manière quand une personne quitte sa session, tmux continue à tourner, le client
     24 reste ouvert et ainsi elle ne passera à côté d'aucun message.
     25 
     26 A l'usage c'est génial *sauf que* si vous utilisez ssh vous n'êtes pas sans
     27 savoir que c'est fragile. ssh fonctionne de telle manière à ce que la connexion
     28 saute au moindre souci. Vous avez perdu la wifi pendant une seconde ? Plus de
     29 connexion.  Vous avez mis votre ordi en veille ? Plus de connexion. La session
     30 tmux permet de ne pas perdre l'état de la session sur laquelle vous étiez[^1]
     31 mais il faudra tout de même vous y reconnecter.
     32 
     33 ## Ne jamais perdre sa connexion
     34 
     35 C'est là qu'intervient [mosh](https://mosh.org). Je ne vous fais pas la réclame
     36 complète, vous pouvez aller sur le site du projet directement. Ce qui nous
     37 intéresse ici est principalement la capacité de `mosh` à récupérer la connexion
     38 là où elle s'est arrêtée partout où avec ssh elle aurait ét morte pour de bon.
     39 On ouvre la session une fois au démarrage de son pc puis on l'oublie, elle sera
     40 toujours vivante. *Second besoin satisfait*.
     41 
     42 Si vous en êtes là vous constaterez une chose : lancer une nouvelle commande
     43 ssh prend tout de même du temps. En effet, par défaut, le client ssh initie une
     44 nouvelle connexion pour chaque ouverture de session. Il faudra repasser par
     45 tout le système d'authentification à chaque fois, ce qui prend du temps.
     46 On pourrait penser qu'il est possible de réutiliser la connexion existante et
     47 ainsi s'économiser de précieuses secondes.
     48 
     49 ## Réutiliser la connexion
     50 
     51 Effectivement, c'est possible avec la configuration ssh suivante, à mettre dans
     52 son `~/.ssh/config` :
     53 
     54     Host *
     55     ControlMaster auto
     56     ControlPath  ~/.ssh/sh-%r@%h:%p
     57     ControlPersist yes
     58 
     59   * `Host *` : Pour toute connexion 
     60   * `ControlMaster auto` : utiliser une connexion existante si elle existe,
     61     sinon la créer
     62   * `ControlPath ~/.ssh/sh-%r@%h:%p` : Le chemin du socket par lequel passer
     63     sera `~/.ssh/sh-%r@%h:%p`. `%r` est le nom du compte, `%h` le nom de la
     64     machine et `%p` le port
     65   * `ControlPersist yes` : Si une connexion se termine, laisser le socket
     66     ouvert (jusqu'à redémarrage de la machin) pour toute autre connexion
     67 
     68 La dernière ligne est essentielle si l'on utilise mosh. À la connexion mosh
     69 ouvre une connexion ssh pour échanger des clefs de chiffrement, la ferme
     70 instantanément puis ouvre une session mosh. `ControlPersist yes` permet de
     71 conserver le socket créé à cette occasion même après la fermeture de la
     72 connexion ssh.
     73 
     74 **Sécurité** : avant d'adopter cette configuration demandez vous si cela vous
     75 expose à un risque que vous ne pouvez pas accepter. En effet si on la combine
     76 avec un agent ssh relaxe, du type à ne presque jamais demander le mot de passe
     77 des clefs ssh, c'est la porte ouverte à toute connexion du moment que l'on
     78 mette la main sur votre ordinateur. Pas forcément grave pour bebou mais
     79 certainement plus dans un cadre professionnel par exemple. Si vous
     80 voulez plus de sécurité vous pouvez jouer sur la valeur de `ControlPersist`
     81 afin d'avoir un timeout par exemple. Voir `man ssh_config`. Il est également
     82 possible d'avoir un script tiers qui désactive la clef dans votre agent ssh
     83 et/ou supprime le socket à la mise en veille de votre pc. Posez vous les
     84 bonnes questions et adoptez le bon niveau de sécurité.
     85 
     86 ## Faire fonctionner `ControlMaster` et mosh ensemble vers un serveur NATé
     87 
     88 On pourrait en avoir fini sauf que non ! Pour ouvrir une connection, mosh a
     89 besoin de connaître l'ip de la machine distante. Pour cela il existe plusieurs
     90 techniques. Celle par défaut de mosh, nommée "proxy", utilise la `ProxyCommand`
     91 d'ssh pour récupérer le nom canonique de l'hôte distant et ainsi son ip. Malin.
     92 Sauf que, comme nous l'enseigne [cette
     93 issue](https://github.com/mobile-shell/mosh/issues/24), la configuration
     94 `ControlMaster` désactive `ProxyCommand`. La personne qui développe mosh a
     95 retenu comme solution de forcer la désactivation de `ControlMaster` lors de la
     96 connexion ssh qui précède la connexion mosh avec un `-S`[^2]. Certaines
     97 personnes voulant tout de même utiliser `ControlMaster`, deux autres techniques
     98 ne nécessitant pas `ProxyCommand` on été implémentées.  L'une, `local`,
     99 consiste à vérifier des valeurs de variables d'environnement locales (à vous de
    100 les setup). L'autre, `remote`, profite de la première connexion ssh pour
    101 exécuter une commande donnant l'ip sur la machine distante, lit ce résultat et
    102 le passe au processus exécutant la commande `mosh-client`.  Dans le code
    103 d'origine de `mosh` cette technique repose sur le contenu de la variable
    104 d'environnement `$SSH_CONNECTION`. Malheureusement sur un serveur NATé, tel que
    105 bebou, `$SSH_CONNECTION` contiendra l'ip **locale** du serveur et non pas l'ip
    106 du routeur derrière lequel il est. Pour récupérer la bonne ip il convient donc
    107 de modifier la commande shell lancée à distance pour une commande donnant la
    108 bonne ip, par exemple un `curl` vers https://ipinfo.io/ip. En l'occurrence dans
    109 la version que j'ai, on modifie la ligne 368 :
    110 
    111     shell_quote ( '[ -n "$SSH_CONNECTION" ] && printf "\nMOSH SSH_CONNECTION %s\n" "$SSH_CONNECTION"' ) .
    112 
    113 par :
    114 
    115     shell_quote ( 'printf "\nMOSH SSH_CONNECTION c d %s e\n" "$(curl -sS http://ipinfo.io/ip)"' ) .
    116 
    117 Si vous préférez une autre technique pour récupérer l'ip mettez ce que vous
    118 voulez à la place du `curl`. Après cette modification on pourra utiliser
    119 l'option `--experimental-remote-ip=remote` de mosh pour forcer l'utilisation
    120 de cette technique en lieu de celle qui désactive `ControlMaster`.
    121 
    122 Le résultat de toute cette affaire : dès que l'on lance une session mosh, y
    123 compris vers un serveur NATé, un socket persistant est créé !
    124 
    125 [^1]: et ce serait la première raison d'être des multiplexeurs type tmux et
    126     screen. Ayant découvert cette informatique à un moment où les connexions
    127     étaient déjà très fiables dans les grandes villes française je n'avais
    128     jamais perçu cet avantage là. Je pensais que c'était pour avoir plusieurs
    129     fenêtre sur un même terminal.
    130 [^2]: vous pouvez aller lire tout ça dans le script mosh en faisant un `vim
    131     $(whereis mosh)`. C'est du perl et c'est lisible. Le `-S` est ligne 408
    132     par exemple. On y voit la construction de la commande ssh qui sera lancée,
    133     avec la commande proxy contenant un `%h` permettant de récupérer le nom
    134     canonique de l'hôte.