使用 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
的连接,然后打开另一个从 jump
到 final
的连接,并启用必要的转发。
在您的配置中,您已将 ProxyCommand
替换为执行某些设置的 shell 脚本。之后您仍然需要 运行 类似普通 ssh 命令的命令。
给定像您这样的配置行:
ProxyCommand ~/.ssh/get_dynamic_port.sh ssh -W %h:%p jumphost
调用普通 ssh 命令(您将其作为参数传递给 shell 脚本)的最简单方法是在最后调用它:
#!/bin/sh
# ... custom stuff ...
# new final line:
eval "$@"
我有一个服务器设置,可以在一定时间后随机化它的 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
的连接,然后打开另一个从 jump
到 final
的连接,并启用必要的转发。
在您的配置中,您已将 ProxyCommand
替换为执行某些设置的 shell 脚本。之后您仍然需要 运行 类似普通 ssh 命令的命令。
给定像您这样的配置行:
ProxyCommand ~/.ssh/get_dynamic_port.sh ssh -W %h:%p jumphost
调用普通 ssh 命令(您将其作为参数传递给 shell 脚本)的最简单方法是在最后调用它:
#!/bin/sh
# ... custom stuff ...
# new final line:
eval "$@"