我在 Azure 上运行的 Ubuntu 虚拟机上运行各种服务,我想远程访问其中一些服务,即使端口未公开开放。为此,我设置了一个脚本来执行使用 SSH 进行本地端口转发。
通常,此方法通过启动与远程主机的连接、执行sleep 10
并在 sleep 命令完成之前在转发端口上建立连接来实现。当使用保持连接活动的服务(例如远程 SMB 共享)时,此方法非常有效。
但是我在访问 Web 服务时遇到了问题,因为连接会在一段时间后关闭 - 建立连接后 10 到 90 秒。
为了在连接关闭时重新连接,我根据这个编写了一个小脚本SO线程。
while true; do { \
while true; do \
echo echo ping; sleep 10; \
done } | ssh -f myapp.cloudapp.net -F .ssh/myapp.cloudapp.net_config \
-o ExitOnForwardFailure=yes sleep 10; echo "$(date) I died";
sleep 1;
done
不幸的是,这个“修复”有点不靠谱,连接经常断开,因此浏览器每发出五个请求就会挂起一次。这个方法有效,但远非完美,所以我想要一个更好的方法。也许可以有某种脚本进行长轮询或类似操作?有谁解决了这个问题吗?
答案1
使用自动SSH。它以包的形式存在,无需您编写脚本即可处理所有这些问题。还可以在 ssh 配置文件中配置 Keepalive 和 ClientAliveInterval 以及 ServerAliveInterval。选项与 ssh 类似,但它会自动处理断开的连接。
例如,启动反向隧道(并保持其运行):
server_behind_fw # autossh -M 20000 -f -N your_public_server -R 1234:localhost:22 -C
进而:
your_public_seerver # ssh -p 1234 localhost
将通过 ssh 将您连接到 server_behind_fw。
答案2
在这里添加我自己的答案,因为实际上没有一个答案能为我的情况提供明确的解决方案。但这基本上是@sivann 的答案针对我的具体情况修改的。所以如果它对你有帮助,请给他点赞!
完整的命令行
# This forwards all requests to my local 39000 port to port 8080 on the server
LOCAL_PORT=39000
REMOTE_PORT=8080
SERVER=myapp.cloudapp.net
autossh -M20000 -N -L $LOCAL_PORT:$SERVER:$REMOTE_PORT myuser@$SERVER
与我上面拼凑起来的黑客脚本相比,到目前为止,这已被证明是极其稳定的。
使用配置文件
如果你想将配置保存在每个服务器的文件中,它看起来应该是这样的
$HOME/.ssh/config_myapp.cloudapp.net
Host myapp.cloudapp.net
User myuser
LocalForward 127.0.0.1:39000 localhost:8080
ServerAliveInterval 5
使用配置文件的命令行
autossh -M 12345 -N -F $HOME/.ssh/config_myapp.cloudapp.net 192.168.10.2
答案3
使用-N
命令行标志ssh
将保持连接运行而无需执行任何命令,因此您不需要睡眠命令。
此外,您还应设置ClientAliveInterval
并ServerAliveInterval
按照这个答案。
答案4
不要过多地使用 sleep 和 ping,而是告诉 ssh 发送 keepalive 数据包。您要查找的选项是 ServerAliveInterval。这会告诉 ssh 每隔几秒发送一些数据,以便服务器(以及沿途的任何 nat 防火墙)知道连接仍然打开,并且您的会话不会超时。这仍然应该与一个脚本结合使用,如果连接由于其他原因失败,该脚本将自动重新连接。
这里有一个配置示例:http://embraceubuntu.com/2006/02/03/keeping-ssh-sessions-alive/