Розшифровка контейнера LUKS в момент завантаження системи

Всім доброго дня, ночі! Цей пост буде корисний тим, хто використовує шифрування даних LUKS і хоче робити decryptдешифрування дисків під Linux (Debian, Ubuntu) на стадії розшифрування root розділу. І такої інформації в інтернеті знайти не зміг.

Нещодавно зі збільшенням кількості дисків у полицях, зіткнувся з проблемою розшифрування дисків з використанням більш ніж відомого методу через /etc/crypttab. Особисто я виділяю кілька проблем використання цього методу, саме те, що файл читається тільки після завантаження (mount) root-розділу, що негативно позначається на імпорті ZFS, зокрема, якщо вони були зібрані з розділів на *_crypt пристрої, або mdadm рейди, зібрані так само з розділів. Ми ж знаємо, що можна використовувати parted на LUKS контейнерах? І також проблема раннього старту інших служб, коли масивів ще немає, а використовувати вже щось треба (я працюю з кластеризованим Proxmox VE 5.x та ZFS over iSCSI).

Трохи про ZFSoverISCSIiSCSI працює у мене через LIO, і власне коли стартує iscsi-таргет і не бачить ZVOL пристроїв, він їх просто видаляє з конфігурації, що не дає можливості завантажуватися гостьовим системам. Звідси або відновлення бекапу json файлу, або ручне додавання пристроїв з ідентифікаторами кожної VM, що просто жах, коли таких машин десятки і в конфігурації кожної більше одного диска.

І друге питання, яке я розгляну, це чим робити розшифровку (це ключовий момент статті). І про це ми поговоримо нижче, заходьте під кат!

Найчастіше на просторах інтернету використовують ключовий файл (доданий перед цим в слот командою - cryptsetup luksAddKey), або в рідкісних винятках (в російськомовному інтернеті дуже мізерна інформація) - скрипт decrypt_derived, що лежить в /lib/cryptsetup/script/ (Звичайно, є ще способи, але я використав саме ці два, що лягло в основу статті). Так само я прагнув до повного автономного включення після перезавантажень, без будь-яких додаткових команд у консолі, щоб у мене все злітало відразу. Тож навіщо чекати? -

Приступаємо!

Припускаємо систему, наприклад Debian, встановлену на crypto-розділ sda3_crypt і десяток дисків, готових до шифрування та створення чого завгодно. Ми маємо ключову фразу (passphrase) для розблокування sda3_crypt і саме з цього розділу ми на запущеній (розшифрованій) системі зніматимемо «хеш» від пароля і додаватимемо на інші диски. Все елементарно, в консолі виконуємо:

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

де X це наші диски, розділи і т.д.

Після шифрування дисків «хешем» від нашої ключової фрази, необхідно дізнатися UUID, або ID - дивлячись хто і до чого звик. Беремо дані з /dev/disk/by-uuid та by-id відповідно.

Наступний етап підготовки файлів і міні-скриптів для роботи необхідних нам функцій, приступаємо:

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/

далі

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

Вміст ../decrypt

#!/bin/sh

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

далі

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

Вміст ../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"

ще трохи

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

Вміст ../partprobe

#!/bin/sh

$DESTDIR/bin/partprobe

і останнє перед update-initramfs потрібно відредагувати файл /etc/initramfs-tools/scripts/local-top/cryptroot, починаючи з рядка ~360, шматок коду нижче

Оригінал


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

і наводимо до такого виду

Відредагований


                # 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

Зверніть увагу, що тут можна використовувати UUID або ID. Головне, щоб потрібні драйвера на пристрої HDD/SSD були додані в /etc/initramfs-tools/modules. Дізнатися драйвер можна командою udevadm info -a -n /dev/sdX | egrep 'looking|DRIVER'.

Тепер, коли ми закінчили всі файли на місці, запускаємо update-initramfs -u -k all -v, у логуванні не повинно бути помилок виконання наших скриптів. Перезавантажуємося, вводимо ключову фразу і трохи чекаємо, залежно від кількості дисків. Далі система запуститься і на кінцевій стадії запуску, а саме після «маунтингу» root-розділу, буде виконана команда partprobe - вона знайде і підчепить всі створені розділи на пристроях LUKS і будь-які масиви, будь то ZFS або mdadm зберуться без проблем! І все це до завантаження основних служб та сервісів, яким потрібні ці диски/масиви.

update1: Як помітив AEP, цей спосіб працює тільки для LUKS1.

Джерело: habr.com

Додати коментар або відгук