Deszyfrowanie kontenera LUKS w momencie uruchamiania systemu

Witam wszystkich wspaniale, dzień dobry, noc! Ten post będzie przydatny dla tych, którzy używają szyfrowania danych LUKS i chcą przeprowadzać deszyfrowanie dysków na systemie Linux (Debian, Ubuntu) na etapie deszyfrowania partycji root. Takiej informacji nie mogłem znaleźć w internecie.

Niedawno, w miarę zwiększania liczby dysków w magazynach, natknąłem się na problem deszyfrowania dysków przy użyciu znanej metody przez /etc/crypttab. Osobiście wyróżniam kilka problemów związanych z używaniem tej metody, a mianowicie to, że plik jest odczytywany tylko po załadowaniu (mount) partycji root, co negatywnie wpływa na import ZFS, w szczególności jeśli były zbudowane z partycji na urządzeniu *_crypt, lub mdadm raidy, również zbudowane z partycji. Wszyscy wiemy, że można używać parted na kontenerach LUKS? Pojawia się również problem wczesnego uruchamiania innych usług, gdy tablice jeszcze nie istnieją, a już trzeba coś wykorzystać (pracuję z klastrowym Proxmox VE 5.x i ZFS over iSCSI). Trochę o ZFSoverISCSI

iSCSI działa u mnie przez LIO, a tak naprawdę, kiedy uruchamia się cel iscsi i nie widzi urządzeń ZVOL, po prostu je usuwa z konfiguracji, co uniemożliwia uruchomienie systemów gościnnych. Stąd albo przywracanie kopii zapasowej pliku json, albo ręczne dodawanie urządzeń z identyfikatorami każdej VM, co jest po prostu przerażające, gdy takich maszyn jest dziesiątki i w konfiguracji każdej jest więcej niż 1 dysk.A drugie pytanie, które rozważę, to czym przeprowadzać deszyfrowanie (to kluczowy moment artykułu). O tym porozmawiamy poniżej, zapraszam do lektury!

Najczęściej w internecie używa się pliku klucza (oczywiście dodanego wcześniej do slotu poleceniem — cryptsetup luksAddKey), albo w rzadkich przypadkach (w rosyjskiej sieci informacji jest bardzo mało) — skryptu decrypt_derived, znajdującego się w /lib/cryptsetup/script/ (oczywiście są jeszcze inne sposoby, ale użyłem tych dwóch, co stanowi fundament artykułu). Dążyłem też do pełnego autonomicznego uruchamiania po restarcie, bez jakichkolwiek dodatkowych poleceń w konsoli, żeby wszystko „wskakiwało” od razu. Dlatego, po co czekać? —

Zaczynamy!

Przystępujemy!

Zakładamy system, na przykład Debian, zainstalowany na partycji szyfrowanej sda3_crypt oraz dziesięć dysków gotowych do szyfrowania i tworzenia czego dusza zapragnie. Mamy frazę kluczową (passphrase) do odblokowania sda3_crypt i to z tej partycji będziemy na uruchomionym (odszyfrowanym) systemie pobierać „hash” hasła i dodawać go na pozostałe dyski. Wszystko jest proste, w konsoli wykonujemy:

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

gdzie X to nasze dyski, partycje itd.

Po zaszyfrowaniu dysków „hashem” z naszej frazy kluczowej, należy sprawdzić UUID lub ID — w zależności od preferencji. Pobieramy dane z /dev/disk/by-uuid i by-id odpowiednio.

Następny etap to przygotowanie plików i mini-skryptów do realizacji potrzebnych nam funkcji, przystępujemy do działania:

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/

dalej

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

Zawartość ../decrypt

#!/bin/sh

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

dalej

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

Zawartość ../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"

jeszcze trochę

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

Zawartość ../partprobe

#!/bin/sh

$DESTDIR/bin/partprobe

i na koniec, przed update-initramfs, należy zedytować plik /etc/initramfs-tools/scripts/local-top/cryptroot, zaczynając od linii ~360, poniższy fragment kodu

Oryginał


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

i przekształcamy go do takiej postaci

Zredagowany


                # 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

Zauważ, że można tutaj używać zarówno UUID, jak i ID. Ważne, aby odpowiednie sterowniki do dysków HDD/SSD były dodane do /etc/initramfs-tools/modules. Użyć można polecenia, aby poznać używany sterownik udevadm info -a -n /dev/sdX | egrep 'looking|DRIVER'.

Teraz, kiedy skończyliśmy i wszystkie pliki są na miejscu, uruchamiamy update-initramfs -u -k all -v, w logowaniu nie powinno być błędów wykonania naszych skryptów. Restartujemy, wpisujemy frazę kluczową i czekamy chwilę, w zależności od liczby dysków. Następnie system uruchomi się, a na końcowym etapie uruchamiania, a mianowicie po „zamontowaniu” partycji root, zostanie wykonane polecenie partprobe — znajdzie ono i podłączy wszystkie stworzone partycje na urządzeniach LUKS oraz jakiekolwiek macierze, czy to ZFS, czy mdadm, skomponują się bez problemów! I to wszystko przed załadowaniem głównych usług i serwisów, które wymagają tych dysków/macierzy.

update1: Jak zauważyłem AEP, ta metoda działa tylko dla LUKS1.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster