在日常工作中,我们经常需要同时打开多个 SSH 连接到同一台服务器。每次连接都需要经历 TCP 握手、TLS 协商(如果是跳板机)、密钥交换等过程,既浪费时间又消耗资源。SSH 提供的 ControlMaster 特性可以让我们复用已建立的连接,大幅提升多会话场景下的效率。
什么是 ControlMaster?#
ControlMaster 是 SSH 的连接复用功能。它允许在第一个 SSH 会话建立后,创建一个控制 socket(套接字文件)。后续的 SSH 连接可以通过这个 socket 复用已有的网络连接,无需重新建立 TCP 连接和身份验证。
核心优势:
- 减少连接建立时间(从数秒缩短到毫秒级)
- 降低跳板机/堡垒机负载
- 支持多会话共享同一个加密通道
工作原理#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
首次连接(无 ControlMaster):
客户端 ----TCP 握手----> 服务器
客户端 ----密钥交换----> 服务器
客户端 ----认证-------> 服务器
客户端 <---会话建立----
后续连接(无 ControlMaster):
客户端 ----TCP 握手----> 服务器(重复一遍)
...
首次连接(启用 ControlMaster):
客户端 ----TCP 握手----> 服务器
客户端 ----密钥交换----> 服务器
客户端 ----认证-------> 服务器
客户端 <---会话建立----
同时创建: /tmp/ssh-control/%r@%h:%p
后续连接(复用 ControlMaster):
客户端 ----控制 socket通信----> 已有连接复用
客户端 <---瞬间建立----
|
配置方法#
方式一:全局配置文件#
编辑 ~/.ssh/config:
1
2
3
4
5
6
7
8
9
10
|
# 启用 ControlMaster
Host *
# 自动复用连接(找不到 socket 时自动降级为普通连接)
ControlMaster auto
# 控制 socket 路径模板
ControlPath ~/.ssh/sockets/%r@%h-%p
# socket 目录权限(必须为 0700)
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlMaster auto
ControlPersist 600
|
创建 socket 目录:
1
2
|
mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/sockets
|
方式二:针对特定主机配置#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 为跳板机启用连接复用
Host bastion
HostName bastion.example.com
User admin
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 4h
# 目标服务器(通过跳板机访问)
Host internal-server
HostName 192.168.1.100
User webadmin
ProxyJump bastion
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
|
方式三:命令行参数#
1
2
3
4
5
|
# 首次连接,创建 master
ssh -o ControlMaster=yes -o ControlPath=/tmp/ssh-%r@%h:%p user@server
# 后续连接,自动复用
ssh -o ControlMaster=auto -o ControlPath=/tmp/ssh-%r@%h:%p user@server
|
关键参数详解#
| 参数 |
说明 |
| ControlMaster |
yes=强制启用, no=禁用, auto=自动(找不到 socket 则新建), ask=询问 |
| ControlPath |
socket 文件路径模板,支持变量:%r(远程用户名)、%h(主机名)、%p(端口)、%l(本地主机名) |
| ControlPersist |
master 连接保持时间,单位秒;4h=4小时;yes=永久(慎用) |
ControlPath 变量:
%r - 远程用户名
%h - 目标主机名(IP 或域名)
%p - SSH 端口(默认 22)
%l - 本地主机名
%C - 连接参数的哈希值(更复杂但更安全)
实际验证#
查看当前活动的 socket#
1
2
|
$ ls -la ~/.ssh/sockets/
srwx------ 1 admin admin 0 Jul 7 00:15 admin@bastion-22
|
验证连接复用#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 第一个终端:建立连接
$ ssh -o ControlMaster=yes -o ControlPath=/tmp/test-%r@%h:%p user@server
# 保持连接...
# 第二个终端:查看 socket 已创建
$ ls -la /tmp/test-*
srwx------ 1 root root 0 Jul 7 00:15 root@server:22
# 第二个终端:连接时间大幅缩短
$ time ssh -o ControlMaster=auto -o ControlPath=/tmp/test-%r@%h:%p user@server echo "done"
done
real 0m0.021s # 复用连接,毫秒级
vs
real 0m2.345s # 全新连接
|
手动关闭 master 连接#
1
2
3
4
5
6
|
# 方法1:等待 ControlPersist 超时
# 方法2:直接删除 socket 文件
rm ~/.ssh/sockets/admin@bastion-22
# 方法3:使用 ssh -O exit 退出 master
ssh -o ControlPath=~/.ssh/sockets/%r@%h-%p -O exit server
|
安全注意事项#
1. ControlPath 权限#
socket 文件权限必须严格控制:
1
2
3
4
5
|
# 确保目录权限为 700
chmod 700 ~/.ssh/sockets
# 确保 socket 只有所有者可读写
ControlPath ~/.ssh/sockets/%r@%h-%p
|
2. ControlPersist 的风险#
1
2
3
4
5
6
7
|
# 风险:后台保持连接可能带来安全风险
ControlMaster yes
ControlPersist yes # 永久保持,慎用
# 推荐:设置合理超时
ControlMaster auto
ControlPersist 600 # 10分钟后自动关闭
|
3. 多人共享服务器的注意事项#
在多人共用的服务器上,建议:
- 使用
%C(哈希值)替代简单变量,防止路径猜测
- 或使用
ControlMaster=ask 确认每次复用
1
2
3
|
Host *
ControlMaster ask
ControlPath ~/.ssh/sockets/%C
|
4. Agent 转发#
使用 ControlMaster 时,ssh-agent 转发行为有变化:
- 所有复用同一 socket 的会话共享同一个 agent
- 无法为每个会话指定不同的 agent
常见问题#
Q: ControlMaster 不生效?#
检查:
- socket 目录是否存在且权限正确
- ControlMaster 是否设置为 auto/yes
- ControlPath 是否正确
1
2
|
# 调试模式查看详情
ssh -vvv -o ControlMaster=auto -o ControlPath=~/.ssh/sockets/%r@%h-%p user@server
|
Q: socket 文件删除后报错?#
1
2
3
|
# 自动降级为普通连接(ControlMaster=auto 时)
# 或手动重建:
ssh -o ControlMaster=yes -o ControlPath=~/.ssh/sockets/%r@%h-%p user@server
|
Q: ControlMaster 和 ProxyJump 同时使用?#
完全兼容:
1
2
3
4
5
6
|
Host target
HostName 10.0.0.5
User app
ProxyJump bastion
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
|
性能对比#
| 场景 |
普通连接 |
ControlMaster |
| 首次连接 |
~2s |
~2s |
| 第二次连接 |
~2s |
<0.1s |
| 10次连接 |
~20s |
~2s |
| 跳板机场景 |
每次验证 |
首次验证 |
SSH ControlMaster 是提升 SSH 使用效率的利器,特别适合:
- 频繁连接同一台服务器
- 通过跳板机访问内网机器
- 日常开发运维多会话场景
配置简单,效果显著。建议在 ~/.ssh/config 中全局启用,并使用 ControlMaster=auto 实现无感知复用。
参考来源: