Bootserver mit PXE

ZIEL: Rechner, auf denen kein Betriebssystem installiert ist, sollen übers Netzwerk gebootet werden können.

Wichtige Komponenten sind dabei:

  1. Preboot Execution Environment (PXE)

    1. Client: Netzwerkkarte muss PXE-fähig sein

    2. Server: Bootloader pxelinux.0 muss konfiguriert werden

  2. BootP Unterstützung (DHCP-Server)

  3. TFTP Dateitransfer für Kernel und Root Filesystem (FTP-Server)

Hyperlinks:

Bootablauf:

1.) PXE-Client ->  DHCPDISCOVER

                Next PXE-Server + DHCPOFFER  <- Boot-Server 2.)

3.) PXE-Client ->  DHCPOFFER

            Linux-Kernel via TFTP + DHCPACK  <- Boot-Server 4.)

Netzwerkkonfiguration

Am besten, wir führen die PXE-Bootexperimente in einem isolierten Netzwerk durch (hinter NAT). In Virtualbox verwenden wir dazu ein „Internes Netzwerk“ namens „intnet“. Damit kommen uns andere DHCP-Server nicht so leicht in die Quere. Die Schnittstelle enp0s3 zeigt ins WAN, enp0s8 ins LAN.

Mit der folgenden Netzwerkkonfiguration in der Datei /etc/network/interfaces haben wir einen guten Ausgangspunkt. Die letzten 15 Zeilen sind die besondern relevanten:

auto enp0s3
iface enp0s3 inet static
    address 192.168.2.234
    netmask 255.255.255.0
    gateway 192.168.2.1

auto enp0s8
iface enp0s8 inet static
    address 192.168.5.1/24

up echo nameserver 8.8.8.8 > /etc/resolv.conf
up echo 1 > /proc/sys/net/ipv4/ip_forward
up iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE

In diesem Falle gehen wir davon aus, dass kein DHCP-Client via NetworkManager, wicd, connman, systemd-resolved oder dergleichen am Start ist und unsere Resolver-Konfiguration, die wir hier einfach in die Datei /etc/resolv.conf schreiben, am Ende wieder kaputt macht!

PXE-Server einrichten

Mit apt-get install dnsmasq pxelinux syslinux installieren wir die erforderliche Software, dann geht es an die Konfiguration.

Bei Artix Linux (ein Arch Linux-Derivat ohne Systemd) würde die Zeile so lauten: pacman -Sy syslinux dnsmasq dnsmasq-openrc

DHCP- und TFTP-Server einrichten

Zuerst benennen wir die Konfigurationsdatei unseres schicken, kleinen DHCP- und TFTP-Servers „dnsmasq“ um:

root@pxeSrv# mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig

Danach erzeugen wir eine neue Datei namens /etc/dnsmasq.conf mit diesem Inhalt:

port=53
log-dhcp
enable-tftp
dhcp-range=192.168.5.50,192.168.5.150,12
tftp-root=/srv/tftp
dhcp-boot=pxelinux.0

HINWEISE zur Konfiguration von DNS-Masquerading und -Caching:

  1. Im einfachsten Fall kann die obige Resolver-Konfiguration unverändert bleiben, wobei der dort angegebene Nameserver automatisch den Boot-Clients zugewiesen wird.

  2. Soll der PXE-Server selbst auch in den Genuss des DNS-Zwischenspeichers kommen, ergänze man diese Datei um die Zeile server=8.8.8.8. Anschließend kann als Nameserver in der Resolver-Konfiguration „127.0.0.1“ gesetzt werden.

  3. Falls auf dieser Maschine bereits ein (Stub-)Nameserver wie systemd-resolved (wie bei Ubuntu), bind9 oder unbound läuft, kann dnsmasq nicht den Port 53 öffnen, daher bitte port=0 setzen.

  4. Falls aber eben port=0 gesetzt werden muss, bekommen die Boot-Clients keinen Nameserver mehr zugewiesen. Daher folgende Zeile noch hinzufügen: dhcp-option=option:dns-server,8.8.8.8

PXE-Bootloader, Menü- und Konfigurationsdatei

Nun kümmern wir uns als nächstes um die TFTP-Wurzel, wo der PXE-Bootloader landet sowie eine Textdatei für das Auswahlmenü:

