我下班时使用SSH隧道来绕过各种隐蔽的防火墙(我的老板没关系:))。问题是,一段时间后,ssh连接通常会挂起,并且隧道断开。甚至没有想过这样做的方法。

当然,对于那些可以告诉我如何防止ssh连接挂起的人,要加分!

评论

您的隧道因不活动而死了吗?我在通过电话建立端口隧道时遇到了这个问题,因此我最终结束了在连接上生成虚拟命令以使用watch命令将其设置为“ alive”,例如:watch -n1 60 echo“ wiiiii”。除非网络断开或您不使用它,否则隧道不会消失。

相关:unix.stackexchange.com/q/200239

#1 楼

听起来您需要autossh。这将监视ssh隧道并根据需要重新启动它。我们已经使用了两年了,它似乎运行良好。

评论


+1表示autossh,它会按照提示进行操作。我相信其功能的一部分还在于发送保持活动风格的数据包,以防止任何形式的超时。

–akent
09年9月8日于13:55

autossh -f -nNT -i〜/ keypair.pem -R 2000:localhost:22 username@myoutsidebox.com您可能会注意到,我使用-nNT设置了此设置,它不会创建远程终端,因此可以将autossh放入后台,以及-i选项使SSH使用.pem文件。如果您要一直保持连接打开,我绝对建议您进行额外的设置。

– juckele
15年8月31日在20:01



就其价值而言,似乎最好省略-M参数:bugs.debian.org/cgi-bin/bugreport.cgi?bug=351162

– rinogo
2015年9月15日在22:40



我这样做是为了让它在网络更改后重试,对我来说效果很好:autossh -M 0 -o“ ServerAliveInterval 10” -o“ ServerAliveCountMax 2” -L 9999:localhost:19999 server@example.com

–卢克·斯坦利(Luke Stanley)
17年6月29日在13:23

对于那些只是复制然后想知道为什么他们的连接可能会变慢的人:-C强制压缩连接,这在调制解调器线路和缓慢的Internet连接上很有用,但是如果建立了快速连接,则实际上会减慢速度。如今,除非您的连接速度非常慢,否则极有可能不使用它。

–五彩纸屑
18-10-23在8:53

#2 楼

所有有状态的防火墙在一段时间内都没有看到该连接的数据包后会忘记连接(以防止状态表充满连接,而两端都死了而不关闭连接)。大多数TCP实现会在很长一段时间后发送keepalive数据包,而不会听到对方的声音(2小时是常见值)。但是,如果有状态防火墙在发送keepalive数据包之前忘记了连接,那么长寿但闲置的连接将消失。防止连接变得空闲。 OpenSSH具有一个称为ServerAliveInterval的选项,该选项可用于防止连接空闲太长时间(作为奖励,即使连接处于空闲状态,它也会检测对等端何时更快死亡)。

评论


指定的间隔以秒为单位,因此您可以进行一些微调。如果您的状态防火墙的空闲超时为5分钟,则60或120秒足以保持连接打开。这是我通过家用路由器保持ssh会话打开的方式之一。

– Darren Hall
09年12月2日在21:16

谢谢,这有所帮助。但是请注意(从此处排名较低的答案,superuser.com / a / 146641/115515),如果您指定ServerAliveInterval而不是ServerAliveCountMax,则可能会发现ssh故意比您想要的更快地断开连接。

–美达美
2012年1月26日在21:54

@metamatt,您引用的排名较低的答案是出于充分原因而排名较低的:它是错误的。

–伦巴特
2014年2月20日下午0:14

#3 楼

我使用以下Bash脚本在上一个死亡时继续产生新的ssh隧道。当您不想或无法安装其他软件包或使用编译器时,使用脚本非常方便。

while true
do
  ssh <ssh_options> [user@]hostname
  sleep 15
done


请注意,这需要密钥文件来自动建立连接但是autossh也是如此。

评论


您应该添加任何原因,而不是在autossh上使用此脚本,还是这样更容易?

