Decrypting a LUKS container at system boot time

Good day and night everyone! This post will be useful for those who use LUKS data encryption and want to decrypt disks under Linux (Debian, Ubuntu) on stages of decrypting the root partition. And I could not find such information on the Internet.

More recently, with the increase in the number of disks in the shelves, I ran into the problem of decrypting disks using the more than well-known method through /etc/crypttab. Personally, I highlight a few problems with using this method, namely that the file is being read only after loading (mount) the root partition, which negatively affects ZFS imports, in particular if they were built from partitions on the *_crypt device, or mdadm raids built from partitions as well. We all know that you can use parted on LUKS containers, right? And also the problem of the early start of other services, when there are no arrays yet, but use I already need something (I work with clustered Proxmox VE 5.x and ZFS over iSCSI).

A little about ZFSoverISCSIiSCSI works for me through LIO, and in fact, when the iscsi target starts and does not see ZVOL devices, it simply removes them from the configuration, which prevents guest systems from booting. Hence, either restoring a json file backup, or manually adding devices with identifiers for each VM, which is simply terrible when there are dozens of such machines and each configuration has more than 1 disk.

And the second question that I will consider is how to decrypt (this is the key point of the article). And we'll talk about this below, go under the cut!

Most often, on the Internet, a key file is used (self-added to the slot before this by the command - cryptsetup luksAddKey), or in rare exceptions (on the Russian-language Internet there is very little information) - the decrypt_derived script located in /lib/cryptsetup/script/ (of course, there are other ways, but I used these two, which formed the basis of the article). I also strove for full autonomous inclusion after reboots, without any additional commands in the console, so that everything would β€œfly up” for me at once. Therefore, why wait? β€”

Getting started!

Let's assume a system, like Debian, installed on a sda3_crypt crypto partition and a dozen disks ready to be encrypted and created to your heart's content. We have a passphrase (passphrase) to unlock sda3_crypt, and it is from this partition that we will remove the β€œhash” from the password on the running (decrypted) system and add it to the rest of the disks. Everything is elementary, in the console we execute:

/lib/cryptsetup/scripts/decrypt_derived sda3_crypt | cryptsetup luksFormat /dev/sdX

where X is our disks, partitions, etc.

After encrypting the disks with a "hash" from our passphrase, you need to find out the UUID or ID - depending on who is used to what and what. We take data from /dev/disk/by-uuid and by-id respectively.

The next step is preparing files and mini-scripts for the functions we need, let's proceed:

cp -p /usr/share/initramfs-tools/hooks/cryptroot /etc/initramfs-tools/hooks/
cp -p /usr/share/initramfs-tools/scripts/local-top/cryptroot /etc/initramfs-tools/scripts/local-top/

more...

touch /etc/initramfs-tools/hooks/decrypt && chmod +x /etc/initramfs-tools/hooks/decrypt

Contents of ../decrypt

#!/bin/sh

cp -p /lib/cryptsetup/scripts/decrypt_derived "$DESTDIR/bin/decrypt_derived"

more...

touch /etc/initramfs-tools/hooks/partcopy && chmod +x /etc/initramfs-tools/hooks/partcopy

The contents of ../partcopy

#!/bin/sh

cp -p /sbin/partprobe "$DESTDIR/bin/partprobe"
cp -p /lib/x86_64-linux-gnu/libparted.so.2 "$DESTDIR/lib/x86_64-linux-gnu/libparted.so.2"
cp -p /lib/x86_64-linux-gnu/libreadline.so.7 "$DESTDIR/lib/x86_64-linux-gnu/libreadline.so.7"

a bit more

touch /etc/initramfs-tools/scripts/local-bottom/partprobe && chmod +x /etc/initramfs-tools/scripts/local-bottom/partprobe

Content ../partprobe

#!/bin/sh

$DESTDIR/bin/partprobe

and last, before update-initramfs, you need to edit the /etc/initramfs-tools/scripts/local-top/cryptroot file, starting from line ~360, code snippet below

Original


                # decrease $count by 1, apparently last try was successful.
                count=$(( $count - 1 ))
                
                message "cryptsetup ($crypttarget): set up successfully"
                break

and bring it to this form

Edited


                # decrease $count by 1, apparently last try was successful.
                count=$(( $count - 1 ))
                

                /bin/decrypt_derived $crypttarget | cryptsetup luksOpen /dev/disk/by-uuid/ *CRYPT_MAP*
                /bin/decrypt_derived $crypttarget | cryptsetup luksOpen /dev/disk/by-id/ *CRYPT_MAP*

                message "cryptsetup ($crypttarget): set up successfully"
                break

Note that either UUID or ID can be used here. The main thing is that the necessary drivers for HDD / SSD devices are added to /etc/initramfs-tools/modules. You can find out which driver is being used with the command udevadm info -a -n /dev/sdX | egrep 'looking|DRIVER'.

Now that we are done and all the files are in place, run update-initramfs -u -k all -v, in logging must not be execution errors of our scripts. We reboot, enter the passphrase and wait a bit, depending on the number of disks. Next, the system will start and at the final stage of launch, namely after β€œmounting” the root partition, the partprobe command will be executed - it will find and pick up all created partitions on LUKS devices and any arrays, be it ZFS or mdadm, will be assembled without problems! And all this before loading core services and services that need these disks/arrays.

update1: How noticed AEP, this method only works for LUKS1.

Source: habr.com

Add a comment