SSH多路复用控制命令详解

本文详细介绍了SSH多路复用技术及其控制命令的使用方法,包括如何配置主连接、管理连接状态、端口转发以及性能测试等实用技巧,帮助提升SSH连接效率。

如何通过控制命令管理SSH多路复用

作者:Vivek Gite
最后更新:2025年5月23日

多路复用通过重用与远程主机的现有TCP连接来提升SSH连接速度。当您频繁使用SSH协议连接到同一服务器进行远程登录、服务器管理、使用IT自动化工具或运行每小时备份时,这非常有用。然而,在使用多路复用时,有时您的SSH命令(客户端)可能无响应或会话挂起。通常,这种情况发生在您的公共IP更改(使用DNS名称时IPv4到IPv6更改)、VPN问题或防火墙切断连接时。因此,了解SSH客户端控制命令可以在出现这些问题时节省时间并提高工作效率。

教程详情

  • 难度级别:中级
  • 需要root权限:否
  • 要求:Linux或Unix终端
  • 类别:终端/ssh
  • 操作系统兼容性:AIX • AlmaLinux • Alpine • Amazon Linux • Arch • CentOS • Debian • Fedora • FreeBSD • HP-UX • Linux • macOS • Mint • Mint • NetBSD • OpenBSD • openSUSE • Pop!_OS • RHEL • Rocky • Slackware • Stream • SUSE • Ubuntu • Unix • WSL
  • 预计阅读时间:5分钟

SSH多路复用工作原理

假设您想要连接到AWS EC2服务器,您在CLI中键入以下命令:

1
$ ssh ec2-user@ec2-ipv4-or-ipv6-address-here

对于SSH多路复用,您需要首先启动并设置一个称为套接字的控制主连接文件。例如,我可以为SSH用户vivek和远程主机“192.168.2.20”设置一个名为“/home/vivek/.ssh/controlmasters/vivek@192.168.2.20:22”的套接字文件,TCP端口为“22”。现在,所有后续的SSH命令会话都会重用这个主连接文件:/home/vivek/.ssh/controlmasters/vivek@192.168.2.20:22,而不是创建新的TCP连接,从而加快连接速度。

那么,如何设置这样的SSH多路复用?

只需尝试以下命令:

1
$ ssh -M -S {/path/to/socket_file} {user}@{server}

首先,使用mkdir命令创建一个新目录:

1
$ mkdir -v ~/.ssh/controlmasters/

现在键入:

1
$ ssh -M -S ~/.ssh/controlmasters/freebsd-server-socket vivek@192.168.2.20

您可以为ssh连接指定TCP端口,例如TCP/2222:

1
$ ssh -P 2222 -M -S ~/.ssh/controlmasters/freebsd-server-socket vivek@192.168.2.20

如何在Linux macOS或Unix客户端桌面上启用SSH多路复用

其中:

  • -M:为SSH启用多路复用主模式。
  • -S ~/.ssh/controlmasters/freebsd-server-socket:指定用于连接共享的控制套接字文件路径。无需创建此文件,它将为您创建。
  • vivek@192.168.2.20:指定ssh用户为“vivek”,服务器IP或DNS名称为“192.168.2.20”。
  • -P 2222:使用TCP/2222进行ssh连接,而不是默认的TCP/22。

就是这样。下次您只需键入并跳过-M和-S选项:

1
2
$ ssh {user}@{host}
$ ssh vivek@192.168.2.20

使用SSH配置文件创建多路复用

编辑~/.ssh/config文件并为名为db1的主机附加以下配置:

1
2
3
4
5
6
7
Host db1
  ControlPath ~/.ssh/controlmasters/%r@%h:%p
  ControlMaster auto
  ControlPersist yes
  User ec2-user
  Host 1.2.3.4
  Port 2222

现在只需连接:

1
$ ssh db1

但是,推荐的方式如下,您首先配置各个主机,然后为所有主机应用通用设置,例如多路复用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Host aws-db1
	Hostname 15.xxx.xxx.xxx
	#ProxyCommand ~/bin/connect.vpn.py 
	User debian
	IdentityFile ~/.ssh/id_ed25519

Host aws-web-server
	Hostname 23.xxx.yyy.zzz
	User admin
	IdentityFile ~/.ssh/id_ed25519

Host post-bios-unlock-freebsd-raid-server
	Hostname 192.168.2.19
	Port 2222
	User root
	RequestTTY yes
	RemoteCommand cryptroot-unlock
	IdentityFile ~/.ssh/intel_nuc_freebsd
	HostKeyAlgorithms ssh-rsa

# 为所有主机/服务器启用SSH多路复用
Host *
	IdentitiesOnly yes
	ControlPath ~/.ssh/controlmasters/%r@%h:%p
	ControlMaster auto
	ControlPersist yes

使用控制命令控制SSH多路复用

现在您知道如何使用主连接设置多路复用了。是时候借助大写-O选项使用ssh命令来管理它了。语法是:

1
2
$ ssh -O {ctrl-command} {IP}
$ ssh -O {ctrl-command} {user}@{IP}

SSH多路复用控制命令列表

表1:一旦建立了主连接,您可以使用带有-O选项的ssh来管理它