–雷米
2012年10月20日17:25

如果ssh自身冻结,这将无济于事,不是吗?

– nafg
13年11月25日在23:59

如果您无法在服务器中安装东西,它将很有帮助。 autossh没有预先安装,有时会变得很钝。

–夸克
17年3月13日在15:13

是的,最好不必安装东西。一年以来,我一直以这种方式进行操作,这是保持远程计算机可访问性的唯一方法(甚至将crontab设置为在重新启动时运行它)。它永远不会失败,更重要的是,我知道为什么它永远不会失败。

– sudo
18-4-2在6:42



#4 楼

在您自己的Mac或Linux计算机上,配置ssh,每3分钟使服务器ssh保持活动状态。打开一个终端,然后将您不可见的.ssh放在家里:

cd ~/.ssh/ 


,然后使用以下命令创建一个1行配置文件:

echo "ServerAliveInterval 180" >> config


还应该添加:

ServerAliveCountMax xxxx (high number)


默认值为3,因此ServerAliveInterval 180将在9分钟(3分钟间隔中的3分钟)后停止发送由ServerAliveInterval指定)。

评论


请注意,如果您已经有配置文件,则不建议您使用该命令。使用>>进行重定向会更好!

–珀尔帖
2011年3月18日在9:34

为什么ServerAliveInterval 180给我们6分钟?直觉让我尝试:180/60 ==3。那么,ServerAliveInterval是否可以30秒的倍数工作?

–nemesisfixx
2011年11月30日14:37

@mcnemesis:ServerAliveInterval 180表示3分钟。 ServerAliveCountMax默认值为3表示这些间隔为3,即9分钟。

–美达美
2012年1月26日21:50

我赞成这个答案,因为感谢您提到ServerAliveCountMax,以及如果指定不带ServerAliveCountMax的ServerAliveInterval会发生什么。但是像前面的评论一样,我注意到“将在以后停止发送”的计算是错误的,并且我认为如果仅给出这些选项的信息,而不告诉我们如何使用cd和echo命令应用它们,则此答案将更好。 。

–美达美
2012年1月26日21:51

拒绝投票是因为将ServerAliveCountMax设置为“高数字”没有意义。 ServerAliveCountMax指定在放弃之前它将尝试发送“ keepalive”消息的次数。默认值为3,因此使用ServerAliveInterval 180时,如果服务器在9分钟后未响应,则它将仅停止发送,在这种情况下,您的连接可能很好并且确实死了。

–伦巴特
2014年2月20日下午0:13

#5 楼



创建服务文件/etc/systemd/system/sshtunnel.service包含:

[Unit]
Description=SSH Tunnel
After=network.target

[Service]
Restart=always
RestartSec=20
User=sshtunnel
ExecStart=/bin/ssh -NT -o ServerAliveInterval=60 -L 5900:localhost:5900 user@otherserver

[Install]
WantedBy=multi-user.target


(修改ssh命令以适合)


它将以用户sshtunnel的身份运行,因此请确保用户首先存在
发出systemctl enable sshtunnel以将其设置为在启动时启动
发出systemctl start sshtunnel以立即启动


2018年1月更新:某些发行版(例如Fedora 27)可能会使用SELinux策略来阻止从systemd init使用SSH,在这种情况下,需要创建自定义策略以提供必要的豁免。 br />

评论


这看起来与我的主旨非常相似:gist.github.com/guettli/…欢迎反馈!

– Guettli
17/12/22在11:47

非常适合系统化系统。如果使用Restart = on-failure,则手动终止SSH客户端将不会导致系统成功重启,因为SSH客户端成功退出。

– David Tonhofer
18年3月22日在19:36

