Libvirt SSH proxy

Sometimes it's necessary to run some commands inside a guest. While libvirt already provides a NSS module that can translate guest name to IP address it has some limitations (e.g. guest has to have a network interface plugged into a libvirt-managed network). To resolve some of these limitations, libvirt offers a SSH proxy. It consists of a SSH client config file (/etc/ssh/ssh_config.d/30-libvirt-ssh-proxy.conf) and a small binary. Both are automatically installed by libvirt-ssh-proxy package which is dragged in by libvirt-client, libvirt-daemon-qemu and/or daemon-kvm RPM packages. After running either of:

ssh user@qemu:system/virtualMachine
ssh user@qemu:session/virtualMachine

the configuration file instructs SSH client to start the binary helper which finds a VSOCK device inside the virtualMachine and establishes a connection to it.

For now, only QEMU domains are implemented and the lookup of the virtualMachine is done under qemu:///system URI for qemu:system or under qemu:///session URI for qemu:session.

For convenience, there's also another alternative:

ssh user@qemu/virtualMachine

where the virtualMachine is looked up under qemu:///system first, possibly followed by qemu:///session (for cases where ssh client runs as non-root, since there's no qemu:///session for root).

Accepted values for virtualMachine are: domain name (as reported by e.g. virsh list), domain UUID and finally domain ID.

Guest OS requirements

It is obvious that the SSH daemon inside the guest needs to be configured to listen for incoming connections on a VSOCK. There are couple of ways to achieve this:

  • Run systemd-v256 or newer inside the guest.

    In this release, systemd started to deploy systemd-ssh-generator which should configure socket activation for SSHD automagically.

  • Set up socket activation for VSOCK.

    We can take an inspiration in the unit file generated by systemd-ssh-generator:

[Unit]
Description=OpenSSH Server Socket (systemd-ssh-generator, AF_VSOCK)
Documentation=man:systemd-ssh-generator(8)
Wants=ssh-access.target
Before=ssh-access.target

[Socket]
ListenStream=vsock::22
Accept=yes
PollLimitIntervalSec=30s
PollLimitBurst=50
  • Run a service that forwards VSOCK <=> SSHD communication

    For instance:

socat VSOCK-LISTEN:22,reuseaddr,fork TCP:localhost:22

Libvirt domain XML configuration

Since the SSH proxy uses a VSOCK to communicate with the SSH daemon running inside the guest, it is a must to configure VSOCK in the domain XML.