root@pxeSrv# mkdir /srv/tftp
root@pxeSrv# cp /usr/lib/PXELINUX/pxelinux.0 /srv/tftp
root@pxeSrv# cp /usr/lib/syslinux/modules/bios/ldlinux.c32 /srv/tftp

Unter Artix/Arch liegen die Bootloaderdateien woanders: cp /usr/lib/syslinux/bios/pxelinux.0 /usr/lib/syslinux/bios/ldlinux.c32 /srv/tftp/

Wir erzeugen als nächstes die Datei fürs Auswahlmenü /srv/tftp/boot.msg und geben ihr folgenden Inhalt:

######################### PXE-Boot-Auswahl #########################

- Zum Starten der Live-Distribution SLiTaz bitte eingeben:

    slitaz  (oder einfach ENTER drücken oder 10s warten)

Timeout = 10s

####################################################################

Weiterhin erstellen wir mittels mkdir /srv/tftp/pxelinux.cfg das PXE-Konfigurationsverzeichnis, in dem dann die Datei default angelegt und mit diesem Inhalt befüllt wird:

# /srv/tftp/pxelinux.cfg/default
prompt 1
display boot.msg
default slitaz
timeout 100

label slitaz
kernel /SLITAZ/bzImage
append initrd=/SLITAZ/rootfs.gz root=/dev/null vga=771

Hier haben wir bereits die Startkonfiguration für unsere erste Client-Distribution „SLiTaz“ vorliegen.

PXE-bootfähige Micro-Distribution bereitstellen

Wir laden uns SLiTaz Linux herunter, mounten das ISO-File und kopieren uns daraus den Kernel sowie das Wurzeldateisystem (rootfs) in das dafür vorgesehene Verzeichnis:

root@pxeSrv# wget -c http://mirror.slitaz.org/iso/rolling/slitaz-rolling-core.iso
...

root@pxeSrv# mount -o ro,loop slitaz-rolling-core.iso /mnt
root@pxeSrv#
root@pxeSrv# mkdir /srv/tftp/SLITAZ
root@pxeSrv# cp /mnt/boot/bzImage /mnt/boot/rootfs.gz /srv/tftp/SLITAZ
root@pxeSrv#
root@pxeSrv# umount /mnt
root@pxeSrv#
root@pxeSrv# systemctl restart dnsmasq
root@pxeSrv#
root@pxeSrv# lsof -i:20,21,53,67 -Pn
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
dnsmasq  5389 dnsmasq    4u  IPv4  45906      0t0  UDP *:67
dnsmasq  5389 dnsmasq    6u  IPv4  45909      0t0  UDP *:53
dnsmasq  5389 dnsmasq    7u  IPv4  45910      0t0  TCP *:53 (LISTEN)
dnsmasq  5389 dnsmasq    9u  IPv6  45912      0t0  UDP *:53
dnsmasq  5389 dnsmasq   10u  IPv6  45913      0t0  TCP *:53 (LISTEN)
root@pxeSrv#

Und dies haben wir zu diesem Zeitpunkt insgesamt vorliegen:

root@pxeSrv# ls -lR /srv/tftp
/srv/tftp:
insgesamt 172
-rw-r--r-- 1 root root    277 Aug 22 08:56 boot.msg
-rw-r--r-- 1 root root 116552 Aug 22 08:54 ldlinux.c32
-rw-r--r-- 1 root root  42058 Aug 22 08:53 pxelinux.0
drwxr-xr-x 2 root root   4096 Aug 22 09:01 pxelinux.cfg
drwxr-xr-x 2 root root   4096 Aug 22 09:07 SLITAZ

/srv/tftp/pxelinux.cfg:
insgesamt 4
-rw-r--r-- 1 root root 187 Aug 22 09:01 default

/srv/tftp/SLITAZ:
insgesamt 34392
-rw-r--r-- 1 root root  2492912 Aug 22 09:07 bzImage
-rw-r--r-- 1 root root 32718961 Aug 22 09:07 rootfs.gz
root@pxeSrv#

Booten des ersten PXE-Clients

Während auf dem Server tail -f /var/log/syslog oder journalctl -f läuft, nun bitte SLiTaz Linux booten und dabei die Daumen drücken…