例如,如果您想从作为ExecStart参数的(bash)脚本启动ssh以构建ssh参数列表,请进行基本检查等,然后从脚本中调用它,例如exec / bin / ssh -N...。是我的命令:exec / bin / ssh -N -oExitOnForwardFailure =是-oTCPKeepAlive = no -oServerAliveInterval = 5 -oServerAliveCountMax = 6 -i“ $ {LOCAL_PRIVATE_KEY}” -L“ $ {TUNNEL_INLET}:$ {TUNNEL_OUTLET}”“ $ {REMOTE_USER} @ $ {REMOTE_MACHINE}“,其中TUNNEL_INLET =” 127.0.0.1:3307“和TUNNEL_OUTLET =” 127.0.0.1:3306“

– David Tonhofer
18-3-22在19:42



#6 楼

在我看来,您肯定误解了ServerAliveCountMax。据我了解的文档,这是在不终止连接的情况下无法应答的服务器活动消息的数量。因此,在类似我们此处讨论的情况下,将其设置为较高的值只会确保不会检测到挂起的连接并终止该连接!

只需设置ServerAliveInterval就足以解决带有防火墙会忘记连接,而将ServerAliveCountMax设置为低电平将使始发端能够注意到故障并在连接失败时终止。

您想要的是,1)在以下情况下使连接永久保持打开状态正常情况下,2)检测到连接失败并在发生故障时退出发起方,3)每次退出时都重新发出ssh命令(您的操作方式与平台密切相关,“ while true “ Jawa建议的脚本是一种方法,在OS XI上实际上设置了启动项)。

#7 楼

如果隧道问题是由过期的NAT会话生成的,请始终使用ServerAliveInterval SSH选项。

如果连接完全断开,请始终使用重生方法,此处至少有三个选项:

bash脚本(while true do ssh ...; sleep 5; done)不能删除sleep命令,ssh可能会很快失败,并且您将重新生成太多进程

/etc/inittab可以访问在NAT之后在另一个国家/地区发货和安装的盒子,而无需将端口转发到盒子,您可以对其进行配置以创建一条回送给您的ssh隧道:

tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip 'sleep 365d'



Ubuntu上的upstart脚本,其中/etc/inittab不可用:

start on net-device-up IFACE=eth0
stop on runlevel [01S6]
respawn
respawn limit 180 900
exec ssh -i /path/to/rsaKey -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip
post-stop script
    sleep 5
end script



或始终使用这两种方法。

评论


内联选项+1,以防您不需要所有SSH连接

–user1146334
2014年7月7日14:29

您写“以防连接性完全下降”。现在我不明白,autossh可以解决哪些问题,而不能解决什么问题?我认为,当然可以解决任何断开的连接,例如拔掉电缆几个小时,但也许不会吗?

– Mads Skjern
16年5月12日在19:02



#8 楼

我用以下方法解决了这个问题:

编辑

~/.ssh/config


并添加

ServerAliveInterval 15
ServerAliveCountMax 4


根据ssh_config的手册页:

ServerAliveCountMax
         Sets the number of server alive messages (see below) which may be
         sent without ssh(1) receiving any messages back from the server.
         If this threshold is reached while server alive messages are
         being sent, ssh will disconnect from the server, terminating the
         session.  It is important to note that the use of server alive
         messages is very different from TCPKeepAlive (below).  The server
         alive messages are sent through the encrypted channel and there‐
         fore will not be spoofable.  The TCP keepalive option enabled by
         TCPKeepAlive is spoofable.  The server alive mechanism is valu‐
         able when the client or server depend on knowing when a connec‐
         tion has become inactive.

         The default value is 3.  If, for example, ServerAliveInterval
         (see below) is set to 15 and ServerAliveCountMax is left at the
         default, if the server becomes unresponsive, ssh will disconnect
         after approximately 45 seconds.  This option applies to protocol
         version 2 only.

 ServerAliveInterval
         Sets a timeout interval in seconds after which if no data has
         been received from the server, ssh(1) will send a message through
         the encrypted channel to request a response from the server.  The
         default is 0, indicating that these messages will not be sent to
         the server.  This option applies to protocol version 2 only.


评论


每隔15秒似乎经常对服务器执行ping操作。

