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:
- Too many steps: VNC into my server -> open
virt-manager
-> go to the graphical console -> type in password. - You cannot paste anything into the graphical console in
virt-manager
. I would have manually type in the password every time. I don’t wanna manually input generated passwords like this every time my VMs need to be rebooted.
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).