防止 SSH 超时问题的最佳实践

通过实施健壮的 keep-alive 配置,来阻止令人沮丧的 SSH 会话断开。这份基本指南详细介绍了客户端 (`ServerAliveInterval`) 配置和服务器端 (`ClientAliveInterval`) 配置之间的差异,并提供了逐步说明,用于调整您的 `~/.ssh/config` 文件。了解如何使用实用数值来绕过激进的防火墙和 NAT 超时设置,确保即使在不稳定的网络上也能实现稳定、持久的连接。此外,还包括了利用 `tmux` 等多路复用器来实现终极会话弹性的建议。

31 浏览量

预防SSH超时问题的最佳实践

SSH(安全外壳协议)是远程系统管理的支柱,提供加密和安全的连接。然而,没有什么比会话因超时而意外中断更令人沮丧的了。这些问题在网络不稳定、连接经过激进的NAT设备或会话长时间处于空闲状态时尤其普遍。

本指南将探讨系统管理员和开发人员可以实施的基本配置调整——包括客户端和服务器端的调整——以主动维护稳定的SSH会话。通过利用内置的保持活动状态(keep-alive)机制,您可以确保即使在网络不确定或不活动期间,您的关键任务也不会中断。


理解SSH超时的根本原因

当客户端和服务器之间的通信链路因任何一方在特定持续时间内未检测到活动而中断时,就会发生SSH超时。这通常不是SSH软件本身的问题,而是中间网络设备(防火墙、路由器和NAT表)为节省资源而主动清理空闲连接所致。

当防火墙在特定TCP连接上几分钟内未看到流量时,它会假定会话已死并终止连接。下次SSH客户端尝试发送数据时,服务器永远不会收到,从而导致会话冻结并最终出现超时错误。

解决方案是配置SSH以定期发送保持活动信号(小的、非数据的包),确保中间设备将连接识别为活动状态。

1. 客户端解决方案:ServerAliveInterval

防止超时的最常见和最简单的解决方案是配置SSH客户端定期向服务器发送保持活动消息。这由ServerAliveInterval指令控制。

ServerAliveInterval的工作原理

ServerAliveInterval指定在客户端从服务器接收到任何数据后的秒数内向服务器发送一个空包的时间。此值可确保客户端保持连接状态。

通过~/.ssh/config进行配置

推荐使用此方法,因为它允许您全局或为每个主机设置配置,并且这些设置在重启和不同的终端会话中都会持久存在。

创建或修改您的客户端配置文件,通常位于~/.ssh/config

nano ~/.ssh/config

要全局应用设置(应用于所有主机):

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

值解释:

  • ServerAliveInterval 60:如果连接空闲,客户端将每60秒发送一个保持活动包。
  • ServerAliveCountMax 3:如果客户端发送了3个连续的保持活动消息但未收到服务器响应,客户端将终止连接。(总超时时长:60秒 * 3次尝试 = 180秒)。

通过命令行配置

如果您需要临时修复或希望仅对单个会话应用设置,请在连接时使用-o选项:

ssh -o "ServerAliveInterval 60" user@remote_host

提示: 30到60秒的值通常是理想的,因为它足够频繁,可以绕过大多数防火墙规则(通常设置为大约5分钟),但又不会过于频繁以产生过多的网络开销。

2. 服务器端解决方案:强制执行保持活动状态

虽然客户端解决方案(ServerAliveInterval)通常足够,但管理由许多用户访问的服务器的管理员可能希望集中强制执行保持活动设置或为闲置连接设置硬性限制。这在SSH守护进程配置文件/etc/ssh/sshd_config中完成。

使用ClientAliveIntervalClientAliveCountMax

这些指令是服务器端对应于客户端设置的指令。它们指示服务器检查客户端是否仍然连接。

  1. 打开SSH守护进程配置文件:

    bash sudo nano /etc/ssh/sshd_config

  2. 添加或修改以下行:

    ```config

    如果在300秒(5分钟)内未从客户端收到任何数据,服务器将发送一个空包

    ClientAliveInterval 300

    如果ClientAliveInterval触发0次而没有响应,则断开连接。

    将此设置为0意味着服务器在第一次检查失败后立即断开连接。

    ClientAliveCountMax 0
    ```

关于ClientAliveCountMax的说明:

如果您将ClientAliveCountMax设置为较小的值(如0或1),服务器将强制执行严格的空闲超时。例如,ClientAliveInterval 300ClientAliveCountMax 0意味着如果用户完全空闲5分钟,服务器将假定连接已死并强制断开连接。这对安全性很有用,但可能会使用户感到沮丧。如果您的目标是防止防火墙丢弃连接,设置此值通常不如客户端的ServerAliveInterval重要。

  1. 重启SSH服务使更改生效:

    ```bash
    sudo systemctl restart sshd

    或者

    sudo service sshd restart
    ```


3. 高级恢复能力策略

SSH保持活动状态可以处理短暂的不活动时间,但完全的网络中断(例如,更改Wi-Fi网络或短暂丢失信号)仍然会终止TCP连接。为了实现真正的恢复能力,请使用会话管理工具。

利用终端多路复用器(tmuxscreen

终端多路复用器是防止连接中断的终极防御措施。它们在远程服务器上运行一个会话,即使您的客户端连接断开,该会话也会保持活动状态。您可以分离会话,稍后重新连接(从同一客户端或不同客户端),然后重新附加以恢复到离开时的确切位置。

基本的tmux工作流程:

  1. 连接到服务器:
    bash ssh user@remote_host
  2. 在服务器上启动一个新的tmux会话:
    bash tmux new -s my_session
  3. tmux会话内部工作。
  4. 如果连接中断,或者您需要离开,请分离会话(Ctrl+B,然后按D)。
  5. 通过SSH重新连接到服务器。
  6. 重新附加到您现有的会话:
    bash tmux attach -t my_session

区分SSH保持活动状态与TCP保持活动状态

可以使用底层操作系统的TCP保持活动机制,通常通过sshd_config中的TCPKeepAlive yes指令进行配置。然而,通常更推荐使用SSH级别的保持活动状态(ServerAliveInterval),原因如下:

  1. 可移植性: SSH指令可以一致地工作,而与底层OS内核调整无关。
  2. 应用层: SSH保持活动状态在应用层内运行,确保SSH守护进程保持响应。
  3. 防火墙感知: TCP保持活动状态有时会被只检查有效负载活动的防火墙或NAT设备静默阻止,而SSH保持活动状态专门设计用于成功穿透这些层。

如果您选择使用TCPKeepAlive yes,请记住,实际的间隔时间由操作系统控制(例如,Linux的net.ipv4.tcp_keepalive_time),而不是由SSH配置控制。

最佳实践总结

问题 配置指令 位置 推荐值 目的
客户端超时 ServerAliveInterval ~/.ssh/config (客户端) 30 - 60 秒 从客户端向服务器发送空包以防止防火墙丢弃连接。
客户端断开阈值 ServerAliveCountMax ~/.ssh/config (客户端) 3 - 5 客户端断开连接前未收到响应的次数。
服务器空闲强制 ClientAliveInterval /etc/ssh/sshd_config (服务器) 300 秒 (5 分钟) 从服务器向客户端发送检查以监控活动。
连接恢复能力 不适用 服务器会话 tmuxscreen 允许会话在网络故障时持续存在。

通过在客户端机器上实施ServerAliveInterval指令,您将解决绝大多数由网络不活动引起的SSH超时问题。对于任务关键型任务,将此配置与会话多路复用器分层,可提供几乎完全免疫连接中断的能力。