sftp 连接慢的 TCP keepalive_interval 与 ServerAliveCountMax 配置

3次阅读

SFTP连接卡住的根本原因是中间网络设备静默丢弃空闲连接,而Openssh默认未启用有效保活机制;必须配置ServerAliveInterval(如45秒)和ServerAliveCountMax(如2)组合实现SSH层主动探测,TCPKeepAlive基本无效且不应禁用。

sftp 连接慢的 TCP keepalive_interval 与 ServerAliveCountMax 配置

为什么 SFTP 连接卡在 “Connecting…” 或传输中途挂死

根本原因常是中间网络设备(如 NAT 网关、防火墙)静默丢弃了空闲连接,而 OpenSSH 默认不主动探测连接是否存活。客户端以为连着,服务端早已关闭,结果 sshsftp 命令卡住几秒到几十秒才超时——这不是 DNS、密钥认证或带宽问题,是 TCP 层保活没配对。

必须设的两个客户端参数:TCPKeepAliveServerAliveIntervalServerAliveCountMax

TCPKeepAlive 是底层 TCP 保活开关(默认 yes),但它由内核控制,间隔长(通常 2 小时)、不可控,对 SSH 场景基本无效。真正起作用的是 SSH 层的主动探测机制:

  • ServerAliveInterval:客户端每隔多少秒发一个空包探测服务端是否在线(推荐设为 3060
  • ServerAliveCountMax:连续几次探测失败后断开连接(默认 3,建议保持)
  • 二者必须一起用,单独设 ServerAliveInterval 不生效
  • 别碰 TCPKeepAlive no——关掉它不会加速,反而让连接更难被及时发现失效

怎么配:全局配置 vs 单次命令 vs sftp 子命令

配置位置优先级:命令行 > ~/.ssh/config > 系统 /etc/ssh/ssh_config。实操中推荐写进用户配置,一劳永逸:

Host myserver     HostName 192.168.1.100     User deploy     ServerAliveInterval 45     ServerAliveCountMax 2

如果只临时调试,直接加参数跑:

sftp -o ServerAliveInterval=30 -o ServerAliveCountMax=3 user@host

注意:sftp 命令本身不读取 ~/.ssh/config 的所有选项(老版本有坑),但现代 OpenSSH(≥7.0)已支持。若仍无效,换 ssh 测试确认配置是否加载成功:

ssh -o "ServerAliveInterval 30" -o "ServerAliveCountMax 2" user@host echo ok

容易被忽略的兼容性细节和副作用

某些老旧 SSH 服务端(如 OpenSSH ServerAlive 探测包,导致客户端提前断连;此时需降级为 TCPKeepAlive yes + 调大内核 net.ipv4.tcp_keepalive_time(不推荐,粒度太粗)。

  • ServerAliveInterval 太小(如 5)会增加无谓流量,对高延迟链路(如跨国)可能引发误判
  • ServerAliveCountMax 设为 1 会让一次丢包就断连,实际网络抖动常见,23 更稳妥
  • 使用 sftp 时若启用了 ProxyCommand,保活包走的是代理链路,得确保代理本身也稳定——这点常被当成 SFTP 问题排查半天

真正卡顿的根因往往藏在第三层:不是参数没设,而是设了但没生效(比如配错 Host 别名、路径拼错、权限不对导致 config 被跳过)。先用 ssh -F /dev/NULL -o "ServerAliveInterval=15" -v user@host 看 debug 日志里有没有 Send SSH2_MSG_GLOBAL_REQUEST keepalive@openssh.com 出现。

text=ZqhQzanResources