我有一台服务器,还有一台位于一个不方便的网络后面的桌面。为了远程访问我的桌面,我让它与我的服务器保持反向 SSH 连接,然后我可以通过它正在使用的任何反向 SSH 端口通过 SSH 连接到我的服务器和桌面。
具体来说,我的桌面正在运行一个小 Bash 脚本,如下:
#!/bin/bash
while true; do
ssh -X -R 19123:localhost:22 http://www.example.pro/
sleep 1000
done
然后,在服务器上,可以使用以下命令访问桌面:
ssh localhost -p 19123
这似乎工作正常。连接可以可靠地维持和重新建立,我可以从桌面在服务器上运行命令等,验证连接确实处于活动状态。
然而过了一段时间,比如几天后,桌面就无法从服务器访问了。在桌面上,连接处于活动状态,但在服务器上返回了以下错误消息:
ssh: connect to host localhost port 19123: Connection refused
有人能猜到会发生什么吗?更重要的是,考虑到服务器无法定期重启等,有人能建议如何防止这种情况发生吗?
答案1
让你的 ssh 时不时地发送一个 keepalive 数据包来提供帮助。
在您的~/.ssh/config
文件中添加以下内容:
Host *
ServerAliveInterval 15
这应该在服务器和客户端上进行设置。
您可以将上面的数字更改为您想要的任何数字。这是每 15 秒设置的,我的服务器连接似乎保持正常,没有任何问题。
希望这可以帮助!
答案2
正如@Terrance所说,您应该使用keepalive来保持连接打开。但是,为了提高稳定性,我还建议使用来autossh
监控ssh连接。由于它不是默认安装的,因此您需要使用来安装它sudo apt install autossh
。
安装后,您可以像这样执行它:
/usr/bin/autossh -f -o "ServerAliveInterval 900" -TN -R30582:localhost:5724 [email protected]
这将设置一个到 的 ssh 隧道[email protected]
。请注意,任何无法理解的选项autossh
都会传递给ssh
自身。
它也不会分配伪终端,从而节省了资源。
这很好,但我们可以做得更好。为了使其永久和自动化,我们可以设置一个 systemd 服务。在其中创建一个/etc/systemd/system
后缀为 的文件.service
,并在其中放入如下内容:
[Unit]
Description=SSH tunnel
[Service]
Type=forking
Environment=AUTOSSH_PIDFILE=/var/run/ssh-tunnel/ssh-tunnel.pid
PIDFile=/var/run/ssh-tunnel/ssh-tunnel.pid
ExecStartPre=/bin/mkdir -p /var/run/ssh-tunnel
ExecStartPre=-/bin/chown username:username /var/run/sbrl-ssh-tunnel
ExecStart=/bin/sh -c 'until ping -c1 bobsrockets.io &>/dev/null && sleep 5; do :; done && /usr/bin/autossh -f -o "UserKnownHostsFile /home/username/.ssh/known_hosts" -o "IdentityFile /home/username/.ssh/ssh-tunnel_ed25519" -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -o "ServerAliveInterval 900" -TN -R30582:localhost:5724 -p 7261 [email protected]'
[Install]
WantedBy=network-online.target
这里有几点值得注意:
username
应替换为autossh
将在以下情况下运行的本地用户帐户- 我禁用密码验证,并在此处启用公钥验证,以便它可以在没有任何外部干预的情况下启动。确保在服务器上创建一个
ssh-tunnel
没有 shell 的特殊帐户(在我的示例中),并确保在安装此服务文件之前设置公钥并对其进行测试。 -p 7261
用于指定要连接的远程服务器上的目标端口。如果需要,请更新它,否则如果不需要,请删除它。known_hosts
我使用选项指定文件的位置UserKnownHostsFile
,因为当作为 systemd 服务运行时autossh
似乎无法找到它。确保将其指向合适的known_hosts
文件,以便可以自动打开 ssh 连接。- 我使用了一些 shell 脚本 (
until ping -c1 bobsrockets.io &>/dev/null && sleep 5; do :; done
) 来确保它等到我们能够到达目标主机后再启动 autossh。否则我会遇到问题。 -f
在这里用于获取autossh
fork。这可以避免无用的sh
进程闲置。