直接在客户端配置发送心跳包,能解决大多数因网络空闲导致的连接中断问题。
先说结论:通过修改 SSH 客户端配置或启动参数,让客户端定期向服务器发送空数据包,可以防止中间网络设备因超时而切断连接。
- 适合需要长时间保持空闲的远程会话场景
- 先准备客户端配置文件或确认命令行参数权限
- 验收需在网络空闲状态下观察连接是否保持
命令速用版
如果只是临时使用,可以在命令中直接添加参数:
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@host
如果希望永久生效,编辑本地配置文件 ~/.ssh/config:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3为什么会这样
SSH 连接断开通常不是因为服务器主动关闭,而是中间的网络设备(如 NAT 网关、防火墙)认为连接已空闲,从而清除了映射表项。SSH 协议本身支持心跳机制,客户端通过 ServerAliveInterval 设置发送心跳的时间间隔,服务器收到后无需回复具体内容,但这一来一回的数据包能刷新网络设备的状态计时器。
另外,服务器端也可能配置了 ClientAliveInterval,如果服务器太久没收到客户端数据,也可能主动断开。客户端发送心跳能同时缓解这两种情况。
分步处理
1. 确认配置文件位置
Linux 和 macOS 用户通常使用 ~/.ssh/config,Windows 用户如果使用 OpenSSH 客户端,路径类似 C:\Users\用户名\.ssh\config。如果文件不存在,可以新建一个。
2. 写入配置项
使用文本编辑器打开文件,添加以下内容。注意缩进不是必须的,但保持清晰更好:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3这里 Host * 表示对所有连接生效。如果只想针对特定服务器,可以把 * 换成主机名或 IP。
3. 设置权限(重要)
SSH 客户端对配置文件权限有严格要求,权限过开放会导致配置被忽略。在 Linux/macOS 终端执行:
chmod 600 ~/.ssh/config
怎么验证是否生效
1. 查看 verbose 日志
连接时加上 -v 参数,观察输出中是否有发送 keepalive 的记录。虽然默认日志不一定显示每次心跳,但可以确认配置已加载:
ssh -v user@host
在输出开头寻找 Reading configuration data... 以及后续的连接维持信息。
2. 实际空闲测试
连接成功后,不要执行任何命令,离开电脑等待超过 2 分钟。回来后按回车,如果仍然能立即出现命令提示符,说明连接未断开。如果配置未生效,通常会看到 Connection reset by peer 或类似错误。
常见坑
1. 混淆客户端与服务端配置
ServerAliveInterval 是客户端配置,写在本地 ssh_config 中;ClientAliveInterval 是服务端配置,写在服务器的 sshd_config 中。普通用户通常只能修改客户端配置,不要试图去改云服务商的控制台安全组来替代心跳。
2. 间隔设置过短
公开资料中没有看到可靠的量化数据表明具体多少秒最优,但设置过短(如 5 秒)会增加不必要的流量和服务器负载,设置过长(如 300 秒)可能无法防止某些激进的 NAT 超时。60 秒是社区中较常见的经验值。
3. 忽略 ServerAliveCountMax
如果网络真的断了,客户端不会无限期尝试发送心跳。ServerAliveCountMax 定义了允许丢失多少个心跳包后断开连接。默认值通常是 3,如果网络质量较差,可以适当调大,但这只是延缓报错,不能修复网络故障。
参考来源
- OpenSSH Manual, ssh_config(5) - OpenSSH SSH client configuration files, https://man.openbsd.org/ssh_config.5
- Linux Man Pages, ssh_config(5) - SSH client configuration files, https://linux.die.net/man/5/ssh_config