ZUSAMMENFASSUNG PXE-Boot

  1. Voraussetzung beim (Thin)-Client ist eine PXE-fähige Netzwerkkarte

  2. Der Server liefert im 1. Schritt per DHCP die Netzwerkkonfiguration und die Menü-Datei ‚boot.msg‘ aus

  3. Der Client wählt nun das zu bootende System aus:

    • Übertragung von Kernel und Rootfs via TFTP

    • Erneute DHCP-Netzwerkkonfiguration durch das bootende Live-System

  4. Danach ist unser Devuan-Server nur noch als NAT-Router tätig (Client will surfen…), siehe dazu die Ausgabe bei „pkts“ und „bytes“:

root@devuanBeo:~# iptables -vnL POSTROUTING -t nat
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
359 26972 MASQUERADE  all  --  *      eth0    0.0.0.0/0            0.0.0.0/0
root@devuanBeo:~#

Hyperlinks:

Hinzufügen weiterer PXE-Clients

Debian 10 - Installer

Zuerst laden wir das netboot-Archiv herunter, erstellen ein neues Verzeichnis in der TFTP-Wurzel und entpacken diesen Tarball:

root@pxeSrv# wget http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/netboot/netboot.tar.gz
--2019-08-22 10:48:43--  http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/netboot/netboot.tar.gz
Auflösen des Hostnamens ftp.nl.debian.org (ftp.nl.debian.org)… 130.89.149.21, 2001:67c:2564:a120::21
Verbindungsaufbau zu ftp.nl.debian.org (ftp.nl.debian.org)|130.89.149.21|:80 … verbunden.
HTTP-Anforderung gesendet, auf Antwort wird gewartet … 200 OK
Länge: 37152933 (35M) [application/x-gzip]
Wird in »netboot.tar.gz« gespeichert.

netboot.tar.gz                      100%[===================================================================>]  35,43M  12,4MB/s    in 2,9s

2019-08-22 10:48:46 (12,4 MB/s) - »netboot.tar.gz« gespeichert [37152933/37152933]

root@pxeSrv#
root@pxeSrv# mkdir /srv/tftp/DEBIAN
root@pxeSrv#
root@pxeSrv# tar xzf netboot.tar.gz -C /srv/tftp/DEBIAN

Als nächstes ergänzen wir die Konfigurationsdatei /srv/tftp/pxelinux.cfg/default um diese 4 Zeilen:

label debian
kernel /DEBIAN/debian-installer/amd64/linux
append priority=low vga=788 initrd=/DEBIAN/debian-installer/amd64/initrd.gz ---
include /DEBIAN/debian-installer/amd64/boot-screens/rqtxt.cfg

Außerdem muss auch das Auswahlmenü in der Datei /srv/tftp/boot.msg diese neuen Zeilen erhalten:

- Zum Starten des Debian Installers bitte eingeben:

    debian (Zum Absenden: ENTER)

Insgesamt hat unsere TFTP-Wurzel nun folgenden Inhalt:

root@pxeSrv# cd /srv/tftp
root@pxeSrv#
root@pxeSrv# ls -l
insgesamt 180
-rw-r--r-- 1 root root    364 Aug 22 11:01 boot.msg
drwxrwxr-x 3 root root   4096 Jul  2 00:39 DEBIAN
-rw-r--r-- 1 root root 119296 Aug 22 08:54 ldlinux.c32
-rw-r--r-- 1 root root  42430 Aug 22 08:54 pxelinux.0
drwxr-xr-x 2 root root   4096 Aug 22 10:51 pxelinux.cfg
drwxr-xr-x 2 root root   4096 Aug 22 09:09 SLITAZ
root@pxeSrv#
root@pxeSrv#
root@pxeSrv# ls -l DEBIAN/
insgesamt 8
drwxrwxr-x 3 root root 4096 Jul  2 00:39 debian-installer
lrwxrwxrwx 1 root root   47 Jul  2 00:39 ldlinux.c32 -> debian-installer/amd64/boot-screens/ldlinux.c32
lrwxrwxrwx 1 root root   33 Jul  2 00:39 pxelinux.0 -> debian-installer/amd64/pxelinux.0
lrwxrwxrwx 1 root root   35 Jul  2 00:39 pxelinux.cfg -> debian-installer/amd64/pxelinux.cfg
-rw-rw-r-- 1 root root   55 Jul  2 00:39 version.info
root@pxeSrv#
root@pxeSrv# ls -l DEBIAN/debian-installer/amd64/
insgesamt 37544
-rw-r--r-- 1 root root  1322936 Jul  2 00:39 bootnetx64.efi
drwxrwxr-x 2 root root     4096 Jul  2 00:39 boot-screens
drwxrwxr-x 3 root root     4096 Jul  2 00:39 grub
-rw-r--r-- 1 root root  1254768 Jul  2 00:39 grubx64.efi
-rw-rw-r-- 1 root root 30581523 Jul  2 00:39 initrd.gz
-rw-r--r-- 1 root root  5221616 Jul  2 00:39 linux
-rw-r--r-- 1 root root    42430 Jul  2 00:39 pxelinux.0
drwxrwxr-x 2 root root     4096 Jul  2 00:39 pxelinux.cfg
root@pxeSrv#