命令 描述
check 检查主进程是否正在运行或活动。
ssh -O check {server}
forward 请求转发而不执行命令。
ssh -O forward -L port:host:port {server}
cancel 取消转发。
ssh -O cancel {server}
exit 请求主连接退出,即当ssh会话因任何原因挂起时关闭主连接。
在大多数情况下,您需要使用stop选项。
ssh -O exit {server}
stop 请求主连接停止接受进一步的多路复用请求。
ssh -O stop {server}

让我们看一些例子。

检查主连接是否活动

键入:

1
2
$ ssh -O check {host}
$ ssh -O check 192.168.2.20

您可以使用小写o选项指定控制(套接字)文件路径,如下所示:

1
2
$ ssh -o ControlPath={/path/to/socket} -O check {host}
$ ssh -o ControlPath=~/.ssh/controlmasters/freebsd-server-socket -O check 192.168.2.20

输出:

1
Master running (pid=2030199)

您可以使用ps命令验证PID,如下所示:

1
2
3
$ ps aux | grep {PID}
$ ps aux | grep 2030199
$ ps -u -p 2030199

输出:

1
2
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
vivek    2030199  0.0  0.0  15988  2804 ?        Ss   12:02   0:00 ssh: /home/vivek/.ssh/controlmasters/vivek@192.168.2.20:22 [mux]

使用stop或exit选项关闭主连接

正如我之前所说,由于各种原因,您的主SSH连接可能无法工作。以下是杀死它的方法:

1
2
3
4
$ ssh -O exit {host}
$ ssh -o ControlPath={/path/to/socket} -O exit {host}
$ ssh -O exit 192.168.2.20
$ ssh -o ControlPath=~/.ssh/controlmasters/freebsd-server-socket -O exit 192.168.2.20

输出:

1
Exit request sent.

验证:

1
$ ssh -O check 192.168.2.20

输出:

1
Control socket connect(/home/vivek/.ssh/controlmasters/vivek@192.168.2.20:22): No such file or directory

ssh -O stop 与 ssh -O exit 命令有什么区别?

ssh -O exit 命令完全终止主SSH连接。与该主连接关联的所有活动会话将突然关闭,如果您正在远程主机上编辑文件,可能会丢失数据。因此,您可以使用 ssh -O stop 选项,这对现有的SSH连接更为温和。此选项阻止使用现有主连接创建新会话。但是,它允许现有会话继续运行,直到它们完成或由用户独立关闭。语法很简单:

1
2
$ ssh -O stop {host}
$ ssh -o ControlPath={/path/to/socket} -O stop {host}

多路复用时的SSH端口转发控制

以下示例假设您的远程SSH服务器上已安装所需服务并通常运行TCP端口8443或端口5900的VNC服务器。

您可以通过多路复用连接转发本地端口。语法是:

1
2
$ ssh -O forward -L {port}:{host}:{port} {user}@{remote_ip}
$ ssh -o ControlPath={/path/to/socket}  -O forward -L {port}:{host}:{port} {user}@{remote_ip}

要通过多路复用退出转发会话,键入:

1
2
$ ssh -O cancel {user}@{remote_ip}
$ ssh -o ControlPath={/path/to/socket} -O cancel {user}@{remote_ip}

例如,可以通过以下方式从您的桌面完成通过SSH多路复用的VNC端口转发:

1
$ ssh -O forward -L 5900:127.0.0.1:5900 vivek@192.168.2.20

然后我在桌面上打开VNC客户端并指向127.0.0.1和端口5900。要通过多路复用退出SSH转发,运行:

1
$ ssh -O cancel vivek@192.168.2.20

现在考虑以下示例:

1
$ ssh -O forward -L 8443:10.147.164.1:8443 vivek@192.168.2.20

其中:

  • ssh -O forward:通过多路复用的SSH端口转发命令。
  • -L 8443:10.147.164.1:8443:这是使用ssh的端口转发命令:
    • 8443:这是您本地机器上将要连接的端口号。
    • 10.147.164.1:这是您通过IPv4地址192.168.2.20访问的网络内的目标IP地址,流量将转发到此处。
    • 8443:这是目标机器10.147.164.1上的目标端口号。
  • vivek@192.168.2.20:这是您的SSH服务器的公共/私有IPv6地址,用户名设置为“vivek”。

要取消通过SSH多路复用的转发,键入:

1
$ ssh -O check vivek@192.168.2.20

如何测量SSH多路复用效果

首先,连接并激活多路复用套接字:

1
$ time ssh {user}@{server} true

输出:

1
2
3
real	0m3.563s
user	0m0.018s
sys	0m0.004s

使用time命令测量多路复用效果:

1
$ time ssh {user}@{server} true

输出:

1
2
3
real	0m0.939s
user	0m0.004s
sys	0m0.003s

禁用多路复用并测试:

1
$ time ssh -o 'ControlMaster=no' -o 'ControlPath=no' {user}@{server} true

输出:

1
2
3
real	0m3.508s
user	0m0.014s
sys	0m0.007s

总结

SSH多路复用是一个非常方便的功能,但其控制命令文档较少。因此,本页提供了如何使用SSH多路复用及其控制命令的各种实用示例。有关更多信息,请参见OpenSSH文档,或使用man命令离线阅读:

1
2
3
4
$ man ssh
$ man ssh_config
$ man sshd_config
$ man sshd
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计