Montag, 14. Mai 2012

SSH unlock with fully encrypted ubuntu 12.04 server

When operating a server with full system encryption it is often undesirable to enter the password with a local keyboard. However setting up unlocking via SSH with ubuntu 12.04 is quite a stony path as there are several bugs that need to be worked around, before it actually works. I put together a complete guide how to set it up. The tutorial is based on the setup created in the previous one.
So I assume your ubuntu 12.04 server is installed on a fully encrypted partition that is managed with LVM. The unlocking of the root-partition is done in the "initial ramdisk" that is stored on the unencrypted /boot partition. In order to enter this password over SSH, you need to add an SSH-server to your initial ramdisk. To keep the initial ramdisk small we use "dropbear" - an SSH-server implementatin for embedded systems.

# apt-get install openssh-server dropbear

The dropbear system-installation will automatically use the RSA and DSA keys provided by OpenSSH.
It is also automatically integrated into the initial ramdisk. However it generates a separate pair of keys for the initial ramdisk which can be undesirable because it will give you nasty "Host identification changed" errors when you connect to the ramdisk-system. So I decided to work around that by using the system-key-pair for the ramdisk as well:
# cp /etc/dropbear/dropbear_* /etc/initramfs-tools/etc/dropbear/

As the initial ramdisk will only contain a root-user, the root-user has to be activated and assigned a password.

# passwd root

Optional: If you like to authenticate using a public key you need to make sure the ramdisk accepts it:

# cp ~/.ssh/authorized_keys /etc/initramfs-tools/root/.ssh/authorized_keys

Because of a bug in ubuntu/debian authentication will always fail when trying to login to your initial ramdisk system. A workaround provided by Alex Roper fixes this problem.

# vi /etc/initramfs-tools/hooks/fix-login.sh

Copy the content of the script into the editor:

#!/bin/sh

PREREQ=""

prereqs()
{
    echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
    prereqs
    exit 0
    ;;
esac

cp $(dpkg -L libc6 | grep libnss_ | tr '\n' ' ') "${DESTDIR}/lib/"

Save the file and make sure it's executable:

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

After updating the initramfs you can reboot and login via SSH should work.

# update-initramfs -u
# reboot

However entering the password for the encrypted volume will not work because of a bug in plymouth that prevents other ways to enter the password. So another workaround is required.
Add another script "crypt_unlock" to /etc/initialramfs-tools/hooks:

# vi /etc/initramfs-tools/hooks/crypt_unlock.sh

And add the following content:

#!/bin/sh

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}'\`
    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 sure it's executable:

# chmod +x /etc/initramfs-tools/hooks/crypt_unlock
And update the initramfs

# update-initramfs -u
# reboot
Now when you boot into your initial ramdisk you can connect to your server via ssh and unlock the encrypted volume by typing

# unlock
Unlocking the disk /dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (sda2_crypt)
Enter passphrase: 
  Reading all physical volumes.  This may take a while...
  Found volume group "mydisk" using metadata type lvm2
  2 logical volume(s) in volume group "mydisk" now active
cryptsetup: sda2_crypt set up successfully
# 
Congratulations! You should now be able to unlock your encrypted server without a local keyboard present.

Kommentare:

  1. Actually now it works: Copy paste just did not paste the scipts above full, so check them before rebooting!

    AntwortenLöschen
  2. I got an error, "cannot stat '/lib/libnss_*': No such file or directory, when running the final update-initramfs -u.

    As for the version for you are using, search for the correct libnss.
    E.g in my small home development server, I searched
    #find / -name libnss_*

    Result:

    /lib/i386-linux-gnu/libnss_hesiod.so.2
    /lib/i386-linux-gnu/libnss_compat-2.15.so
    /lib/i386-linux-gnu/libnss_nisplus-2.15.so
    /lib/i386-linux-gnu/libnss_compat.so.2
    /lib/i386-linux-gnu/libnss_files.so.2
    etc...

    So in my box, replaced the line in the /usr/share/initramfs-tools/hooks/dropbear file saying
    cp /lib/libnss_* "${DESTDIR}/lib/"
    as
    cp /lib/i386-linux-gnu/libnss_* "${DESTDIR}/lib/"

    Then run
    $sudo update-initramfs -u
    Again reboot if no errors.

    AntwortenLöschen
  3. Interesting, I just tried everything on a 64-bit system

    AntwortenLöschen
  4. Final Solution for x86_64 and i386

    cp /lib/libnss_* /lib/$(uname -i)*/libnss_* "${DESTDIR}/lib/"

    AntwortenLöschen