通过 Jump Host 使用 SSH,使用动态端口号

通过 Jump Host 使用 SSH,使用动态端口号

我有 3 个主机:

  1. 我的电脑。
  2. 具有静态 IP 的跳转主机 (又名堡垒)。
  3. 具有动态 IP 的服务器;位于 NAT 路由器/防火墙后面,没有打开任何入站端口。

服务器当前连接到 Jump Host,并通过 建立 SSH 隧道-R "0:localhost:22",因此端口由 Jump Host 动态分配(到目前为止这非常可靠)。

和一些插座魔法,我已将动态分配的端口号记录在 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帐户(在 Jump Host 上)受到严格限制(仅用于建立这些隧道连接),我需要进行设置,StreamLocalBindMask=0111以便 Jump Host 上的帐户可以使用此套接字文件。同样,如果通过 建立了新连接,则应删除旧套接字文件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 作业,它从 Jump Host 收集端口号,并创建一个新~/.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为了确保我能得到一个返回的数字。如果我的 Jump Host 被攻陷,我不希望端口文件包含一些额外的(恶意的)SSH 配置。

相关内容