首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

从TCP看SSH终端断开的那些事

作者:刘金龙

1 概述

网络闪断对普通用户可能影响非常小,但是对IT人员特别是运维工程师来说,可能是暴击一万点。最惨的是正在进行游戏批量更新或者完全没保存进度的时候,SecureCRT的ssh终端突然红了,这个闪断意味着接下来的各种未知的错误和重试。

经历久了,发现如果运营商是在线路切换,可能还不能马上继续进行更新操作,因为运营商可能会马上再进行一次线路回切。再久了,我们就会想办法来避免这种事情的发生,比如常挂screen之类的,再久了,我们就来从系统命令和网络参数这两方面小总结下关于ssh断开的那些事。

2 系统命令相关

linux有很多自带的命令来防止终端异常断开的影响,除了做成daemon服务的方式之外,其余常见的就是放后台执行,关于放后台执行的命令大家应该都很熟悉,先简单回顾下。

2.1 screen

为了让任务持久运行,最友好的应该是screen,像一个windows远程终端一样把我们的任务放在那里运行,需要看的时候直接打开那个“窗口”即可。

比如简单地敲screen新建一个窗口之后,我们可以在上面运行任务,然后直接按ctrl+a+d即可把这个窗口放后台,需要的时候再通过screen –ls查看,然后通过screen –r来接管我们的窗口即可。

2.2 nohup

如果不是那种长久的需要用screen窗口的时候,简单命令我们会首选用nohup把任务放后台运行,如果是好几条命令,我们就写个小脚本,然后用nohup放后台执行,这种是最简单的情况。为了保守,有时候重启网卡或者进行网卡驱动更新操作也会用这个来护航。

但是需要警惕如果终端断开了,nohup里面的一些key交互登录的情况一般会失效。

2.3 disown

最纳闷的是如果是已经在跑的进程,怎么实现这个效果呢?有disown这个命令来拯救,不过这个是bash下面的,其余csh之类的shell不管用。

把当前任务ctrl+z切后台之后,用bg命令让其继续运行。到了可以用jobs命令可以看到任务编号在running的时候可以用disown -h %任务编号来给我们的任务加护身符。之后我们再突发地把crt软件关掉可以看到我们的任务的父进程又变为系统进程1来守护了。

2.4 其他

另外一个是正常退出终端的情况,按ctrl+d,终端会把jobs看到的命令转交给系统进程1来托管:

这样可以实现比较安全的退出,注意不是直接按crt软件的disconnect按钮,也不是直接关软件,是需要手动按ctrl+d退出终端,这样端断开之后任务也还会继续,不过感觉不太靠谱,但是没找到相关的资料。

还有个子进程的方式,这个比较少用,不太符合习惯,比如:

1 ( sleep 101 & )

2 setsid sleep 102

但是效果和上面差不多,都是在终端断开之后把进程交给系统进程1来托管。

3 网络参数

上面那些系统相关的命令大家应该都经常有用到,但是还有些网络相关的情况大家可能就没怎么去细细体会。

举两个简单的案例。

1、断网5分钟

2、拔掉网线带笔记本去开个小会

这个情况我们也是可以通过各种tcp参数来保持任务在持续运行的。注意这里只是针对开发机器的小调整,非线上海量在线机器的调优。

这里按是否有数据在传输分为两个情况,比如rsync的回显是重定向到服务器文件的,也就是不会实时传输数据到我们客户端,这个时候我们可以直接把网线拔了,等回来之后再把网线接上就可以了。注意也不要从客户端发送数据给服务端,不要乱敲键盘,SecureCRT窗口大小也不能调整。

也就是说我们的ssh连接会在一段时间内保持着,其实这里一般是涉及到两个地方的参数控制,也就是keepalive相关的控制,分为网络设备和系统控制。

3.1 网络设备

第一个是客户端到服务端中间的线路是否有网络设备在检测,比如我们cisco的路由器,会把这个nat信息保持1小时,如果还没有任何数据在传输的情况下,路由器就会释放这个nat连接,这样这个ssh就彻底断了。这个nat信息到底会保持多久呢,我们可以通过命令来查看:

3 #juniper可以这样来看nat信息

4 show security flow session source-prefix 10.1.61.23 destination-port 22 destination-prefix 123.123.123.123

可以看到这个nat信息还剩下多少秒都会给你留着,juniper默认是1800s。

5 #cisco路由器这样看:

6 show ip nat translations verbose | beg 123.123.123.123

