Linux – how to use ssh over serial without using pppd? ( Or how to transfer TCP over serial without using pppd)

linuxpoint-to-point-protocolqemuserialtcp

There are many virtual machine based on QEMU in my server. Some of them are forbbiden to use networking, and only way to attach them is via virtual serial port.

Due to serial console's bad features (such as working badly with tmux and vim), I want to use ssh via serial line.

Here is my try: (QEMU maps serial to a unix socket in host machine)

#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

Then I tried to run ssh -vv root@127.0.0.1 -p 10022, but it prompts:

Bad packet length 1349676916.
ssh_dispatch_run_fatal: Connection to UNKNOWN port 65535: message authentication code incorrect

But when I use

# Ctrl+C to terminate
socat STDIO,raw,echo=0,escape=0x3 UNIX-CONNECT:/var/run/qemu-server/vm.serial1

I can see

SSH-2.0-OpenSSH_7.6p1

So the tunnel is connected, but it seems that it can't transfer bare TCP over serial port (maybe lack of framing and package control).

So I tried to use pppd on serial line, and up a interface then ssh via TCP over IP over PPP…

But there are many VMs, it is hard to manage with so much interface created by ppp because of lack of automatic IP assigning. Also, an IP address just for ssh is too wasted.

So if it is possible to run a bare TCP socket over serial? Or skiping IP layer created by pppd and open a TCP socket over PPP like this:

+----------------------+
|                      |
|      TCP Socket      |
|                      |
+----------------------+
|                      |
| Data Link Layer(PPP) |
|                      |
+----------------------+

I only want to expose a TCP port (or a UNIX socket) to users who want to connect via ssh to a VM.

I tried to search for solutions, but all answers are about how to transfer serial over TCP, but what I want is reverse: how to transfer TCP over serial?

Best Answer

You're trying to shove a bunch of protocols that have nothing to do with serial consoles over a serial console. It's not going to yield reasonable results, and the data you want is already being offered in plain text.

If you use libvirt to define and manage your VMs, this work has already been done for you. virsh console <VM Name> will connect you to a serial console of a VM, and it works just fine - you can also pipe that over SSH from the host or connect to virsh over ssh+qemu if you want to do that. Similarly, most other management and orchestration systems like OpenStack or Xenserver have similar methods of connecting to pty-like VM serial devices without the need for unix sockets.

tmux doesn't work as well with serial interfaces as minicom or screen does. If you're taking a manual approach, connecting either of those to PTY or socket devices would yield satisfactory results.

If you have many serial consoles in a manual orchestration plane like pure QEMU tends to be, using a console server would be prudent rather than connecting to each VM on its own special socket or PTY. conserver is a good one that I've worked with fairly regularly. You can set up aliases for connecting serial programs to each VM and connect to those programs through conserver via SSH; this yields a simple console <servername> from the conserver host connected via SSH to get to where you need to be.