_                               _           
(_)_ __ ___  _ __ ___  _   _  __| | _____  __
| | '_ ` _ \| '_ ` _ \| | | |/ _` |/ _ \ \/ /
| | | | | | | | | | | | |_| | (_| |  __/>  < 
|_|_| |_| |_|_| |_| |_|\__,_|\__,_|\___/_/\_\

Transformacja GNU/Linux Debian w immudex - Budowanie

Chcąc podnieść swój poziom bezpieczeństwa na nieco wyżej, uznałem, że dobry pomysłem będzie użycie systemu, który jest niezmienny. Za najprostszą formę niezmienności uznałem systemy uruchamiane z poziomu LiveCD. Gdy taki system się uruchamia, zostaje uruchomione jądro oraz initrd, montowane jest archiwum squashfs, a dysk na którym są zapisane te elementy pozostaje w trybie tylko do odczytu. Uruchamiając komputer ponownie wszystko powróci do swojej pierwotnej formy. Tę dystrybucję oparłem o GNU/Linux Debian z dwóch powodów. Pierwszym z nich jest doświadczenie. Otóż już wcześniej zajmowałem się dystrybucją pochodną od Debiana oraz stabliność, GNU/Linux Debian to bardzo stablina dystrybucja. Ten materiał ma za zadnie przedstawić w jaki sposób można utworzyć obraz płyty z niezmiennym systemem operacyjnym.

Do budowy immudex potrzebujemy kilku pakietów do utworzenia końcowego obrazu płyty oraz plików, które on będzie zawierać.

$ sudo apt install -y debootstrap squashfs-tools xorriso isolinux syslinux-efi\
grub-pc-bin grub-efi-amd64-bin mtools dosfstools git vim

Teraz możemy utworzyć katalog przeznaczony na nasz system, jeśli będziemy obsługiwać obie architektury komputerów klasy PC tj. amd64 lub i386, to wypadało by utworzyć podkatalogi dla obu.

$ mkdir -p immudex/{64,32};

Po utworzeniu początkowych katalogów, możemy pobrać czysty obraz katalogu głównego z jednego z dostępnych serwerów lustrzanych.

$ sudo /sbin/debootstrap --arch=amd64 bullseye ~/immudex/64/chroot http://ftp.icm.edu.pl/debian

Polecenie debootstrap służy do pobrania oraz instalacji obrazu we wskazane miejsce (~/immudex/64/chroot). Wersja stablina immudex jest analogiczna do Debiana więc jako nazwę kodową wersji podajemy bullseye (wersja stablilna na czas pisania tego materiału). Tak samo jest z wersją testową. Ostatni argument to adres najszybszego dla nas serwera lustrzanego z repozytorium Debiana. Dla mnie jest SunSITE ICM UW.

Na chwilę opuszczamy utworzony wcześniej katalog ~/immudex, aby pobrać pliku projektu z serwisu GitHub: https://github.com/xf0r3m/immudex. Do tego celu najlepiej wybrać takie miejsce, w którym możemy pozostawić po sobie bałagan. Katalog ~/Pobrane świetnie się do tego nadaje.

$ if [ ! -d ~/Pobrane ]; then mkdir ~/Pobrane; fi
$ cd ~/Pobrane
$ git clone https://github.com/xf0r3m/immudex.git;

Pośród pobranych plików projektu znajduje się bazowy plik wersji (versions/base.sh), który wykorzystywany jest do budowania immudex od zera. Od czystej wersji Debiana. Ten plik musimy skopiować do katalogu, w którym debootstrap wypakował obraz Debiana.

$ sudo cp -v ~/Pobrane/immudex/version/bash.sh ~/immudex/64/chroot;

Plik ten musi zostać uruchomiony przez powłokę w zmienionym katalogu głównym. Skrypt aby mógł prawidłowo określić pakiety jakie trzeba pobrać (na przykład jądro) oczekuje również na podanie architektury (w tym przypadku jest to 64 dla amd64 lub 32 dla i386),

$ sudo chroot ~/immudex/64/chroot bash base.sh 64

Program zainstaluje wszystkie pakiety oferowane przez pierwszą wersję immudex, uzupełni system o kilka autorskich narzędzi ułatwiających pracę z dystrybucją zgodnie z jej koncepcją (oczywiście wszystko zostało stworzone, w taki sposób aby niczego nie narzucać. Wszystko można w łatwy sposób obejść) oraz skonfiguruje środowisko graficzne. Wszystkie czynności można sprawdzić analizując plik, który znajduje się w repozytorium: https://github.com/xf0r3m/immudex/blob/main/versions/base.sh

Po zakończeniu wykonywania czynności przez skrypt, możemy go usunąć, aby nie zaśmiecać obrazu.

$ sudo rm -f ~/immudex/64/chroot/base.sh;

Teraz kiedy rootfs jest gotowy. Możemy zająć się pozostałymi plikami do okoła niego. Wrócimy jeszcze do niego, tworząc z katalogu archiwum squashfs. Nasze czynności rozpoczniemy od utworzenia struktury katalogowej, której część znajdzie się na obrazie płyty.

$ mkdir -p ~/immudex/64/{staging/{EFI/boot,boot/grub/x86_64-efi,isolinux,live},tmp}

Po tym jak utworzyliśmy odpowiednie miejsce w strukturze, możemy teraz wygenerować z katalogu chroot archiwum squashfs. Ten proces może trochę potrwać w zależności od mocy naszego komputera. Istotnym faktem tutaj jest nazwa pliku archiwum squashfs. Nie jest ona przypadkowa, pod tą nazwą program live-boot odpowiedzialny za obsługę środowiska LiveCD będzie domyślnie szukać pliku o nazwa filesystem.squashfs i będzie próbować użyć go jako katalogu głównego. Wcześniej montując archiwum.

$ sudo mksquashfs ~/immudex/64/chroot ~/immudex/64/staging/live/filesystem.squashfs -e boot

Przygotowując squashfs nie możemy zapomnieć o jądrze oraz initrd. Nazwy plików jądra oraz initrd, zostały dobrane pod istniejące już pliki konfiguracyjne programów rozruchowych.

$ cp -v $(ls -v ~/immudex/64/chroot/boot/vmlinuz-* | tail -1) ~/immudex/64/staging/live/vmlinuz
$ cp -v $(ls -v ~/immudex/64/chroot/boot/initrd.img-* | tail -1) ~/immudex/64/staging/live/initrd

Już tłumaczę skąd wzięło się te podstawienia. Otóż, czasami może się zdarzyć, że katalog /boot będzie zawierał dwa jądra. Ponieważ przeważnie w dystrybucjach Linuksa tak jest. Jest "nowe" domyślne jądro oraz "stare" zapasowe wrazie gdy to nowe okaże się wadliwe. Wyżej wymienione podstawienia, uzupełnią polecenie nazwami plików nowszych wersji.

Po skopiowaniu plików jądra. Możemy zająć teraz kwestią uruchomienia systemu, a co za tym idzie - instalacja oraz konfiguracja programów rozruchowych. Immudex wspiera dwa tryby rozruchu: rozruch w trybie BIOS oraz w trybie UEFI (ale tylko UEFI 64-bitowe, domyślnie. Gdyż można przystosować pamięc USB do uruchomienia na komputerach z 32-bitowym UEFI - narzędzie create_media). Konfiguracja tych programów nie jest trudna, wystarczy kilka poleceń. Na początek zaczniem od załadowania do struktury katalogowej plików konfiguracyjnych. Za rozruch w trybie BIOS odpowiada program isolinux, część projektu syslinux, który będzie odpowiadać za rozruch już zainstalowanego immudex na dysku (o tym w innym materiale). Natomiast za rozruch w trybie UEFI odpowiada GRUB w wersji 2. Pliki konfiguracyjne znajdują się wśród plików projektu immudex.

$ cp -v immudex/isolinux/amd64/* ~/immudex/64/staging/isolinux;
$ cp -v immudex/grub/amd64/* ~/immudex/64/staging/boot/grub

Następną czynnością jest utworzenie pliku konfiguracyjnego dla samodzielnego pliku GRUB-a. W tym pliku wskazane jest katalog główny, ustalenie prefiksu dla ścieżek, oraz wskazanie pliku konfigracyjnego dla GRUB-a.

$ cat >> ~/immudex/64/tmp/grub-standalone.cfg <<EOF
search --set=root --file /DEBIAN
set prefix=(\$root)/boot/grub
configfile /boot/grub/grub.cfg
EOF

Pierwsza linia na powyższym przykładzie powoduje ustawienie zmiennej root scieżki dysku zawierającego plik DEBIAN. Więc, aby GRUB ustawił katalog główny obrazu jako swój główny katalog, musi się na nim znajdować "luzem" plik o nazwie DEBIAN.

$ touch ~/immudex/${arch}/staging/DEBIAN;

Aby programy rozruchowe mogły prawidło działać potrzebują plików pomocniczych. Te pliki są instalowane wraz z pakietami, które dostarczają do naszych systemów te programy. Poniżej znajdują się polecenia, których zadaniem jest skopiowanie plików pomocniczych programów rozruchowych do struktury katalogowej obrazu płyty.

$ cp -v /usr/lib/ISOLINUX/isolinux.bin ~/immudex/64/staging/isolinux;
$ cp -v /usr/lib/syslinux/modules/bios/* ~/immudex/64/staging/isolinux;
$ cp -rv /usr/lib/grub/x86_64-efi/* ~/immudex/64/staging/boot/grub/x86_64-efi

Teraz możemy utworzyć plik wykonywalny GRUB, który następnie zostanie załadowany do partycji UEFI:

$ grub-mkstandalone --format=x86_64-efi\
--output=${HOME}/immudex/64/staging/EFI/boot/bootx64.efi --locales=""\
--fonts="" "boot/grub/grub.cfg=${HOME}/immudex/64/tmp/grub-standalone.cfg";

Ciekawym argumentem jest tutaj ostatni argument, gdyż zawiera on mapowania plików. W przypadku tego pliku konfiguracyjnego GRUB-a jego plikiem jest plik ~/immudex/64/tmp/grub-standalone.cfg, o którym już wspomniałem. Tamten zaś wskazuje na właściwy już plik, w którym widnieją wpisy rozruchowe.

Tak utworzony plik możemy skopiować do partycji EFI, która w przypadku obrazów płyt jest plkiem. Poniżej znajdują polecenia, które tworzą plik partycji.

$ cd ~/immudex/64/staging/boot/grub
$ dd if=/dev/zero bs=1M of=efiboot.img count=20
$ sudo mkfs.vfat efiboot.img
$ sudo mmd -i efiboot.img efi efi/boot

Po utworzeniu pliku partycji oraz utworzeniu na nim odpowiednich folderów (ostatnie polecenie). Możemy skopiować nasz plik GRUB-a.

$ sudo mcopy -vi efiboot.img ~/immudex/64/staging/EFI/boot/bootx64.efi ::efi/boot 

Po wykonaniu tej czynności obraz w postacji struktury katalogów i plików jest gotowy. Pozostała do wykonania jedna czynność. Zmiana tej struktury w jeden plik, który będzie mógł być zapisany na płycie lub nośniku USB, a następnie komputer będzie mógł być z niego uruchomiony.

cd ~/immudex/64;
xorriso as mkisofs -iso-level 3 -o "immudex64.iso" -full-iso9660-filenames\
-volid "immudex64" -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin\
-eltorito-boot isolinux/isolinux.bin -no-emul-boot -boot-load-size 4\
-boot-info-table --eltorito-catalog isolinux/isolinux.cat -eltorito-alt-boot\
-e /boot/grub/efiboot.img -no-emul-boot -isohybrid-gpt-basdat\
-append_partition 2 0xef ~/immudex/${arch}/staging/boot/grub/efiboot.img\
~/immudex/64/staging

Poszczególne opcje polecenie xorriso ustawiają odpowiednio programy rozruchowe, aby były one uruchamiane podczas uruchamiana komputera z róznym rodzajem oprogramowania układowego. Obraz jest również ustawiony tak, aby hybrydą obrazu płyty oraz obrazu dysku, przez co może być załadowany bezpośrednio do pamięci USB. Dzięki tej czynności jesteśmy w stanie uruchomić komputer z pendrive-a.

Podsumowując dużą role w transformacji Debiana w immudex odgrywa bazowy plik wersji. Po za kilkoma szczegółami, prowadzona przeze mnie dystrybucja Linuksa dalej pozostaje Debianem. Nie chciałem tworzyć nowego bytu, a raczej dostoswać obecny byt do swoich potrzeb. Wiele z technik rekomendowanych to tworzenia obrazów z Debianem nie zostało tutaj użytych.

~xf0r3m