The Network Block Device (NBD) protocol is really useful to us when we deal with virtual machines and disk images. It lets us share disk images between machines and is also the universal protocol we use for communicating disk images between different bits of software. I wrote a pluggable NBD server called nbdkit to make this even easier.
However there was a problem: The protocol has no concept of logins. If you have an open NBD port, then anyone can connect and read or write your disk image. This is not quite as terrible as it sounds since when two processes are talking NBD to each other, we use a Unix domain socket and we hide the socket in a directory with restrictive permissions. But there are still cases — such as communicating between separate servers — where authentication would be useful.
NBD does let you upgrade the protocol to use TLS, and all the important NBD servers support that. You can use TLS to do client authentication but it’s seriously clunky and difficult to set up because you have to use X.509 certificates, and if we’ve learned anything from the web we know that X.509 is a plot by the NSA to stop us using encryption (only joking, spooks!)
It turns out there’s a more sensible corner of the TLS specification called TLS-PSK. This uses usernames and randomly generated Pre-Shared Keys (PSK). As long as you can ensure that both the client and server can read a simple
username:key file of keys, and the keys are kept secret, you can both authenticate and communicate securely.
Unfortunately just implementing TLS doesn’t get you PSK as well, and no existing NBD server supports TLS-PSK.
Amazingly it all works, and qemu and nbdkit interoperate too. Here’s how you could use it:
$ mkdir -m 0700 /tmp/keys $ psktool -u rich -p /tmp/keys/keys.psk
$ nbdkit -n \ --tls=require --tls-psk=/tmp/keys/keys.psk \ file file=disk.img
$ qemu-img info \ --object "tls-creds-psk,id=tls0,endpoint=client,username=rich,dir=/tmp/keys" \ --image-opts "file.driver=nbd,file.host=localhost,file.port=10809,file.tls-creds=tls0"
The qemu command line is a bit clunky, but it’s overall much simpler than setting up certificates, although not as scalable for large installations.