端口转发将SSH从获取终端会话的协议转换为任意转发TCP流量的工具。但大多数防火墙(和一些互联网服务提供商)故意终止一段时间内空闲的TCP连接。出于空闲状态的SSH会话最终将被服务器、客户端或其间的某个网络设备断开连接。如果你通过SSH转发服务,或者即使你懒得在每次防火墙切断连接时登录SSH服务器,你也希望保持活动会话。
大多数保持SSH连接的方法都是“在后台传递少量流量,这样中间网络设备就不会将连接视为空闲”。这些方法称为keepalives。运行一个持续显示和更新的程序,如top,可以在不更改任何SSH设置的情况下充当keepalive。你需要做的就是养成每次被打断前运行top命令的习惯。
keepalives的问题是临时断开连接终止会话。如果你的服务器提供商在半夜出现问题,并且keepalive数据包在几分钟内无法通过网络,则你的客户端或服务器将终止连接。决定如何为你的网络适当地配置keepalives。你可能根本不需要它们。
如果你的连接如此不稳定,以至于keepalives无法维持你的连接,请调查mosh(https://mosh.org),它是一种类似于SSH的远程连接协议,但专为不可靠的网络而设计。
你有两种keepalives选项,TCP keepalives和SSH keepalives。
PuTTY和OpenSSH都支持TCP keepalives。虽然TCP keepalives不如SSH keepalives可配置,但它们对大多数最终用户来说已经足够了。
TCP keepalive是TCP协议的一部分,在传输层发送,而不是SSH本身的一部分。当TCP连接保持空闲时,它最终会超时并断开连接。打开TCP keepalives会偶尔来回发送数据包,以提醒每个人此连接仍然存在。不过,TCP keeplive可以被欺骗或伪造。这不一定是坏事。你需要多久发送一个TCP keepalive取决于你的操作系统的TCP堆栈,但它不应该超过两分钟。
PuTTY仅支持TCP keepalives,但默认情况下不发起它们。然而,它会对收到的任何TCP keepalive有效做出响应。在PuTTY配置屏幕上,转到连接部分。第一个选项是 Seconds between keepalives。默认值为0,禁用发送keepalives。大多数情况下,每90秒发送一次 TCP keepalive就足以保持连接打开。即使PuTTY不发送 keepalives,SSH服务器通常也会发送,PuTTY会对它们做出响应。这通常足以保持连接打开。
默认情况下,OpenSSH服务器发送TCP保持有效。如果要禁用它们,请在sshd_config中将关键字TCPKeepAlive设置为no。
虽然TCP keepalives可能满足大多数人的需求,但OpenSSH的keepalives要灵活得多。在加密通道内发送得keepalive消息告诉中间网络设备此TCP会话仍在使用中。接收到keepalive消息会告诉主机远端仍然连接,并且SSH会话仍然有效。SSH keepalive也更有可能继续保持会话打开,即使是在漫长得路由器重启过程中。
OpenSSH得客户端和服务器都支持keepalives。严格来说,客户端发送 client alive 消息。虽然出于协议原因,这些必须是不同得,但对我们来说,它们都只是keepalives。OpenSSH默认不使用SSH keepalive;你必须在开始会话之前配置它们。
发送keepalives得主机期望收到keepalives作为回报。每个主机都会跟踪它从另一端收到keepalives消息以来已经有多长时间了。如果主机发送了指定数量的keepalives消息而没有收到任何信息,则认为连接丢失并终止SSH会话。
使用SSH keepalives需要决定发送keepalive数据包的频率,以及在主机断开会话之前可以错过多少数据包。服务器使用关键字ClientAliveInterval和ClientAliveContMax。客户端支持关键字ServerAliveInterval和ServerAliveCountMax。
AliveInterval关键字规定了主机发送keepalive之前连接必须空闲多少秒。要使客户端在90秒不活动后传输keepalive,请将ServerAliveInterval设置为90。默认值为0,禁止keepalives。
AliveCountMax关键字告诉主机在终止连接之前必须连续发送多少个keepalive消息。默认值为3。
让我们看看这在实践中是如何工作的。服务器的sshd_config中有以下内容:
xxxxxxxxxx
ClientAliveInterval 90
ClientAliveCountMax 5
在客户端,我们在ssh_config中添加以下内容:
xxxxxxxxxx
ServerAliveInterval 90
ServerAliveCountMax 4
我们登录到SSH服务器,做一些工作,然后让连接空闲。连接空闲90秒后,客户端向服务器发送keepalive。如果服务器以自己的keepalive响应,则客户端和服务器都知道连线是活动的。如果再过90秒没有收到服务器的响应,客户端将发送另一个keepalive。它知道它发送了两个keepalive请求,但没有收到服务器的任何响应。如果连接保持空闲,客户端将继续发送keepalives。在第四次keepalive时,六分钟后,客户端丢弃SSH会话并退出。
服务器已相同的方式发送keepalive,但请注意,它设置为在5个未确认的keepalive请求时断开连接。这个特定的客户端比服务器容忍更少的中断。
请注意,TCP协议也参与其中。发送TCP数据包的主机希望接收方确认每个数据包。如果发送方没有收到此确认,它最终会断开连接,尽管SSH可以做任何事情。时间长度因操作系统而异,但你应该知道,如果你不能维持TCP连接,你就无法维持SSH会话。
如果你想无论如何都保持连接畅通,将AliveCountMax调到高值会有所帮助,特别是当你使用廉价的网络地址转换设备(如许多家用路由器)时。
PuTTY不支持SSH keepalives。
如果禁用SSH服务器上的所有keepalives,服务器将无法注意到客户端何时脱机。这意味着,当工作站崩溃或网络链接失败,强行断开客户端连接时,服务器不会知道。它将继续为这些客户端运行SSH进程。如果您的服务器长时间运行,您可能会累积数百甚至数千个已失效的sshd进程。清理它们有点痛苦。我建议至少使用TCP keepalives,最好也使用SSH keepalives。
现在让我们来看看通过密钥分发简化你的生活。