SSH über einen Jump Host mit einer dynamischen Portnummer

SSH über einen Jump Host mit einer dynamischen Portnummer

Ich habe 3 Hosts:

  1. Mein Computer.
  2. Ein Jump Host (auch Bastion genannt) mit einer statischen IP.
  3. Ein Server mit einer dynamischen IP; hinter einem NAT-Router/einer NAT-Firewall, ohne geöffnete eingehende Ports.

Der Server stellt derzeit eine Verbindung zum Jump-Host her und baut einen SSH-Tunnel über auf -R "0:localhost:22", sodass der Port dynamisch vom Jump-Host zugewiesen wird (dies war bisher sehr zuverlässig).

Mit etwasSteckdosenmagie, ich habe die dynamisch zugewiesene Portnummer in einer Datei auf dem Jump Host aufgezeichnet.

Damit kann ich per SSH auf den Jump Host zugreifen undssh -p $(cat /path/to/port-file) localhost

Aber ist es möglich, diesen zusätzlichen Schritt zu überspringen?


Dies wäre für Ansible nützlich, wo inventory.ymldie Portnummer aktualisiert werden muss:

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"

Möglicherweise könnten Sie Folgendes verwenden ProxyCommand:

Es kann (irgendwie) eine Befehlsersetzung auf die ~/.ssh/configDatei meines Computers anwenden:

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

Dies funktioniert (auch ohne echo -n), wobei die Ersetzung auf meinem lokalen Computer zu erfolgen scheint.

Und trotz der Ineffizienz, SSH zu verwenden, um zuerst die Portnummer zu erhalten, funktioniert dies nicht:

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

Es fuehrt zu:

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

Und seltsamerweise vermerkt der Server (am Ende der Kette) Folgendes in seinen Authentifizierungsprotokollen:

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

Das bedeutet, dass die Portnummer zurückgegeben wird. Aber keine Ahnung, warum es an dieser Stelle abbricht.

Und ssh -vvvzeigt, dass es den Hostschlüssel in meinem identifiziert ~/.ssh/known_hosts.


Ich habe außerdem versucht, auf dem Jump Host eine benutzerdefinierte „ssh_config“-Datei ssh -F /path/to/ssh_configmit folgendem Inhalt zu erstellen:

Host tunnel.server
  HostName localhost
  Port 34625

Aber ich glaube nicht, dass ich das mit dem verwenden kann ProxyCommand.


Ich vermute auch, dass es StrictHostKeyChecking=nomöglicherweise irgendwann eingeführt werden muss, wenn sich die Portnummer ändert.

Antwort1

Zweite Teillösung, inspiriert von @anx...

Erstellen einer Socket-Datei

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

Um diesen Socket (vom Jump Host) zu verwenden, kann ich dann Folgendes verwenden socat:

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

Die Verwendung von socatscheint ein unnötiger Schritt zu sein, da es sicher eine Möglichkeit geben muss, den sshBefehl dazu zu bringen, die Socket-Datei direkt zu verwenden, die ich aber noch nicht finden kann.

Ich habe auch nicht herausgefunden, wie ich diese Socket-Datei von meinem Computer aus verwenden kann (da ProxyCommand auf dem lokalen Host und nicht auf dem JumpHost ausgeführt wird).

Ich sollte auch beachten: Da das tunnelKonto (auf dem Jump Host) sehr eingeschränkt ist (es ist nur dazu da, diese Tunnelverbindungen herzustellen), muss ich es StreamLocalBindMask=0111so einrichten, dass mein Konto auf dem Jump Host diese Socket-Datei verwenden kann. Ebenso sollte die alte Socket-Datei entfernt werden, wenn eine neue Verbindung hergestellt wird, über StreamLocalBindUnlink=yes.

Beide Optionen müssen auf dem Jump Host in „/etc/ssh/sshd_config“ festgelegt werden:

Match User tunnel
  StreamLocalBindMask 0111
  StreamLocalBindUnlink yes

Leider Matchwerden Regeln in "/etc/ssh/sshd_config.d/tunnel.conf" vor OpenSSH 8.4, veröffentlicht am 27. September 2020, ignoriert (Fehlerbericht), und dies ist derzeit unter Ubuntu 20.04.1 LTS nicht verfügbar.

Antwort2

Vorübergehende Lösung, nicht ideal ...

Fügen Sie auf meinem Computer einen stündlichen Cron-Job hinzu, der die Portnummer(n) vom Jump-Host sammelt und eine neue ~/.ssh/config_tunnelsDatei erstellt.

#!/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}";

Die Hauptdatei ~/.ssh/configkann dann verwenden Include ~/.ssh/config_tunnels.

Beachten Sie, dass ich sedsicher bin, dass ich eine Nummer zurückbekomme. Wenn mein Jump Host kompromittiert werden sollte, möchte ich nicht, dass die Port-Datei eine zusätzliche (bösartige) SSH-Konfiguration enthält.

verwandte Informationen