使用 ProxyCommand 和 BASH 脚本的 SSH 配置动态端口

SSH Config Dynamic Port with ProxyCommand and BASH Script

我有一个服务器设置,可以在一定时间后随机化它的 SSH 端口,并将该端口发布到它的 Web 服务器上可用的 .txt 文件。然后我在我的客户端上编写了一个简单的脚本,它从 Web 服务器 .txt 文件中获取新端口并更新 ~/.ssh/config 中的特定主机端口号。

因为 ~/.ssh/config 无法解析 Bash 变量我用 ProxyCommand 调用脚本(我正在使用 JumpHost 并且 JH 端口是动态端口)。

我的~/.ssh/config如下:

Host jumphost
HostName jumphost.example.com
Port 51638
User bob
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null

Host myserver
HostName myserver.com
Port 2222
User bob
ProxyCommand ~/.ssh/get_dynamic_port.sh ssh -W %h:%p jumphost

Bash脚本如下(get_dynamic_port.sh):

#!/bin/sh
PORT=$(curl -s http://jumphost.example.com/port.txt)
OLDIP=`grep -w "jumphost.example.com" -A 1 ~/.ssh/config | awk '/Port/ {print }'`
LINE_NUMBER=`grep -n "jumphost.example.com" -A 1 ~/.ssh/config | grep -v "jumphost.example.com" | awk '{print }' FS="-"`
sed -i'.bak' -e "${LINE_NUMBER}s/$OLDIP/$PORT/" ~/.ssh/config

脚本工作正常并更新 jumphost.example.com 的端口,但不幸的是我无法连接,ssh 运行ning 在下面的调试输出中:

macosx:$ ssh -vvv myserver
OpenSSH_7.9p1, LibreSSL 2.7.3
debug1: Reading configuration data ~/.ssh/config
debug1: ~/.ssh/config line 54: Applying options for myserver
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 48: Applying options for *
debug1: Executing proxy command: exec ~/.ssh/get_dynamic_port.sh ssh -W myserver:2222 jumphost
debug1: identity file ~/.ssh/id_rsa type -1
debug1: identity file ~/.ssh/id_rsa-cert type -1
debug1: identity file ~/.ssh/id_dsa type -1
debug1: identity file ~/.ssh/id_dsa-cert type -1
debug1: identity file ~/.ssh/id_ecdsa type -1
debug1: identity file ~/.ssh/id_ecdsa-cert type -1
debug1: identity file ~/.ssh/id_ed25519 type -1
debug1: identity file ~/.ssh/id_ed25519-cert type -1
debug1: identity file ~/.ssh/id_xmss type -1
debug1: identity file ~/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_7.9
ssh_exchange_identification: Connection closed by remote host

应该注意的是,在 jumphost 服务器上拖尾安全日志文件不会显示任何连接尝试,这可能是错误的迹象。

jumphost 配置在没有动态端口脚本的情况下工作正常,如上所述,脚本实际上正确地更改了 jumphost 的端口,但之后 ssh 就失败了。

任何有关如何实现此目标或我可能做错了什么的想法都将不胜感激。我可以经常使用 运行 脚本的 crontab 条目来更新 jumphost 端口,但我更愿意只在建立连接时更新 jumphost 端口,看起来更干净一点方式。

谢谢:)

使用 "jumphosts" 的现代方法是使用 -J 选项 (ProxyJump)。

使用 ProxyCommand 选项仍然有效,并且可以通过调用脚本灵活地 运行 任意设置代码,如此处所示。但是,您的代码最终必须 运行 一个适当的 ssh 命令来执行 "jump".

典型的配置选项如下所示:

Host jump
    Hostname jumphost.fqdn
    User juser

Host final
    Hostname final.fqdn
    User fuser
    ProxyCommand ssh -W %h:%p jump

你 运行 ssh final 打开一个从本地主机到 jump 的连接,然后打开另一个从 jumpfinal 的连接,并启用必要的转发。

在您的配置中,您已将 ProxyCommand 替换为执行某些设置的 shell 脚本。之后您仍然需要 运行 类似普通 ssh 命令的命令。

给定像您这样的配置行:

ProxyCommand ~/.ssh/get_dynamic_port.sh ssh -W %h:%p jumphost

调用普通 ssh 命令(您将其作为参数传递给 shell 脚本)的最简单方法是在最后调用它:

#!/bin/sh

# ... custom stuff ...

# new final line:
eval "$@"