我们路由器设置的是1小时都保持着tcp的连接(除非主动断开)。

如果是iptables做的网关,数据在这里查看:/proc/net/nf_conntrack,直接用grep匹配即可

注意,上面这一段是经过了网络nat设备的情况,如果是只经过交换机的网络,这一段就可以忽略。

看到这里大家应该可以初步理解为什么公司网络很稳定,但是家里网络ssh经常断开了,很大原因是他们设备为了尽快释放“空闲“连接而设置nat的超时时间很短,这种情况可以勾选crt软件的NO-OP功能,或者配置sshd的ClientAliveInterval参数。

3.2 系统控制

在nat有效时间内,是不是一直都保持着这个连接呢?肯定不是,因为服务器系统有自身的tcp控制逻辑,也就是我们说的空闲连接的tcp检测和数据重传。

3.2.1 空闲连接和服务端重传

注意这里是没有配置sshd_config里面的ClientAliveInterval配置的情况下发生的。如果有配置ClientAliveInterval,比如配置了30秒,那么就不会有什么空闲2小时的情况了,每30秒就有数据包发送,如果这个时间内没有恢复的话这个连接就断开了。

有个有趣的地方是,tcp_keepalive_time的值有个最大值,最大值是2**31/1000,而且还可以是负数,按照负数的理解貌似是可以永远保持这个空闲连接。不过这个也没找到相关文献,实际测试确实是可以保持很久,不过假如这个连接对应的客户端已经通过断网的形式非正常断开的话,这个连接就变成了孤儿orphans连接了。比如下图的几个好几天的IDLE连接是已经死了的。

这种tcp_keepalive_time过大造成的“死连接”是没有好办法进行断开,即使用tcpkill工具也不行,tcpkill是基于活动的连接来发送rst包的。只有停掉对应的sshd进程进行释放才行,不能是restart操作,或者把网卡down掉再重新启用,也就是万能的重启操作。

3.2.2 数据重传

上面说了如果把网线拔了之后,我们不能敲键盘,因为windows默认的重传次数和时间都很短,如果不能马上恢复连接的话,这个ssh就断开了。

而且每次间隔的时间差不是那么的固定,叫做RTO值(超时重传时间),这个值比较复杂(不太懂),大概意思是最小取200毫秒,最大取120秒,不过经多次测试,大多数默认就是200毫秒,然后递增的差值是进行2**N/10来算,当时间差超过120秒的时候间隔时间就变为120秒,累计持续重传tcp_retries2次数,默认是15次。这里大概有204+120*(n-10)秒的时间来复活这个连接。

实际上服务端的重传逻辑和上面的一样,有204+120*(n-10)秒的时间来复活这个连接。

而windows的重传次数是注册表里面的TcpMaxDataRetransmissions值,路径:

7 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters\TcpMaxDataRetransmissions

注意修改之后需要重启机器才生效。

windows好像win7和win2003不一样,我把win7的超时次数调为14,然后测试发现实际上重试了17次,而且最大是60秒的间隔差值,不是之前说的120秒:

这里大概有153+60*(n-10)秒的时间来复活这个连接。

而默认参数效果是重试9次:

会在21秒的时候就断开了,而且如果网络突然恢复了,在等待客户端继续重传的时候,再使劲乱敲键盘也是没用的,而且会造成稍后联通之后会乱执行你刚才敲的东西,服务端只认之前第一个还没完成的数据的重传,慢慢等到接下来的重传即可。可以看到如果参数过大,某些软件会一段时间都处于重传的周期内,还不如手动断开然后再连接便捷一些。

还有,这个重传的参数不影响syn的重试,也就是建立连接的重试不受这个参数影响,linux上面syn的重传受tcp_syn_retries参数控制。

4 小结

综上所说,如果我们断网了,还继续按回车之类的话,15秒左右我们的SecureCRT终端就红了,如果保持不动,运气好是空闲连接的话,在keepalive+重传时间内恢复的话,我们的终端还是活的。注意这个时候不要勾选crt软件的定时发送NO-OP信号功能。

如果服务端在传东西给我们的话,那这个连接会在等服务端传输超时之后再断开。所以针对常用的开发机,我们可以适当加大一下服务器重传的次数和keepalive的时间,win机器也可以调下注册表把次数加大来避免被快速断开。

注意所有通讯时间间隔不能超过nat设备的超时时间,参数仅供开发机微调参考,不能极端,否则有很多假连接保持着或者会造成别的不适影响。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180727B1JT1900?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券