Multiplexing SSH Connections with Control Master: Speed Up Deployments and Automation
Multiplexing SSH Connections with Control Master: Speed Up Deployments and Automation
使用 Control Master 进行 SSH 连接多路复用:加速部署与自动化
Every SSH command you run opens a fresh TCP connection and completes a full cryptographic handshake. Here’s how to do it once and reuse it hundreds of times. If you run ansible against 50 servers, each task opens a new SSH connection. If you have 10 tasks per server, that’s 500 handshakes. If you run rsync frequently to a remote dev server, you’re paying the connection cost every time. If your deployment script calls ssh in a loop, you’re paying it once per iteration. 你运行的每一条 SSH 命令都会开启一个新的 TCP 连接并完成完整的加密握手。以下是如何只做一次握手并将其复用数百次的方法。如果你对 50 台服务器运行 Ansible,每个任务都会开启一个新的 SSH 连接。如果每台服务器有 10 个任务,那就是 500 次握手。如果你频繁地向远程开发服务器运行 rsync,你每次都在支付连接成本。如果你的部署脚本在循环中调用 ssh,那么每次迭代你都要支付一次成本。
SSH’s connection handshake isn’t free. On a fast local network it’s imperceptible. Over the internet, through a bastion, or under load, it adds up — sometimes adding minutes to operations that should take seconds. ControlMaster is OpenSSH’s built-in connection multiplexing feature. One SSH connection per host, shared by every subsequent operation. The first ssh host pays the handshake cost; every connection after that reuses the established socket and connects in milliseconds. This article explains how it works, how to configure it, how to use it to accelerate deployments and automation, and the edge cases you need to know. SSH 的连接握手并非没有代价。在快速的局域网中,这种延迟几乎无法察觉。但在互联网上、通过堡垒机访问或在高负载情况下,这些延迟会累积起来——有时会让原本只需几秒钟的操作增加数分钟的等待时间。ControlMaster 是 OpenSSH 内置的连接多路复用功能。它为每个主机建立一个 SSH 连接,并供后续所有操作共享。第一个 ssh 连接承担握手成本;此后的每个连接都会复用已建立的套接字,并在几毫秒内完成连接。本文将解释其工作原理、配置方法、如何利用它加速部署与自动化,以及你需要了解的边缘情况。
Understanding the Problem: What Happens on Every SSH Connection
理解问题:每次 SSH 连接时发生了什么
Before seeing the solution, it’s worth understanding what you’re eliminating. Every fresh SSH connection performs: 在查看解决方案之前,有必要了解你正在消除的是什么。每一个新的 SSH 连接都会执行:
-
TCP handshake — three-way SYN/SYN-ACK/ACK (~1 RTT)
-
SSH version exchange — client and server announce protocol versions
-
Key exchange — Diffie-Hellman or Curve25519 negotiation to establish a shared secret (~1–2 RTTs)
-
Host key verification — server proves its identity
-
User authentication — key signing challenge/response (~1 RTT)
-
Channel open — session channel established
-
TCP 握手 — 三次握手 SYN/SYN-ACK/ACK(约 1 个往返时间 RTT)
-
SSH 版本交换 — 客户端和服务器通告协议版本
-
密钥交换 — Diffie-Hellman 或 Curve25519 协商以建立共享密钥(约 1–2 个 RTT)
-
主机密钥验证 — 服务器证明其身份
-
用户认证 — 密钥签名质询/响应(约 1 个 RTT)
-
通道开启 — 建立会话通道
On a low-latency local network, this takes ~50ms. Over a VPN or through a bastion with 100ms RTT, it takes ~300–500ms. In automation that makes hundreds of connections, this accumulates into real time. With ControlMaster, connections 2 through N skip steps 1–5 entirely. They open a new channel on the existing multiplexed connection. Connection time drops to single-digit milliseconds regardless of network latency. 在低延迟的局域网中,这大约需要 50 毫秒。在 VPN 或通过 100ms RTT 的堡垒机连接时,则需要 300–500 毫秒。在进行数百次连接的自动化任务中,这些时间会累积成显著的延迟。使用 ControlMaster 后,第 2 到第 N 个连接将完全跳过第 1 到第 5 步。它们会在现有的多路复用连接上开启一个新通道。无论网络延迟如何,连接时间都会降至个位数毫秒。
How ControlMaster Works
ControlMaster 的工作原理
ControlMaster designates one SSH connection as the “master.” The master connection creates a Unix socket on your local machine — the “control socket” — and listens for subsequent connection requests. ControlMaster 将一个 SSH 连接指定为“主连接”(master)。主连接会在你的本地机器上创建一个 Unix 套接字(即“控制套接字”),并监听后续的连接请求。
-
First ssh connection: Your machine ──[full handshake]──► Remote server Creates:
~/.ssh/sockets/ubuntu@server:22(control socket) -
Second ssh connection to same host: Your machine ──[connect to control socket]──► (reuse existing connection) Skips handshake entirely. Opens new channel on existing connection.
-
首次 ssh 连接: 你的机器 ──[完整握手]──► 远程服务器 创建:
~/.ssh/sockets/ubuntu@server:22(控制套接字) -
第二次连接同一主机: 你的机器 ──[连接到控制套接字]──►(复用现有连接) 完全跳过握手。在现有连接上开启新通道。
The master connection stays alive (for a configurable duration) even after all sessions using it have closed. New sessions can attach instantly. 即使所有使用它的会话都已关闭,主连接仍会保持存活(持续时间可配置)。新的会话可以立即附加到该连接上。
Basic Configuration
基本配置
~/.ssh/config Setup:
~/.ssh/config 设置:
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h:%p
ControlPersist 4h
Create the sockets directory: 创建套接字目录:
mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/sockets
Directive breakdown: 指令解析:
-
ControlMaster:
yes— always act as master; refuse to connect if a master already existsauto— use existing master if available; become master if not. This is what you want.no— never use multiplexingask— prompt whether to use the existing master
-
ControlPath: The filesystem path for the control socket. The tokens expand as:
%r— remote username%h— remote hostname%p— port number- Result for
ssh ubuntu@web-01.example.com:~/.ssh/sockets/ubuntu@web-01.example.com:22
-
ControlPersist: How long the master connection stays alive after all sessions close.
4h= four hours. Also accepts:yes— persist indefinitelyno— close when last session closes- A time value:
10m,1h,4h,1d
-
ControlMaster:
yes— 始终作为主连接;如果已存在主连接则拒绝连接auto— 如果可用则使用现有主连接;否则成为主连接。这是你所需要的。no— 不使用多路复用ask— 询问是否使用现有主连接
-
ControlPath: 控制套接字的文件系统路径。标记展开如下:
%r— 远程用户名%h— 远程主机名(连接命令中指定的主机名)%p— 端口号ssh ubuntu@web-01.example.com的结果为:~/.ssh/sockets/ubuntu@web-01.example.com:22
-
ControlPersist: 所有会话关闭后主连接保持存活的时间。
4h= 四小时。也接受:yes— 永久保持no— 最后一个会话关闭时关闭- 时间值:
10m,1h,4h,1d
Verifying It Works
验证是否生效
# First connection — pays full handshake cost
time ssh web-01 "echo hello"
# real 0m0.312s
# Second connection — uses existing master
time ssh web-01 "echo hello"
# real 0m0.008s
首次连接 — 支付完整握手成本
第二次连接 — 使用现有主连接
差异即为完整的握手成本。在高延迟连接上,这每次操作可节省 1–2 秒。
To confirm the master is running: 确认主连接正在运行:
ssh -O check web-01
# Master running (pid=12345)
ControlMaster Control Commands
ControlMaster 控制命令
ControlMaster sessions respond to control commands sent via ssh -O:
ControlMaster 会话响应通过 ssh -O 发送的控制命令:
# Check if master is running
ssh -O check web-01
# Open a new multiplexed session (equivalent to normal ssh)
ssh -O forward -L 8080:localhost:80 web-01
# Request master to exit when all sessions close
ssh -O stop web-01
# Force-close the master immediately (all sessions dropped)
ssh -O exit web-01
These are essential for automation and scripting — you can explicitly manage the master lifecycle rather than relying on the persist timer. 这些命令对于自动化和脚本编写至关重要——你可以显式地管理主连接的生命周期,而不必依赖持久化计时器。
Accelerating Ansible
加速 Ansible
Ansible uses SSH for every task on every host. With large inventories and many tasks, SSH handshake overhead dominates execution time. Ansible 对每台主机上的每个任务都使用 SSH。在大型清单和大量任务的情况下,SSH 握手开销会占据执行时间的主要部分。
Ansible’s Built-in SSH Pipelining Ansible 内置的 SSH Pipelining
First, enable SSH pipelining in ansible.cfg — this alone significantly reduces connection count by sending multiple operations in one SSH session:
首先,在 ansible.cfg 中启用 SSH Pipelining——仅此一项就能通过在单个 SSH 会话中发送多个操作来显著减少连接数:
[defaults]
pipelining = True
On managed hosts, comment out requiretty in /etc/sudoers (pipelining doesn’t work with it enabled):
在受管主机上,注释掉 /etc/sudoers 中的 requiretty(启用该选项时 Pipelining 无法工作):
# On target servers:
sudo visudo
# Comment out or remove:
# Defaults requiretty
ControlMaster for Ansible Ansible 的 ControlMaster
Ansible supports ControlMaster via ssh_args:
Ansible 通过 ssh_args 支持 ControlMaster:
[defaults]
pipelining = True
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPath=/tmp/ansible-ssh-%r@%h:%p -o ControlPersist=60s
Use a separate ControlPath for Ansible to avoid socket conflicts with your interactive sessions.
为 Ansible 使用单独的 ControlPath,以避免与你的交互式会话发生套接字冲突。
Practical Impact
实际影响
A benchmark: Ansible playbook, 20 servers, 15 tasks each: 基准测试:Ansible playbook,20 台服务器,每台 15 个任务:
| Configuration | Time |
|---|---|
| Default (no pipelining, no multiplexing) | 4m 12s |
| Pipelining enabled | 2m 38s |
| Pipelining + ControlMaster | 1m 04s |
| 配置 | 时间 |
|---|---|
| 默认(无 Pipelining,无多路复用) | 4m 12s |
| 启用 Pipelining | 2m 38s |
| Pipelining + ControlMaster | 1m 04s |
Multiplexing doesn’t just save time — it reduces load on the bastion and target servers, which are no longer handling hundreds of handshakes. 多路复用不仅节省了时间,还减轻了堡垒机和目标服务器的负载,因为它们不再需要处理数百次握手。