virsh-ss (virsh send string)

Introduction

virsh is the CLI management tool for libvirt, a virtualization API commonly used for defining KVM/QEMU virtual machines. I’ve used libvirt for many years setting up virtual machines with GPU passthrough when gaming on Linux was not nearly as good. Nowadays, most games just work out of box on Linux, while the rest employ very annoying VM detection techniques, making the setup more or less obsolete.

When I began setting up my own home server, I decided to use qemu machines with libvirt since I had a lot of experience working with it. It was also around the time I started college, and I thought that having unencrypted data on my server is not the best idea, since roommates and university faculty had physical access to it. Having the entire disk be encrypted was not an option: I want to be able to reboot the box remotely, which would not be possible if I had to type in a password over a physical keyboard.

Concept

My solution is to use have each virtual machine that hosts a service to be encrypted, while having the hypervisor be open. This solves both of my problems, but creates a new one: how do you unlock the virtual machines? The simple solution is just open up the graphical console and type it in. This is very undesirable for two reasons:

But, there’s another way. virsh has a subcommand called virsh send-key. Like the name suggests, it sends a single keystroke to a virtual machine. A sample call of send-key for domain example looks like this:

# virsh send-key example KEY_H KEY_E KEY_L KEY_L KEY_O

Each character needs to be listed separately and formatted like KEY_ + uppercase ASCII. Special keys have their own names, such as KEY_BACKSLASH, for example. Finally, in order to send a #, we need to pass a shift key and the 3 key into virsh send-key:

# virsh send-key example KEY_LEFTSHIFT KEY_3

Implementation

To make this process a lot cleaner, I wrote a wrapper for converting regular strings into virsh send-key executable calls.

virsh-ss is a POSIX C99 program, therefore it should compile and work on Linux, BSD, and macOS. The latter two might not support sending keys to virtual machines based on which virtualization backend is used. I have no idea if this is true, as I haven’t done much testing outside of Linux.

With this tool you can write commands like this:

# virsh-ss example hello

There are also options for prompting the user for input, hiding input and also options for sending keystrokes faster. The prompting uses nanorl, which is a line editing library that I wrote. Personally, I use this command to unlock my virtual machines:

# virsh-ss -psn example

This command prompts (p) the user for input, hides (s) the input, and sends a newline (n).

Notes