Encrypt backups at an untrusted remote location

In a previous blog post I argued that a good backup solution includes backups at different geographical locations to compensate for local disasters. If you don’t fully trust the location, the only solution is to keep an encrypted backup.

In this tutorial we’re going to set up an encrypted, mountable backup image which allows us to use regular file system operations like rsync.

First, on any kind of permanent medium available, create a large enough file which will hold the encrypted file system. You can later grow the file system (with dd and resize2fs) if needed. We will use dd to create this file and fill this file with zeros. This may take a couple of minutes, depending on the write speed of the hard drive. Here, we create a 500GB file:

dd if=/dev/zero of=/path/to/backup.img bs=100M count=5000

A quicker method to do the same (file will not be filled with zeroes) is:

fallocate -l 500G /path/to/backup.img

Now we will use LUKS to set up a virtual mapping device node for us:

apt-get install cryptsetup

First, we generate a key/secret which will be used to generate the longer symmetric encryption key which in turn protects the actual data. We tap into the entropy pool of the Linux kernel and convert 32 bytes of random data into base64 format (this may take a long time; consider installing haveged as an additional entropy source):

dd if=/dev/random bs=1 count=32 | base64

Store the Base64-encoded key in a secure location and create backups! If this key/secret is lost, you will lose the backup. You have been warned!

Next, we will write the LUKS header into the backup image:

echo "Base64-encoded key" | base64 --decode | cryptsetup luksFormat --key-file=- /path/to/backup.img

Next, we “open” the encrypted drive with the label “backup_crypt”:

echo "Base64-encoded key" | base64 --decode | cryptsetup luksOpen --key-file=- /path/to/backup.img backup_crypt

This will create a device node /dev/mapper/backup_crypt which can be mounted like any other hard drive. Next, create an Ext4 file system on this raw device (“formatting”):

mkfs.ext4 /dev/mapper/backup_crypt

Now, the formatted device can be mounted like any other file system:

mkdir -p /mnt/backupspace_loop
mount -o loop /dev/mapper/backup_crypt /mnt/backupspace_loop

You can inspect the mount status by typing mount. If data is written to this mount point, it will be transparently encrypted to the underlying physical device.

If you are done writing data to it, you can unmount it as follows:

umount /mnt/backupspace_loop
cryptsetup luksClose /dev/mapper/backup_crypt

To re-mount it:

echo "Base64-encoded key" | base64 --decode | cryptsetup luksOpen --key-file=- /path/to/backup.img backup_crypt
mount -o loop /dev/mapper/backup_crypt /mnt/backupspace_loop

Note that we always specify the Base64-encoded key on the command line and pipe it into cryptsetup. This is better than creating a file somewhere on the hard drive, because it only resides in the RAM. If the machine is powered off, the decrypted mount point is lost and only the encrypted image remains.

If you are really security-conscientious, you need to read the manual of cryptsetup to optimize parameters. You may want to use a key/secret longer than the 32 bytes mentioned here.

How to set up password-less SSH login for a Dropbear client

Dropbear is a replacement for OpenSSH for environments with low memory and processor resources. With OpenSSH, you can use the well-known ssh-keyen command to create a private/public keypair for the client. In Dropbear, it is a bit different. Here are the commands on the client:

mkdir ~/.ssh
chmod 700 ~/.ssh/
dropbearkey -t rsa -f ~/.ssh/id_dropbear

Both private and public keys will be in ~/.ssh/id_dropbear, however in a binary format.

To output the public key to stdout in the usual SSH-compatible format, use:

dropbearkey -y -f ~/.ssh/id_dropbear

How to install yubikey-manager on Debian

yubikey-manager is a Python application requiring some dependencies for it to be installed from the Python repositories, because it is not yet in the official Debian package repository. Here is how:

apt-get install swig libpcsclite-dev
pip3 install yubikey-manager --user

Here is the main commandline utility: