matraszek.dev    Blog    Projects    Résumé    Feed

Remote unlocking LUKS-encrypted hard drive with TinySSH

One of the pain points of having hard drive encrypted with LUKS was that I could not unlock the drive remotely. Finally, I found some time to configure this on my system, so here is the walkthrough (please note that this may slightly differ on your system).

First, install the dependencies. mkinitcpio-* packages are the mkinitcpio hooks, tinyssh-convert is used to convert Ed25519 public keys from the format used by OpenSSH to the one used by TinySSH.

sudo pacman -S mkinitcpio-netconf mkinitcpio-tinyssh mkinitcpio-utils

Next, we have to configure hooks in /etc/mkinitcpio.conf. We should already have something like this:

HOOKS="base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 filesystems fsck"

We have to add netconf and tinyssh hooks before encrypt and change encrypt to encryptssh:

HOOKS="base udev autodetect keyboard keymap consolefont modconf block netconf tinyssh encryptssh lvm2 filesystems fsck"

Before rebuilding initrd image we have to add the public keys we will use to log in (the keys are included in the image, so we have to rebuild it every time we add new keys):

cp path/to/public/keys.pub /etc/tinyssh/root_key

You can add a single key, or just copy ~/.ssh/authorized_keys (but remember to always inspect the keys and only add the ones you will use). Please note that TinySSH only supports Ed25519 or ECDSA keys, so you will have to generate one if you use RSA (and you probably should upgrade them to Ed25519 anyway, so maybe it's a good excuse to migrate away from RSA).

Now, we can rebuild the image:

mkinitcpio -p linux

Next, we have to add a kernel command line parameter to configure Ethernet interface. Please note that you have to use kernel device names, not udev's. For most cases this will just be eth0, but if you use more then one network card (like me) and are unsure which kernel name to use, you can run ip a to find out udev device names and then dmesg | grep eth to find out kernel device names:

[   25.548268 ] r8169 0000:03:00.0 enp3s0: renamed from eth0
[   25.565145 ] r8169 0000:05:00.0 enp5s0: renamed from eth1

In my case it was eth1. Edit /etc/default/grub and modify GRUB_CMDLINE_LINUX to look like this (note the ip=::::... part):

GRUB_CMDLINE_LINUX="cryptdevice=UUID=aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee:cryptolvm root=/dev/mapper/vgroup-root ip=:::::eth1:dhcp"

I have IP address statically allocated on my router, so I used DHCP. You can also use static IP (for eth0): ip=192.168.1.2:::::eth0:none or static IP with gateway and netmask specified: ip=192.168.1.2::192.168.1.1:255.255.255.0::eth0:none

With ip parameter configured we can build GRUB configuration with grub-mkconfig -o /boot/grub/grub.cfg.

You can now reboot your machine and ssh to it (using root account) to unlock it.

You can get a host key verification failure, because server keys of TinySSH and OpenSSH differ and have different fingerprints. Some people advise to disable host verification or configure SSH to use /dev/null for this particular host — however, this is a bad idea. The better solution is to set up a separate known_hosts file location. To do that, use something like this in your SSH config:

Host remote-host-tinyssh
  HostName remote-host.example.com
  User root
  UserKnownHostsFile /home/user/.ssh/known_hosts.tinyssh

This configuration gives you an easy way to remotely unlock your machine.