HINWEIS: Bei Debian 9 war ehedem http://ftp.nl.debian.org/debian/dists/stretch/main/installer-amd64/current/images/netboot/netboot.tar.gz herunterzuladen und zu entpacken, an der Konfiguration in der Datei /srv/tftp/pxelinux.cfg/default hat sich erfreulicherweise nichts geändert.

GParted

Quelle: https://gparted.org/livepxe.php

Zuerst wieder das Archiv herunterladen und entpacken. Dann benötigen wir hier allerdings 2 Verzeichnisse:

  • /srv/tftp/GPARTED für den Kernel samt Initrd

  • /srv/tftp/web/pxe/gparted für das Wurzeldateisystem (/srv/tftp/web wird später via Webserver freigegeben)

root@pxeSrv# wget -c https://sourceforge.net/projects/gparted/files/gparted-live-stable/1.0.0-3/gparted-live-1.0.0-3-i686.zip/download
root@pxeSrv# mkdir gparted-live-1.0.0-3-i686
root@pxeSrv# cd gparted-live-1.0.0-3-i686
root@pxeSrv# unzip ../gparted-live-1.0.0-3-i686.zip
root@pxeSrv# mkdir /srv/tftp/GPARTED
root@pxeSrv# mkdir -p /srv/tftp/web/pxe/gparted
root@pxeSrv# cd live/
root@pxeSrv# ls
filesystem.packages         filesystem.size      GParted-Live-Version  memtest
filesystem.packages-remove  filesystem.squashfs  initrd.img            vmlinuz
root@pxeSrv#
root@pxeSrv# cp vmlinuz initrd.img /srv/tftp/GPARTED/
root@pxeSrv# cp filesystem.squashfs /srv/tftp/web/pxe/gparted

Des weiteren ergänzen wir wieder die Konfigurationsdatei /srv/tftp/pxelinux.cfg/default, hier sind es die letzten 3 Zeilen:

# /srv/tftp/pxelinux.cfg/default
prompt 1
display boot.msg
default slitaz
timeout 100

label slitaz
kernel /SLITAZ/bzImage
append initrd=/SLITAZ/rootfs.gz root=/dev/null vga=771

label debian
kernel /DEBIAN/debian-installer/amd64/linux
append priority=low vga=788 initrd=/DEBIAN/debian-installer/amd64/initrd.gz ---
include /DEBIAN/debian-installer/amd64/boot-screens/rqtxt.cfg

label gpart
kernel GPARTED/vmlinuz
append initrd=/GPARTED/initrd.img boot=live config components union=overlay username=user noswap noeject ip= vga=788 fetch=http://192.168.5.1/pxe/gparted/filesystem.squashfs

Ähnlich läuft es mit unserem Auswahlmenü /srv/tftp/boot.msg, das um „gpart“ erweitert werden muss:

######################### PXE-Boot-Auswahl #########################

- Zum Starten der Live-Distribution SLiTaz bitte eingeben:

    slitaz  (oder einfach ENTER geben oder 10s warten)

- Zum Starten des Debian Installers bitte eingeben:

    debian (Zum Absenden: ENTER)

- Zum Starten ivon GParted Live bitte eingeben:

    gpart (Zum Absenden: ENTER)

Timeout = 10s

####################################################################

SystemRescueCD

Quelle: https://www.bachmann-lan.de/systemrescuecd-6-usb-und-pxe-boot/

