How to remotely decrypt a LUKS encrypted Debian/Ubuntu System

In this guide we will show how you can remotely decrypt a headless Debian or Ubuntu Linux system, that has been encrypted with LUKS.

Prerequisites

  • A LUKS encrypted Debian jessie or Ubuntu xenial system
  • Keyboard and monitor for the initial system setup
  • Allow SSH root access on the decrypted system using public key authentication
  • Use a different port for ssh (assuming port 4422) on the decrypted system

    NOTE: using a different port than the standard SSH port (22) serves a double purpose. For once, you will not received the scary WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! message every time you will try to remotely unlock the system and as an additional bonus you will get less SSH attacks on the active system.

Installing dropbear

Dropbear is a lightweight SSH server especially suitable for initial ramdisk (initrd) environments and other lightweight systems.

Install dropbear:

# apt -y install dropbear

Setup public key authentication for dropbear

Create the homedir for the root user and the SSH configuration directory:

# mkdir -p /etc/initramfs-tools/root/.ssh

Append your client SSH pubkey to authorized_keys:

# cat ~/.ssh/id_rsa.pub | ssh -p 4422 root@encrypted-system "cat >> /etc/initramfs-tools/root/.ssh/authorized_keys"

Setup a static IP for the unlock environment

This step is optional but highly recommended if you are setting up a static, permanent service. If you skip this step DHCP will kick in, provided you have a DHCP Server in your environment.

Run this command to update the /etc/initramfs-tools/initramfs.conf configuration file:

echo IP=10.0.0.67::10.0.0.1:255.255.255.0:encrypted-system:eth0:off >> /etc/initramfs-tools/initramfs.conf

Explanation of the different fields:
[host_ip]::[gateway_ip]:[netmask]:[hostname]:[device]:[autoconf]

NOTE: there are two successive colons (::) after the host_ip.

Setup the unlock script

Copy the following text in /etc/initramfs-tools/hooks/crypt_unlock.sh:

#!/bin/sh
#
# By Stinky Parkia
# https://stinkyparkia.wordpress.com/2014/10/14/remote-unlocking-luks-encrypted-lvm-using-dropbear-ssh-in-ubuntu-server-14-04-1-with-static-ipst/

PREREQ="dropbear"

prereqs() {
    echo "$PREREQ"
}

case "$1" in
    prereqs)
    prereqs
    exit 0
    ;;
esac

. "${CONFDIR}/initramfs.conf"
. /usr/share/initramfs-tools/hook-functions

if [ "${DROPBEAR}" != "n" ] && [ -r "/etc/crypttab" ] ; then
    cat > "${DESTDIR}/bin/unlock" << EOF
#!/bin/sh
if PATH=/lib/unlock:/bin:/sbin /scripts/local-top/cryptroot; then
    kill \`ps | grep cryptroot | grep -v "grep" | awk '{print \$1}'\`
    # following line kill the remote shell right after the passphrase has
    # been entered.
    kill -9 \`ps | grep "\-sh" | grep -v "grep" | awk '{print \$1}'\`
    exit 0
fi
exit 1
EOF

    chmod 755 "${DESTDIR}/bin/unlock"

    mkdir -p "${DESTDIR}/lib/unlock"
    cat > "${DESTDIR}/lib/unlock/plymouth" << EOF
#!/bin/sh
[ "\$1" == "--ping" ] && exit 1
/bin/plymouth "\$@"
EOF

    chmod 755 "${DESTDIR}/lib/unlock/plymouth"

    echo To unlock root-partition run "unlock" >> ${DESTDIR}/etc/motd
fi

Make the script executable:

# chmod +x /etc/initramfs-tools/hooks/crypt_unlock.sh

Apply the configuration

Apply the changes in the initial ramdisk:

# update-initramfs -u

Reboot the system:

# reboot

Remotely unlock the system

From your client, SSH into the initial ramdisk:

ssh root@encrypted-system 

If everything is correct you will be greeted by this MOTD:

To unlock root-partition run unlock

BusyBox v1.22.1 (Ubuntu 1:1.22.0-15ubuntu1) built-in shell (ash)
Enter 'help' for a list of built-in commands.

Unlock the system and boot into it:

# unlock
Please unlock disk sda3_crypt: 

You will get the following message and you will exit the remote shell if successful:

cryptsetup: sda3_crypt set up successfully
Connection to 10.0.0.67 closed.

You can now login to the active Linux system using the alternative port 4422:

ssh -p 4422 root@encrypted-system

If you can login successfully to your system you can remove the keyboard and monitor and hide your system somewhere where the Sun does not shine :).

Thanks to Stinky Parkia for the excellent guide and the brilliant unlock script.

References

12 comments

  1. It’s much easier than this at least on upcoming Debian 9/stretch, possibly also on Debian 8/jessie.

    apt-get -y install dropbear-initramfs
    echo 'DROPBEAR_OPTIONS="-p 2222"' >>/etc/dropbear-initramfs/config
    echo "ssh-rsa ...myhostkeygoeshere" >/etc/dropbear-initramfs/authorized_keys

    add the IP= line if you don’t wan’t to use DHCP

    update-initramfs -u

    and then

    ssh -p 2222 root@yourhost cryptroot-unlock
  2. Just wanted to say thank you for the tutorial this works just great on my Ubuntu 16.04 box.

    I do have a couple of items to add.

    1. When using multiple network interfaces best practice to lock down the configure inside initramfs.conf down to one device by using the ‘DEVICE=’ else you will need to make multiple IP= lines inside the config so you guarantee the IP address used by dropbear.

    2. In order to avoid any key warring you should change the a line inside /usr/share/initramfs-tools/scripts/init-premount/dropbear

    The line reads ‘exec /sbin/dropbear ${DROPBEAR_OPTIONS:-$PKGOPTION_dropbear_OPTION} -Fs’

    Append -p XXXX where XXXX is the port number used for the dropbear so it will not overlap with the port that is by your openssh thus avoiding the warnings when sshing into your machine.

  3. Great tutorial. However I am having a very strange problem. I am able to successfully unlock the filesystem using dropbear SSH and a static IP. But after a few moments and the filesystem builds, when I try to SSH into the box on the same IP and port, I get a network unreachable error. can anyone advise?

    1. Well the idea of the tutorial is to have a different port when the server is in production. In the tutorial we are using port 4422. So if you try this it will probably work:

      ssh -p 4422 root@encrypted-system
  4. Hey man, great tutorial.

    I had a few questions though.

    I am looking to set up an environment like this, however, I need it in the following architecture.

    Instead of initiating the unlock from the local host, how would I make it so when the encrypted server boots, it automatically calls the keyserver, retrieves a key file or passphrase, then unlocks the drive.

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *