1 votes

SSH, via un hôte Jump, avec un numéro de port dynamique

J'ai 3 hôtes :

  1. Mon ordinateur.
  2. Un hôte de saut (aka bastion) avec une IP statique.
  3. Un serveur avec une IP dynamique ; derrière un routeur/pare-feu NAT, sans ports entrants ouverts.

Le serveur se connecte actuellement à l'hôte Jump, et établit un tunnel SSH via -R "0:localhost:22" Le port est donc alloué dynamiquement par l'hôte de saut (ce qui s'est avéré très fiable jusqu'à présent).

Avec quelques magie de la prise J'ai le numéro de port alloué dynamiquement enregistré dans un fichier sur l'hôte Jump.

Avec cela, je peux SSH à l'hôte Jump, et exécuter ssh -p $(cat /path/to/port-file) localhost

Mais est-il possible de sauter cette étape supplémentaire ?


Cela serait utile pour Ansible, où mon inventory.yml doit avoir le numéro de port mis à jour :

server:
  # /usr/bin/ssh jh cat /path/to/port-file
  ansible_port: "34625"
  ansible_host: "localhost"
  ansible_ssh_common_args: "-o ProxyCommand='ssh -q -W %h:%p jh' -o StrictHostKeyChecking=no"

Il pourrait être possible d'utiliser ProxyCommand :

Il peut (en quelque sorte) utiliser la substitution de commande sur mes ordinateurs. ~/.ssh/config fichier :

Host server
  ProxyCommand ssh -q -W localhost:$(echo "34625") jh

Cela fonctionne (même sans echo -n ) où la substitution semble se faire sur mon ordinateur local.

Et malgré l'inefficacité de l'utilisation de SSH pour obtenir d'abord le numéro de port, cela ne fonctionne pas :

Host server
  ProxyCommand ssh -q -W localhost:$(ssh jh cat /path/to/port-file) jh

Il en résulte :

Bad packet length 1349676916.
ssh_dispatch_run_fatal: Connection to UNKNOWN port 65535: message authentication code incorrect

Et curieusement, le serveur (à la fin de la chaîne), le note dans ses journaux d'authentification :

sshd[5558]: Bad protocol version identification '' from ::1 port 36048

Ce qui implique que le numéro de port est renvoyé. Mais je n'ai aucune idée de la raison pour laquelle il est cassé à ce stade.

Et ssh -vvv montre qu'il identifie la clé de l'hôte dans mon ~/.ssh/known_hosts .


J'ai également essayé de créer un fichier "ssh_config" personnalisé sur l'hôte Jump, en utilisant les éléments suivants ssh -F /path/to/ssh_config avec le contenu :

Host tunnel.server
  HostName localhost
  Port 34625

Mais je ne pense pas que je puisse l'utiliser avec les ProxyCommand .


Je soupçonne aussi StrictHostKeyChecking=no pourrait devoir être introduite à un moment donné, lorsque le numéro de port change.

2voto

Craig Francis Points 603

Deuxième solution partielle, inspirée par @anx...

Créer un fichier de socket

ssh -R '/path/to/socket-file:localhost:22' tunnel@jh

Ensuite, pour utiliser cette socket (depuis l'hôte Jump), je peux utiliser socat :

ssh -o "ProxyCommand socat - UNIX-CLIENT:/path/to/socket-file" localhost

L'utilisation de socat semble être une étape inutile, où je suis sûr qu'il doit y avoir un moyen d'obtenir la ssh pour utiliser directement le fichier socket, mais je ne l'ai pas encore trouvé.

Je n'ai pas non plus trouvé comment utiliser ce fichier socket depuis mon ordinateur (car ProxyCommand est exécuté sur localhost, pas sur le JumpHost).

Je dois également noter que, comme le tunnel (sur l'hôte de saut) est très restreint (il n'est là que pour établir ces connexions par tunnel), je dois définir les paramètres suivants StreamLocalBindMask=0111 pour que mon compte sur l'hôte Jump puisse utiliser ce fichier socket. De même, l'ancien fichier de socket doit être supprimé si une nouvelle connexion est établie, par l'intermédiaire de StreamLocalBindUnlink=yes .

Ces deux options doivent être définies sur l'hôte Jump, dans "/etc/ssh/sshd_config" :

Match User tunnel
  StreamLocalBindMask 0111
  StreamLocalBindUnlink yes

Malheureusement Match sont ignorées dans "/etc/ssh/sshd_config.d/tunnel.conf" avant OpenSSH 8.4, publié le 27 septembre 2020 ( rapport de bogue ), et ce n'est pas actuellement disponible sur Ubuntu 20.04.1 LTS.

0voto

Craig Francis Points 603

Solution temporaire, pas idéale...

J'ajoute une tâche cron horaire sur mon ordinateur, qui collecte le(s) numéro(s) de port de l'hôte de saut, et crée un nouveau fichier de type ~/.ssh/config_tunnels fichier.

#!/bin/bash

set -u;

config_path="${HOME}/.ssh/config_tunnels";

port=$(/bin/ssh jh /bin/cat /path/to/port-file 2> /dev/null | /bin/sed 's/[^0-9]//g');
if [[ "${port}" -lt 1024 ]]; then
  exit; # Probably a blank/zero value (e.g. connection issue).
fi

{
  echo "";
  echo "Host server";
  echo "  ProxyCommand ssh -q -W localhost:${port} jh";
  echo "";
} > "${config_path}";

chown user:group "${config_path}";
chmod 600 "${config_path}";

Les principaux ~/.ssh/config peut alors utiliser Include ~/.ssh/config_tunnels .

Note, j'utilise sed pour être sûr que je reçoive un numéro en retour. Si mon hôte Jump devait être compromis, je ne veux pas que le fichier de port contienne une configuration SSH supplémentaire (malveillante).

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