sftp 频繁超时 的 TCP keepalive 与 ClientAliveInterval 配置

2次阅读

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

sftp 频繁超时 的 TCP keepalive 与 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 参数

很多脚本或自动化工具(比如用 paramikolibssh2 封装的 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 会话可能中断。

注意:ClientAliveIntervalsftp -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:// 可绕过。

text=ZqhQzanResources