Uruchamianie LiveCD z dystrybucją Linuksa przez sieć
Już jakiś czas temu na tej stronie powstał artykuł o tym w jaki sposób utworzyć własne LiveCD z dystrybucją GNU/Linux Debian. Na podstawie tego materiału powstały dwa większe projekty jakim był greenOS oraz immudex. Immudex jest dalej rozwijany, a jego charakterystyczną cechą jest to, że musi on być aktualizowany ręcznie przez użytkownika za pomocą dysku USB lub dysku optycznego. W podobny sposób przebiega również instalacja. W zależności od tego jak tworzony jest obraz należy go przegrać na jakiś nośnik, aby uruchomić z niego komputer a następnie z aktualizować lub zainstalować na nim system. Nawet więcej, rozważmy taki przypadek, że chcemy uruchomić więcej niż jeden komputer z LiveCD, a mamy do dyspozycji tylko jeden pendrive. Rozwiązaniem tych, że problemów może być uruchomienie systemu z sieci z wykorzystaniem takich technologii jak DHCP, TFTP, PXE oraz HTTP.
Ze względu na to, że wykorzystujemy tutaj usługę DHCP - powszechną w każdej sieci lokalnej - środowisko PXE (uruchamiania z sieci) możemy skonfigurować w różnych wariantach. Podczas zgłębiania tematu udało mi się wyodrębnić 3 wariacje konfiguracji. Pierwsza z nich - ta najbardziej sprawdzona polega na wyłączniu obecnie używanej dla sieci usługi DHCP i zastąpienie jej tą uruchamianą na serwerze PXE. Z zalet to środowisko PXE na pewno zadziała w naszej sieci, gorzej z faktem, że musimy przenieść całą obecną konfigurację DHCP na nasz serwer i jeśli mamy bardzo dużo rezerwacji to okazuje się to bardzo żmudnym procesem. Dlatego to rozwiązanie może okazać się dobry rozwiązaniem dla wewnętrznej sieci laboratoryjnej. Ta właśnie metodą zostanie tutaj opisana, ponieważ w nalepszy sposób obrazuje zadania konfiguracyjne i stanowi solidną bazę do dalszych eksperymentów ze środowiskiem PXE. Drugą możliwością jest wykorzystanie obecnie działającego serwera DHCP, wówczas serwer PXE zajmuje wyłącznie się hostowanie plików przy użyciu protokołu TFTP. To rozwiązanie będzie dobrze funkcjonować w sieciach gdzie wykorzystywane są routery programowe, oparte na takim oprogramowanie jak na przykład IPFire. Trzecim wariantem jest brak serwera PXE w ogóle, bowiem istnieją routery lub oprogramowanie przygotowane dla routerów takie jak OpenWRT, które jest wstanie uruchomić serwer TFTP. Problemem tutaj jest fakt, że (przynajmniej w przypadku OpenWRT) możemy podać tylko jeden plik bootloadera, a dla komputerów z UEFI potrzebujemy innego pliku bootloadera, niż dla komputerów wykorzystujących klasyczny BIOS. Tutaj będziemy potrzebować wyłącznie plików programu rozruchowego, które możemy przygotować na własnym komputerze. Problematycze może być umieszczenie tych plików w pamięci flash urządzenia.
Jeśli na naszym komputerze posiadamy już zainstalowny system operacyjny w moim przypadku jest GNU/Linux Debian. To naszą konfigurację z racji, że będzie tam zainstalowany serwer DHCP - rozpoczynamy od statycznej konfiguracji interfejsu sieciowego.
# sudo vim /etc/network/interfaces ... allow-hotplug enp3s0 iface enp3s0 inet static address 192.168.1.253 netmask 255.255.255.0 gateway 192.168.1.1 dns-nameservers 192.168.1.1
Po wykonaniu tej konfiguracji, najlepiej jest serwer zrestartować aby zaczął on korzystać z tej konfiguracji. Następną czynnością jest utworzenie odpowiedniej struktury katalogowej dla serwera TFTP.
$ sudo mkdir -vp /pxeboot/{config,firmware}
Teraz wypełnimy katalog /pxeboot/firmware plikami programu rozruchowego. Do tego będzie potrzebować owych plików oraz pierwszego skryptu ipxe. Skrypt ipxe zawiera listę poleceń wykonywach w środowisku powłoki programu ładującego. Takim programem służącym do rozruchu z sieci jest właśnie projekt iPXE. Pliki wykonywalne tego programu skompilujemy samodzielnie z najnowszego kodu źródłowego projektu dostępnego w serwisie GitHub. Na początek zainstalujemy z repozytorium wymagane do pobrania kodu oraz jego kompilacji pakiety.
$ sudo apt install -y build-essetial liblzma-dev git
Po zainstalowaniu pakietów pobieramy kod źródłowy ze GitHub i przechodzimy do katalogu ipxe/src.
$ git clone https://github.com/ipxe/ipxe Klonowanie do „ipxe”... remote: Enumerating objects: 62694, done. remote: Counting objects: 100% (38/38), done. remote: Compressing objects: 100% (27/27), done. remote: Total 62694 (delta 15), reused 22 (delta 11), pack-reused 62656 (from 1) Pobieranie obiektów: 100% (62694/62694), 18.99 MiB | 30.47 MiB/s, gotowe. Rozwiązywanie delt: 100% (47450/47450), gotowe. $ cd ipxe/src
W tym katalogu, przed rozpoczęciem kompilacji tworzymy nasz skrypt ipxe. Skrypt ten zostanie umieszczony w kodzie programu rozruchowego, tak aby on uruchamiany zaraz po uruchomieniu samego programu - dążymy do tego aby było to jak najbardziej bezobsługowe.
~/ipxe/src$ vim bootconfig.ipxe #!ipxe dhcp chain tftp://192.168.1.253/config/boot.ipxe
Skrypt ten nakazuje programowi ładującemu, uzyskanie adresu konfiguracji
sieciowej z serwera DHCP i następnie przejście do uruchomienia kolejnego
skryptu (w tym przypadku) lub innego programu rozruchowego
(tzw. chainloading), który zapisany jest na serwerze TFTP.
Po utworzeniu pliku przechodzimy do kompliacji plików bootloadera
W tym celu wydajemy poniżej odpowiednie polecenie. Flaga
EMBED
wskazuje na nasz skrypt, bardzo
ważne jest prawidłowe zapisanie jej nazwy oraz wskazanie odpowiedniego
pliku, bowiem make
nie wskaże co do tego
błędów.
~/ipxe/src$ make bin/ipxe.pxe bin-x86_64-efi/ipxe.efi EMBED=bootconfig.ipxe [PARSEROM] [DEPS] core/version.c [DEPS] arch/x86/drivers/net/undiisr.S [DEPS] arch/x86/transitions/librm.S [DEPS] arch/x86/transitions/libpm.S [DEPS] arch/x86/transitions/libkir.S [DEPS] arch/x86/transitions/liba20.S [DEPS] arch/x86/prefix/usbdisk.S [DEPS] arch/x86/prefix/unlzma.S ... [BUILD] bin/rtl8180.ids.o [BUILD] bin/rtl8185.ids.o [BUILD] bin/ath5k.ids.o [BUILD] bin/ath9k.ids.o [AR] bin/blib.a [HOSTCC] util/zbin [VERSION] bin/version.ipxe.pxe.o [LD] bin/ipxe.pxe.tmp [BIN] bin/ipxe.pxe.bin [ZINFO] bin/ipxe.pxe.zinfo [ZBIN] bin/ipxe.pxe.zbin [FINISH] bin/ipxe.pxe rm bin/ipxe.pxe.zinfo bin/ipxe.pxe.bin bin/version.ipxe.pxe.o bin/ipxe.pxe.zbin [PARSEROM] [DEPS] core/version.c [DEPS] arch/x86/transitions/librm.S [DEPS] arch/x86/transitions/libpm.S [DEPS] arch/x86/transitions/libkir.S [DEPS] arch/x86/transitions/liba20.S [DEPS] arch/x86/prefix/usbdisk.S [DEPS] arch/x86/prefix/unlzma.S ... [BUILD] bin-x86_64-efi/hvm.ids.o [BUILD] bin-x86_64-efi/rtl8180.ids.o [BUILD] bin-x86_64-efi/rtl8185.ids.o [BUILD] bin-x86_64-efi/ath5k.ids.o [BUILD] bin-x86_64-efi/ath9k.ids.o [AR] bin-x86_64-efi/blib.a [HOSTCC] util/elf2efi64 [VERSION] bin-x86_64-efi/version.ipxe.efi.o [LD] bin-x86_64-efi/ipxe.efi.tmp [FINISH] bin-x86_64-efi/ipxe.efi rm bin-x86_64-efi/version.ipxe.efi.o
Skompliowane pliki wykonywalne programu rozruchowego kopiujemy do wcześniej utworzonego katalogu /pxeboot/firmware.
~/ipxe/src$ sudo cp -v bin/ipxe.pxe bin-x86_64-efi/ipxe.efi /pxeboot/firmware 'bin/ipxe.pxe' -> '/pxeboot/firmware/ipxe.pxe' 'bin-x86_64-efi/ipxe.efi' -> '/pxeboot/firmware/ipxe.efi'
Po skopiowaniu plików bootloadera, możemy zainstalować program, który będzie służył nam za serwer DHCP oraz za serwer TFTP. Dodatkowo domyślnie przekazuje on zapytania DNS, dalej do serwerów skonfigurowanych w systemie.
$ sudo apt install -y dnsmasq
Po zainstalowaniu pakietu możemy przjeść do jego konfiguracji. Rozpoczynamy ją od zabezpieczenia konfiguracji dostarczanej wraz z pakietem. W ten sposób będziemy rozpoczynać konfiguracje od zera, w tym przypadku jest to wskazane.
$ sudo mv /etc/dnsmasq.conf /etc/dnsmmasq.conf.bak
Teraz możemy zapisać poniższą konfigurację w /etc/dnsmasq.con.
interface=enp3s0 bind-interfaces domain=morketsmerke.org dhcp-range=enp3s0,192.168.1.100,192.168.1.200,255.255.255.0,12h dhcp-option=option:router,192.168.1.1 dhcp-option=option:dns-server,192.168.1.1 dhcp-option=option:dns-server,8.8.8.8 enable-tftp tftp-root=/pxeboot dhcp-match=set:bios-x86,option:client-arch,0 dhcp-boot=tag:bios-x86,firmware/ipxe.pxe dhcp-match=set:efi-x86_64,option:client-arch,7 dhcp-match=set:efi-x86_64,option:client-arch,9 dhcp-boot=tag:efi-x86_64,firmware/ipxe.efi
Na początku konfiguracji, dodajemy opcje związane z ogólnymi ustawieniami serwera, takie jak interfejs, na którym ma nasłuchiwać oraz wymusić na dnsmasq nasłuchiwanie na wyłącznie podanych interfejsach. Opcjonalnie możemy dodać nazwę domeny. W drugiej częsci konfiguracji ustawiamy parametry DHCP, takie jak zakres adresów, czas dzierżawy oraz adres bramy czy adresy serwerów DNS. Następnie włączamy usługę TFTP oraz wskazujemy jej katalog główny, w którym będą znajdować pliki udostępniane przez tę usługę. W ostaniej sekcji konfiguracji ustalamy z jakim oprogramowaniem układowym komputer skomunikował się z naszym serwerem DHCP i na podstawie tak uzyskanych informacji dnsmasq będzie określać jaki plik programu rozruchowego mu przekazać do uruchomienia.
Po skonfigurowaniu dnsmasq, nadszedł czas aby napisać już właściwy skrypt ipxe, które go zadaniem bedzie pobranie, załadowanie jądra naszej dystrybucji wraz plikiem initrd oraz uruchomienie jądra wraz z odpowiednimi parametrami. Plik nazwany boot.ipxe - nazwa ta musi być zgodna z nazwą podaną w skrypcie bootconfig.ipxe - ten umiesczamy w /pxeboot/config
#!ipxe set host ftp.morketsmerke.org set root_path immudex/pxe kernel http://${host}/${root_path}/vmlinuz initrd http://${host}/${root_path}/initrd imgargs vmlinuz initrd=initrd boot=live fetch=http://${host}/${root_path}/filesystem.squashfs boot
W tym skrypcie możemy spokojnie używać nazwy domenowej serwera jeśli
nie pamiętamy adresu IP. Ostatnia linia przekazuje argumenty uruchomieniowe
jądra. Parametr fetch
, jest opcją programu
live-boot, który jest odpowiedzialny za uruchomienie
i utrzymanie środowiska LiveCD. W tej linii możemy umieścić więcej opcji
konfigurujących to środowisko. Po zapisaniu konfiguracji pozostało nam,
uruchomienie ponowne usługi dnsmasq i spróbowanie uruchomienia.
Źródła:
- Configuring PXE Network Boot Server on Ubuntu 22.04 LTS [ang.]
- Installing Debian Bullseye ISO over PXE with [ang.]
- live-boot GNU/Linux Debian man page [ang.]
~xf0r3m