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.
So I had to add support. To qemu and qemu-nbd. And to nbdkit.
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.
3 responses to “NBD with TLS-PSK”
Good to learn for QEMU testing 🙂
Could we utilize NBD to boot Foreman Discovery Image? Basically it’s Fedora/RHEL minimalistic LiveCD converted into PXE bootable files via a script from livecd-tools. Currently the ISO is 250-300 MB and it loads slow on PXE (TFTP). My idea is to have NBD bits in initramdisk or kernel itself so it would load the squashfs from network transparently.
I tried some experiments but could not get it working.
You would need an NBD client in the initramfs, and that loads the large ISO over the network?
It should be possible – NBD client is included in the kernel (the ‘nbd-client’ binary is just a wrapper around the kernel functions, basically it makes some
ioctl(fd, NBD_*, ..)system calls). The initramfs would have to run a command like:
which would create the virtual device
/dev/nbd0which would look like the ISO (accesses to the device turn into network requests for the parts of the ISO which are requested).
I don’t know what you would do with
/dev/nbd0. You could copy it out, or you could run
kpartxon it, or if the ISO is just a filesystem you could directly mount it.
On the server side there are plenty of NBD servers to choose from now. Of course I’m going to recommend nbdkit, but both qemu-nbd and nbd-server are valid choices.
I don’t think TLS-PSK has anything to do with this unless you want to restrict which clients have access to download the ISO.