SFTP空闲断连根本原因是中间网络设备静默丢弃TCP空闲连接,需通过客户端TCP keepalive或ServerAliveInterval、服务端ClientAliveInterval协同保活。

为什么 SFTP 连接总在空闲几秒后就断开
根本原因不是 SFTP 协议本身,而是底层 TCP 连接被中间网络设备(如 NAT 网关、防火墙)静默丢弃。当客户端和服务器之间长时间没有数据包流动,这些设备会清理“空闲连接”,而 OpenSSH 默认不主动探测连接是否还活着。
关键区别:TCP keepalive 是内核级机制,作用于 socket 层;ClientAliveInterval 是 OpenSSH 服务端应用层心跳,只对 SSH 登录会话生效(包括 SFTP 子系统),但不覆盖所有连接场景。
-
TCP keepalive需在客户端和服务端操作系统层面开启,影响所有 TCP 连接(含非 SSH) -
ClientAliveInterval必须配置在/etc/ssh/sshd_config中,且仅对由sshd派生的会话起作用 - 如果用
sftp -o ConnectTimeout=5 user@host这类命令直连,ClientAliveInterval不生效——它不控制连接建立阶段,只管建立后的保活
Linux 客户端怎么设 TCP keepalive 参数
很多脚本或自动化工具(比如用 paramiko 或 libssh2 封装的 SFTP 客户端)默认不启用 TCP keepalive,得手动打开并调参。内核默认值太保守:tcp_keepalive_time 是 7200 秒(2 小时),远超大多数企业 NAT 超时阈值(通常 30–300 秒)。
临时生效(当前会话):
echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
永久生效需写入 /etc/sysctl.conf:
net.ipv4.tcp_keepalive_time = 60 net.ipv4.tcp_keepalive_intvl = 10 net.ipv4.tcp_keepalive_probes = 3
- 60 秒后开始探测,每 10 秒发一次 ACK 探测包,连续 3 次无响应才断开连接
- 不要设
tcp_keepalive_time小于 30:某些低端家用路由器会误判为扫描行为而限速 - Java 的
JSch和 Python 的paramiko可通过set_keepalive(30)单独设置 socket 级 keepalive,优先于系统全局值
sshd 怎么配 ClientAliveInterval 才真正管用
ClientAliveInterval 只在用户已成功登录、进入交互或子系统(如 SFTP)后才启动计时。它发的是 SSH 层的 SSH_MSG_GLOBAL_REQUEST,不是 TCP 包,所以能穿透只过滤 TCP 的设备,但会被深度检测 DPI 防火墙拦截。
必须同时配三项(缺一不可):
-
ClientAliveInterval 30:每 30 秒向客户端发一次心跳请求 -
ClientAliveCountMax 3:连续 3 次没收到响应才关闭连接(即最多容忍 90 秒无响应) -
TCPKeepAlive no:关掉系统级 TCP keepalive,避免和 SSH 层心跳冲突导致连接异常重置
配完记得 sudo systemctl reload sshd,别用 restart——否则正在传大文件的 SFTP 会话可能中断。
注意:ClientAliveInterval 对 sftp -b batchfile user@host 这种批处理模式无效,因为 OpenSSH 认为这是“非交互式会话”,默认跳过心跳逻辑。此时只能靠客户端侧 TCP keepalive 或改用 -o ServerAliveInterval=30(OpenSSH 客户端参数)。
OpenSSH 客户端侧的 ServerAliveInterval 更靠谱
如果你无法修改服务端配置(比如连的是第三方 SFTP 服务),ServerAliveInterval 是最直接有效的解法。它是 OpenSSH 客户端主动发起的保活机制,兼容所有服务端(哪怕对方禁用了 ClientAlive)。
用法分三种场景:
- 命令行临时加:
sftp -o ServerAliveInterval=25 -o ServerAliveCountMax=2 user@host - 写进
~/.ssh/config:Host example.com HostName example.com User sftpuser ServerAliveInterval 25 ServerAliveCountMax 2 - 脚本中用环境变量(适用于封装成工具链):
export SSH_CLIENT_OPTIONS="-o ServerAliveInterval=25",再调用sftp
数值建议:设 ServerAliveInterval 比你预估的网络设备超时时间小 5–10 秒。例如知道出口防火墙清空连接是 60 秒,那就设 50;设成 60 反而容易卡在临界点上断连。
真实坑点:某些老旧版本 OpenSSH(ServerAliveInterval,表现为传输中突然卡住不动。升级到 8.0+ 或换用 lftp sftp:// 可绕过。











