为什么非活动的 SSH 会话会以“写入失败:管道损坏”终止?

为什么非活动的 SSH 会话会以“写入失败:管道损坏”终止?

我知道这是一个常见问题,但有一个已知的解决方案。快速的网络搜索会找到许多结果,这些结果会将您引向ServerAliveInterval(或不太常见的服务器端ClientAliveInterval)配置选项。将其中一个设置为某个任意值(例如 15、60 或 120)将解决管道断裂问题。

我的问题是为什么?为什么会发生这种情况?谁关闭了套接字?

TCPKeepAlive鉴于该选项默认启用,这会导致发送 TCP keepalive 消息以检测客户端是否离线,因此我对操作系统是否会因不活动而终止连接表示怀疑。因此操作系统无论如何都不会将连接视为不活动。

那么,是应用程序sshd本身超时了吗?如果是这样,为什么超时没有记录或配置?如果需要应用程序级保持活动来保持 SSH 连接打开,那么为什么默认情况下不启用它们?

每当论坛上出现此问题时,这些问题总是被忽视。有人能解释一下吗?

答案1

SSH 本身是一种相当古老的协议,最初并不是为我们今天生活的移动世界而设计的。如果服务器和客户端之间的连接中断,则无法很好地恢复,因此如果您的连接不稳定,管道中断也不足为奇。这也部分是由于 SSH 完全依赖于 TCP,而 TCP 在这方面存在许多限制。

无论如何,如果您需要更强大的连接功能,我推荐 mosh。它非常容易配置,而且断开连接也不会有问题。事实上,您甚至可以切换 IP 地址,它就会立即回到原来的位置,不会出现任何问题。Mosh 使用 UDP,因此可以实现这种行为。

至于它的工作原理,它使用 SSH 建立与服务器的连接,并在服务器上运行mosh-server。然后程序侦听 UDP 端口(默认情况下约为 60000),以便客户端进行连接mosh-client。这意味着您唯一需要做的配置是简单的端口转发。

我希望这有帮助。

答案2

谁关闭了插座?

没有人关闭“套接字”,即客户端和服务器都没有关闭。连接问题通常是由通信方之间的状态数据包过滤器引起的。这种数据包过滤器用于防火墙,也用于简单的 SoHo 路由器,在这些路由器中,它们需要处理NAT这是为同一外部 IP 地址后面的多个内部系统提供互联网访问的典型方式。

此类状态数据包过滤器会为每个新连接创建一个状态,并在连接关闭时将其拆除。这意味着 SYN/FIN 数据包与 TCP 连接(如 ssh)一起出现。这些状态会占用内存,因此数据包过滤器只能同时支持有限数量的状态。因此,它会在一段时间不活动后(即此连接没有数据包)删除这些状态。

如果 TCP 连接中没有活动,则不会发送任何数据包。SSH 也是如此。一段时间不活动后,数据包过滤器中的状态将被删除。如果连接的任何一方在不活动后发送更多数据包,则数据包过滤器中将没有状态,并将发出 RST 数据包。这会导致“管道断裂”。

SSH 中的 TCPKeepAlive 选项启用 TCP keepalive 选项,这会导致 TCP 层在非活动期间定期发送空数据包(即没有数据有效负载的 TCP 数据包)。这样,数据包过滤器就会保持打开状态。

相关内容