我的服务器上有很多基于 QEMU 的虚拟机。其中一些虚拟机被禁止使用网络,并且唯一连接它们的方式是通过虚拟串行端口。
由于串行控制台的不良功能(例如与 tmux 和 vim 配合不佳),我想通过串行线使用 ssh。
这是我的尝试:(QEMU 将串行映射到主机中的 unix 套接字)
#In Guest: (serial is /dev/ttyS1)
socat -d -d tcp:127.0.0.1:22 file:/dev/ttyS1,b115200
#In Host: (mapped to /var/run/qemu-server/vm.serial1)
socat -d -d tcp-l:10022 UNIX-CONNECT:/var/run/qemu-server/vm.serial1
然后我尝试运行,但是它提示:ssh -vv [email protected] -p 10022
Bad packet length 1349676916.
ssh_dispatch_run_fatal: Connection to UNKNOWN port 65535: message authentication code incorrect
但是当我使用
# Ctrl+C to terminate
socat STDIO,raw,echo=0,escape=0x3 UNIX-CONNECT:/var/run/qemu-server/vm.serial1
我可以看到
SSH-2.0-OpenSSH_7.6p1
因此隧道已连接,但似乎无法通过串行端口传输裸 TCP(可能缺少帧和包控制)。
因此我尝试在串行线中使用 pppd,然后启动一个接口,通过 PPP 上的 IP 上的 TCP 来使用 ssh...
但是虚拟机很多,用ppp创建那么多接口,管理起来很麻烦,因为没有自动分配IP的功能,而且单独给ssh分配一个IP地址也太浪费了。
那么是否可以在串行上运行裸 TCP 套接字?或者跳过创建的 IP 层pppd
并通过 PPP 打开 TCP 套接字,如下所示:
+----------------------+
| |
| TCP Socket |
| |
+----------------------+
| |
| Data Link Layer(PPP) |
| |
+----------------------+
我只想向想要通过 ssh 连接到 VM 的用户公开 TCP 端口(或 UNIX 套接字)。
我试图寻找解决方案,但所有的答案都是关于如何通过 TCP 传输串行,但我想要的是反向:如何通过串行传输 TCP?
答案1
您试图将一堆与串行控制台无关的协议推到串行控制台上。这不会产生合理的结果,而且您想要的数据已经以纯文本形式提供。
如果您使用 libvirt 来定义和管理虚拟机,这项工作已经为您完成了。virsh console <VM Name>
将把您连接到虚拟机的串行控制台,并且它工作得很好 - 您也可以通过主机上的 SSH 管道传输它,或者通过virsh
ssh+qemu 连接到它(如果您愿意的话)。同样,大多数其他管理和编排系统(如 OpenStack 或 Xenserver)都有类似的方法来连接到类似 pty 的虚拟机串行设备,而无需 unix 套接字。
tmux
无法像minicom
或screen
那样与串行接口配合使用。如果您采用手动方法,将其中任何一个连接到 PTY 或套接字设备都会产生令人满意的结果。
如果您在手动编排平面中拥有许多串行控制台(如纯 QEMU 所倾向的),则使用控制台服务器会比通过其自己的特殊套接字或 PTY 连接到每个 VM 更为明智。conserver
是一个很好的选择,我经常使用它。 您可以设置用于将串行程序连接到每个 VM 的别名,并通过 SSH 通过控制台连接到这些程序;这样就可以console <servername>
从通过 SSH 连接的控制台主机轻松到达您需要的位置。
答案2
这是可以工作的,我已经使用 VMWare 和 Windows 客户机完成了此操作,该客户机运行 IPSec VPN 客户端,禁用了其他网络,包括主机 VM。
我发现的窍门是 SSH 客户端和 SSH 服务器都在连接时立即发送横幅。如果您将 /dev/ttyS1 连接到 tcp:22(并且 ttyS1 的另一端没有任何监听),横幅将进入 bitbucket。
类似地,如果您使用 ssh -O "ProxyCommand='socat - /dev/ttyS0'" 目标,并且尚未将服务器端 socat 设置为 tcp:22,则客户端横幅会丢失。最终,这变成了一个时间问题。
你应该能够按照以下顺序完成您需要做的事情:
#In Host: (mapped to /var/run/qemu-server/vm.serial1)
socat -d -d UNIX-CONNECT:/var/run/qemu-server/vm.serial1 tcp-l:10022
#In Guest: (serial is /dev/ttyS1)
socat -d -d tcp:127.0.0.1:22 file:/dev/ttyS1,b115200
#In host:
ssh -vv [email protected] -p 10022
您所做的事情与上述事情的本质区别在于:
- 在主机中,我首先建立与 Unix 套接字的 socat 连接,而不是等待传入的 TCP 连接,然后才打开 Unix 套接字。这样,当我们在客户机中运行 socat 并且服务器发送其横幅时,socat 将读取并缓冲横幅,直到传入的 TCP 连接到达。
- 接下来我在客户机中运行 socat,以便它可以将其横幅发送到等待的 socat 进行缓冲。
- 只有这样我们才能运行 ssh 客户端。