–伦巴特
2014年2月20日下午0:08

@Lambart,但是如果连接确实不稳定并且经常断开连接,则它至少会检测到连接中断,并有机会更早地重试。

– Binki
2014年12月13日下午2:00

在macOS 10.15.3上不起作用

– 4F2E4A2E
20-2-13在9:59

#9 楼

ExitOnForwardFailure yes是其他建议的很好的附件。如果它已连接但无法建立端口转发,则对您来说就好像根本没有连接一样。

评论


这是一个很好的主意。如果以前的连接在远程端比在本地主机中更早超时,则即使autossh也没用,因为在这种情况下,本地主机将尝试再次连接,但由于端口仍处于打开状态,因此无法建立转发。

–劳尔·萨利纳斯-蒙塔古多
17年5月24日在7:42

#10 楼

我需要长期维护SSH隧道。我的解决方案是从Linux服务器上运行的,它只是一个小型C程序,它使用基于密钥的身份验证来重新生成ssh。

我不确定挂起的原因,但是隧道已经死了超时。

我想为重生器提供代码,但我现在似乎找不到。

#11 楼

虽然有诸如autossh之类的工具可以帮助重新启动ssh会话...我发现真正有用的是运行“ screen”命令。即使断开连接,它也允许您恢复ssh会话。如果您的连接不够可靠,则特别有用。


http://www.howtogeek.com/howto/ubuntu/keep-your-ssh-session-running- when-you-disconnect /

...别忘了标记这是“正确的”答案,如果它可以帮助您! ;-)

评论


...但是问题是关于如何保持SSH隧道开放,而不仅仅是终端会话。屏幕很棒!

–akent
2009年9月8日14:15在

我已经使用屏幕了,但是并不能解决我的问题:-/不过,谢谢您的回答。

–珀尔帖
2009年9月8日14:15在

#12 楼

有点骇人听闻,但我喜欢使用屏幕来保持这种状态。我目前有一个运行了数周的远程转发。

示例,从本地开始:

screen
ssh -R ......


screen
Ctrl + a + d


现在您有了不间断的远程转发。诀窍是在两端都运行屏幕

#13 楼

最近我自己遇到了这个问题,因为这些解决方案要求您每次使用密码登录名时都重新输入密码,因此我在循环中使用sshpass以及文本提示来避免在批处理文件中使用密码。

如果其他人遇到相同的问题,我想在这个主题上分享我的解决方案:

#!/bin/bash
read -s -p "Password: " pass
while true
do
    sshpass -p "$pass" ssh user@address -p port
    sleep 1
done


#14 楼

我以前的ISP遇到过类似的问题。
对我来说,任何tcp连接,访问网站或发送邮件都是相同的。

解决方案是通过UDP配置VPN连接(我正在使用OpenVPN)。这种连接对导致断开的原因更宽容。然后,您可以通过此连接运行任何服务。

连接仍然可能存在问题,但是由于隧道可以容忍任何ssh会话,因此它们会产生短暂的延迟,而不是被断开连接。 >
要执行此操作,您将需要在线VPN服务,您可以在自己的服务器上对其进行设置。

#15 楼

由于autossh不能满足我们的需求(如果第一次尝试无法连接到服务器,就会出现错误),因此我们编写了一个纯bash应用程序:https://github.com/aktos-io/link -with-server

默认情况下,它为服务器上NODE的sshd端口(22)创建反向隧道。如果您需要执行任何其他操作(例如转发其他端口,通过连接发送邮件等),则可以放置脚本on-connecton-disconnect文件夹。

#16 楼

您可以非常简单地在远程服务器上使用tmux命令。它允许您在将运行远程代码的远程计算机上打开“会话”。

然后,您可以退出远程计算机(或在您的情况下断开连接),而无需担心tmux会话中的代码安全运行。

最后,当您在远程服务器上重新连接时,您只需tmux attach即可返回到之前打开的会话,仅此而已。