ACHTUNG: Der PXE-Client benötigt hierzu mehr als 1024 MB RAM!

Nach dem Download unter http://www.system-rescue-cd.org/ mounten wir das ISO-Abbild und kopieren uns das Verzeichnis ‚sysresccd‘ ins passende Verzeichnis:

root@pxeSrv# mount -o loop systemrescuecd-6.0.3.iso /mnt
root@pxeSrv# mkdir -p /srv/tftp/web/pxe/
root@pxeSrv# cp -r /mnt/sysresccd /srv/tftp/web/pxe
root@pxeSrv# umount /mnt

Jetzt geht es mit der Konfiguration weiter, zuerst ist die Datei default dran, die letzten 6 Zeilen sind hinzuzufügen:

# /srv/tftp/pxelinux.cfg/default
prompt 1
display boot.msg
default slitaz
timeout 100

label slitaz
kernel /SLITAZ/bzImage
append initrd=/SLITAZ/rootfs.gz root=/dev/null vga=771

label debian
kernel /DEBIAN/debian-installer/amd64/linux
append priority=low vga=788 initrd=/DEBIAN/debian-installer/amd64/initrd.gz ---
include /DEBIAN/debian-installer/amd64/boot-screens/rqtxt.cfg

label gpart
kernel GPARTED/vmlinuz
append initrd=/GPARTED/initrd.img boot=live config components union=overlay username=user noswap noeject ip= vga=788 fetch=http://192.168.5.1/pxe/gparted/filesystem.squashfs

label resc
LINUX http://192.168.5.1/pxe/sysresccd/boot/x86_64/vmlinuz
INITRD http://192.168.5.1/pxe/sysresccd/boot/intel_ucode.img,http://192.168.5.1/pxe/sysresccd/boot/amd_ucode.img,http://192.168.5.1/pxe/sysresccd/boot/x86_64/sysresccd.img vga=791 setkmap=de
APPEND archisobasedir=sysresccd archiso_http_srv=http://192.168.5.1/pxe/
SYSAPPEND 3

Und natürlich muss auch wieder das Auswahlmenü in der Datei /srv/tftp/boot.msg für „resc“ ergänzt werden:

######################### PXE-Boot-Auswahl #########################

- Zum Starten der Live-Distribution SLiTaz bitte eingeben:

    slitaz  (oder einfach ENTER geben oder 10s warten)

- Zum Starten des Debian Installers bitte eingeben:

    debian (Zum Absenden: ENTER)

- Zum Starten von GParted Live bitte eingeben:

    gpart (Zum Absenden: ENTER)

- Zum Starten von SystemRescueCD Live bitte eingeben:

    resc (Zum Absenden: ENTER)


Timeout = 10s

####################################################################

Was uns nun noch fehlt, ist die PXE-Bootloaderdatei für nativen HTTP- und FTP-Transfer, die hier verwendet werden soll, wodurch wir auch die dnsmasq-Konfiguration anpassen müssen:

root@pxeSrv# cp /usr/lib/PXELINUX/lpxelinux.0 /srv/tftp/
root@pxeSrv# vi /etc/dnsmasq.conf
root@pxeSrv# cat /etc/dnsmasq.conf
# Falls auf dieser Maschine bereits ein Nameserver wie bind9 oder unbound läuft:
#port=0
port=53
log-dhcp
enable-tftp
dhcp-range=192.168.5.50,192.168.5.150,12
tftp-root=/srv/tftp
# AXPE geändert:
#dhcp-boot=pxelinux.0
dhcp-boot=lpxelinux.0
root@pxeSrv#
root@pxeSrv# systemctl restart dnsmasq

Webserver nginx installieren und konfigurieren

Weil wir hier mit nativen HTTP übers Netzwerk gehen wollen, braucht es noch einen Webserver, der mittels apt-get install nginx schnell installiert ist.

Allerdings muss das Freigabe-Wurzelverzeichnis für unseren Bedarfsfall noch abgeändert werden:

root@pxeSrv# sed -i 's/root \/var\/www\/html/root \/srv\/tftp\/web/' /etc/nginx/sites-enabled/default
root@pxeSrv# systemctl restart nginx
root@pxeSrv# tail -f /var/log/nginx/access.log
...