5月28日 00:51

什么是 SSH 连接复用?如何配置和使用连接复用提高性能?

SSH 连接复用(Connection Multiplexing)是指复用一条已建立的 SSH 连接来创建新的会话,省去重复的 TCP 握手和密钥交换环节。面试中常考的是三个配置参数:ControlMaster、ControlPath、ControlPersist,以及复用带来的性能收益和潜在风险。

连接复用怎么工作

正常的 SSH 连接每次都要经历 TCP 三次握手、SSH 协议版本协商、Diffie-Hellman 密钥交换、用户认证四个阶段。在延迟较高的网络环境(如跨机房、通过跳板机)中,这个过程可能耗时 1-3 秒。

连接复用的做法是:第一次连接建立后,把这条连接作为"主连接"(master)保持在后台,后续对同一目标的连接直接通过 Unix 域套接字(ControlPath)复用主连接,跳过握手和认证,几乎瞬间完成。

shell
首次连接: 客户端 --TCP握手--> --密钥交换--> --认证--> 建立主连接 复用连接: 客户端 --通过套接字--> 直接复用主连接(毫秒级)

这带来的性能差异在脚本批量执行远程命令时尤为明显——10 次连接从 15 秒降到 1 秒以内是常见的。

三个核心配置参数

ControlMaster

决定是否启用复用以及复用的行为:

  • no:禁用(默认值)
  • auto:如果已有主连接就复用,没有就创建新的——最常用的选项
  • yes:强制创建主连接,如果已存在则失败
  • ask:复用前询问用户确认

ControlPath

指定 Unix 域套接字文件的路径。支持的占位符:

  • %r — 远程用户名
  • %h — 主机名
  • %p — 端口号
  • %C — 连接参数的 SHA1 哈希(推荐,避免路径过长)
bash
# 常见写法 ControlPath ~/.ssh/cm-%r@%h:%p # 使用 %C 避免路径超长(macOS 上常见问题) ControlPath ~/.ssh/cm-%C

套接字文件路径有长度限制(通常 104-108 字节),路径太长会导致复用失败。使用 %C 可以规避这个问题。

ControlPersist

控制主连接在最后一个会话关闭后继续存活的时间:

  • no:最后一个会话断开后立即关闭主连接
  • yes:永久保持,直到手动关闭或网络中断
  • 600 / 10m:保持 10 分钟
  • 4h:保持 4 小时

对于日常开发,10m1h 是比较合理的范围。设成 yes 会导致主连接进程一直驻留,不推荐。

最小可用配置

bash
# ~/.ssh/config Host * ControlMaster auto ControlPath ~/.ssh/cm-%C ControlPersist 10m

三行配置即可生效。建好配置后,第一次 ssh user@server 正常连接,第二次起就能感知到速度差异。

如果只想对特定主机启用:

bash
Host prod-* ControlMaster auto ControlPath ~/.ssh/cm-%C ControlPersist 30m

管理复用连接

bash
# 检查主连接是否存活 ssh -O check user@server # 主动关闭主连接(所有复用会话也会断开) ssh -O exit user@server # 停止接受新的复用请求(已有会话不受影响) ssh -O stop user@server # 查看控制套接字文件 ls -l ~/.ssh/cm-*

网络中断后,残留的套接字文件会导致新连接报错 Control socket connect: Connection refused。直接删除即可:

bash
rm -f ~/.ssh/cm-* # 或只删除特定主机的 find ~/.ssh -name "cm-*" -type s -mtime +1 -delete

哪些场景收益最大

批量远程命令执行——在脚本中循环 ssh user@server "cmd",复用后只有第一次有连接延迟。

Git over SSH——git push / git pull / git fetch 走 SSH 时自动受益,频繁提交代码的开发者体感明显。

跳板机 / ProxyJump——通过跳板机连接目标机器时,到跳板机的连接可以复用。当 ~/.ssh/config 中配置了 ProxyJump 时,ControlMaster 对跳板机连接同样生效:

bash
Host bastion HostName jump.example.com ControlMaster auto ControlPath ~/.ssh/cm-%C ControlPersist 10m Host internal-* ProxyJump bastion # internal-* 的连接也会触发 bastion 的复用

rsync / scp 文件传输——底层走 SSH,同样能复用连接。

需要注意的风险

单点故障:主连接断开时,所有复用它的会话同时失效。在长时运行的会话中(如远程编译、持续部署),这意味着一个网络抖动可能打掉所有窗口。

资源泄漏:ControlPersist 设为 yes 时,主连接的 ssh 进程会一直驻留。长时间运行后可能积累大量僵尸进程和套接字文件。建议设定具体时间。

权限风险:控制套接字文件如果权限不当,同一台机器上的其他用户可能劫持你的 SSH 会话。确保 ~/.ssh/ 目录权限为 700

与某些 SSH 功能冲突-W(netcat 模式)、-J(ProxyJump 的命令行形式)在特定版本下与 ControlMaster 存在兼容性问题,遇到问题时可以先 ssh -O exit 清除主连接再试。

面试追问参考

Q: ControlMaster 设为 auto 和 yes 有什么区别? auto 在没有主连接时自动创建,有则复用;yes 强制要求自己成为主连接,如果已有主连接则连接失败。yes 适合脚本中明确需要"我是第一个连接"的场景。

Q: 连接复用会带来安全风险吗? 会。控制套接字本质上是一个 Unix 域套接字,本地有权限的用户理论上可以通过它建立 SSH 会话。所以必须保证套接字路径的目录权限正确(700),不要放在 /tmp 等公共目录。

Q: 主连接断了怎么办? 所有复用该主连接的会话都会立即断开。需要删除残留的套接字文件后重新建立连接。这也是为什么不建议在生产环境的关键操作中过度依赖复用。

标签:SSH