SSH,透過跳轉主機,具有動態連接埠號

SSH,透過跳轉主機,具有動態連接埠號

我有 3 個主機:

  1. 我的電腦。
  2. 具有靜態 IP 的跳轉主機(又稱堡壘)。
  3. 具有動態IP的伺服器;在 NAT 路由器/防火牆後面,沒有開啟入站連接埠。

伺服器目前連接到Jump Host,並透過 建立SSH隧道-R "0:localhost:22",因此連接埠由Jump Host動態分配(到目前為止這已經非常可靠)。

和一些套接字魔法,我將動態分配的連接埠號碼記錄在跳轉主機上的一個檔案中。

有了這個,我可以透過 SSH 連接到 Jump Host,然後運行ssh -p $(cat /path/to/port-file) localhost

但是否可以跳過這個額外的步驟呢?


這對於 Ansible 很有用,我inventory.yml需要更新連接埠號碼:

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"

或許可以使用ProxyCommand

它可以(某種程度上)在我的電腦~/.ssh/config檔案上使用命令替換:

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

echo -n當替換似乎發生在我的本機電腦上時,這可以工作(即使沒有)。

儘管首先使用 SSH 獲取連接埠號碼的效率很低,但這不起作用:

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

結果是:

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

奇怪的是,伺服器(在鏈的末尾)確實在其身份驗證日誌中註意到了這一點:

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

這意味著正在返回連接埠號。但不知道為什麼它會在此時破裂。

ssh -vvv表明它識別了我的~/.ssh/known_hosts.


我還嘗試使用 , 在跳轉主機上建立自訂「ssh_config」文件,其ssh -F /path/to/ssh_config內容為:

Host tunnel.server
  HostName localhost
  Port 34625

但我認為我不能將其與ProxyCommand.


我還懷疑StrictHostKeyChecking=no當連接埠號碼發生變化時,可能需要在某個時候引入。

答案1

第二個部分解決方案,受到@anx的啟發...

建立套接字文件

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

然後,要使用此套接字(來自 Jump Host),我可以使用socat

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

使用socat似乎是一個不必要的步驟,我確信一定有一種方法可以讓命令ssh直接使用套接字文件,但我還找不到它。

我還沒有找到如何從我的電腦使用此套接字檔案(因為 ProxyCommand 在本機上運行,而不是在 JumpHost 上運行)。

我還應該注意;由於tunnel帳戶(在跳轉主機上)非常受限制(它只能建立這些隧道連接),我需要進行設置,StreamLocalBindMask=0111以便我在跳轉主機上的帳戶可以使用此套接字檔案。同樣,如果透過 建立新連接,則應刪除舊的套接字檔案StreamLocalBindUnlink=yes

這兩個選項都需要在跳轉主機上的「/etc/ssh/sshd_config」中設定:

Match User tunnel
  StreamLocalBindMask 0111
  StreamLocalBindUnlink yes

不幸的是,Match在 2020 年 9 月 27 日發布的 OpenSSH 8.4 之前,「/etc/ssh/sshd_config.d/tunnel.conf」中的規則被忽略(錯誤報告),並且目前在 Ubuntu 20.04.1 LTS 上不可用。

答案2

臨時解決方案,不太理想...

在我的電腦上新增每小時一次的 cron 作業,它從跳轉主機收集連接埠號,並建立一個新~/.ssh/config_tunnels檔案。

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

然後主~/.ssh/config文件就可以使用Include ~/.ssh/config_tunnels.

請注意,我用來sed確保我能得到一個號碼。如果我的跳轉主機受到威脅,我不希望連接埠檔案包含一些額外的(惡意)SSH 配置。

相關內容