IPXE : utilisation avec TFTP, PXE, DHCP, NFS et HTTP

iPXE permet de mettre en place un système de démarrage PXE (réseau) afin de lancer des systèmes d’exploitation, des ISOs d’utilitaires ou des programmes d’installation. iPXE est compatible BIOS et EFI. Le système hôte utilisé pour l’élaboration de cette documentation est Ubuntu Server 18.04.

L'avantage de iPXE est qu'il s'adapte facilement aux interfaces BIOS et EFI.

Il existe d’autres méthodes comme par exemple : netboot ou netboot_live

Serveur DHCP

Installation du serveur DHCP sur le serveur.

Un serveur doit avoir une adresse ip fixe ! Ici, le serveur dispose de l’ip 10.0.0.200. Voir : netplan
sudo apt update && sudo apt install  isc-dhcp-server
sudo nano etc/dhcp/dhcpd.conf
/etc/dhcp/dhcpd.conf
default-lease-time 7200;
max-lease-time 7200;

allow unknown-clients;
#authoritative;
option subnet-mask 255.255.255.0;

###PXE###
option space PXE;
option PXE.mtftp-ip code 1 = ip-address;
option PXE.mtftp-cport code 2 = unsigned integer 16;
option PXE.mtftp-sport code 3 = unsigned integer 16;
option PXE.mtftp-tmout code 4 = unsigned integer 8;
option PXE.mtftp-delay code 5 = unsigned integer 8;
option arch code 93 = unsigned integer 16;

option space ipxe;
option ipxe-encap-opts code 175 = encapsulate ipxe;
option ipxe.priority code 1 = signed integer 8;
option ipxe.keep-san code 8 = unsigned integer 8;
option ipxe.skip-san-boot code 9 = unsigned integer 8;
option ipxe.syslogs code 85 = string;
option ipxe.cert code 91 = string;
option ipxe.privkey code 92 = string;
option ipxe.crosscert code 93 = string;
option ipxe.no-pxedhcp code 176 = unsigned integer 8;
option ipxe.bus-id code 177 = string;
option ipxe.san-filename code 188 = string;
option ipxe.bios-drive code 189 = unsigned integer 8;
option ipxe.username code 190 = string;
option ipxe.password code 191 = string;
option ipxe.reverse-username code 192 = string;
option ipxe.reverse-password code 193 = string;
option ipxe.version code 235 = string;
option iscsi-initiator-iqn code 203 = string;
# Feature indicators
option ipxe.pxeext code 16 = unsigned integer 8;
option ipxe.iscsi code 17 = unsigned integer 8;
option ipxe.aoe code 18 = unsigned integer 8;
option ipxe.http code 19 = unsigned integer 8;
option ipxe.https code 20 = unsigned integer 8;
option ipxe.tftp code 21 = unsigned integer 8;
option ipxe.ftp code 22 = unsigned integer 8;
option ipxe.dns code 23 = unsigned integer 8;
option ipxe.bzimage code 24 = unsigned integer 8;
option ipxe.multiboot code 25 = unsigned integer 8;
option ipxe.slam code 26 = unsigned integer 8;
option ipxe.srp code 27 = unsigned integer 8;
option ipxe.nbi code 32 = unsigned integer 8;
option ipxe.pxe code 33 = unsigned integer 8;
option ipxe.elf code 34 = unsigned integer 8;
option ipxe.comboot code 35 = unsigned integer 8;
option ipxe.efi code 36 = unsigned integer 8;
option ipxe.fcoe code 37 = unsigned integer 8;
option ipxe.vlan code 38 = unsigned integer 8;
option ipxe.menu code 39 = unsigned integer 8;
option ipxe.sdi code 40 = unsigned integer 8;
option ipxe.nfs code 41 = unsigned integer 8;

###RESEAUX###
subnet 10.0.0.0 netmask 255.255.255.0 {
        option broadcast-address 10.0.0.255;
        option routers 10.0.0.1;
        option domain-name-servers 8.8.8.8, 1.1.1.1;
        range 10.0.0.100 10.0.0.199;
        ping-check = 1;
        next-server 10.0.0.200;
#      PXE
        if option arch = 00:07 or option arch = 00:09 {
                if exists user-class and option user-class = "iPXE" {
                        filename "http://10.0.0.200/install.ipxe";
                } else {
                        filename "ipxe/ipxe.efi";
                }
        } else if option arch = 00:06 {
                if exists user-class and option user-class = "iPXE" {
                        filename "http://10.0.0.200/install.ipxe";
                } else {
                        filename "ipxe/ipxe32.efi";
                }
        } else {
         	if exists user-class and option user-class = "iPXE" {
                        filename "http://10.0.0.200/install.ipxe";
                } else {
                        filename "undionly.kpxe";
                }
        } 
}
Dans la configuration ci-dessous le réseau est configurer en 10.0.0.0/24, libre a vous de l’adapter à votre réseau actuel.

Les premières « option » permettent à isc-dhcp-server de comprendre des options DHCP spécifique à ipxe. Cela sera plus compréhensible plus tard, mais les « if » en fin de document permettent de distribuer le bon fichier en fonction du client PXE (Bios, EFI) Pour plus d’info sur la configuration : isc-dhcp-server

sudo service isc-dhcp-server restart
Avoir deux serveurs DHCP sur le même réseau est souvent synonyme de conflits. Il est préférable de désactiver tous les autres serveurs DHCP (de votre box ou routeur par exemple). Dans ce cas, il faut décommenter la ligne "authoritative;" en dessous allow unknown-clients.

Dans le cas où il n'est pas possible de désactiver les autres serveur DHCP, à minima, il faut régler le paramètre "range" sur une autre plage que celle de votre autre serveur DHCP.

Une autre méthode consiste à amorcer iPXE à l'aide d'une clé USB : Créer une clé USB d'iPXE

Serveur TFTP

Le serveur TFTP est celui qui va fournir les fichiers nécessaires au démarrage réseau.

sudo apt install tftpd-hpa
sudo nano /etc/default/tftpd-hpa
/etc/default/tftpd-hpa
# /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/var/lib/tftpboot"
TFTP_ADDRESS="10.0.0.200:69"
TFTP_OPTIONS="--secure"
RUN_DAEMON="yes"

Ensuite, redémarrer le service :

 sudo service tftpd-hpa restart
Si un pare-feu est activé, il faut ouvrir le port 69

Serveur NFS

Le serveur NFS sera nécessaire dans certains cas, il permet de laisser à disposition des fichiers au système démarré.

sudo apt install nfs-kernel-server
Si un pare-feu est activé, il faut ouvrir le port 2049

Serveur LAMP basique

Pour fonctionner, iPXE à besoin d’un serveur HTTP.

sudo apt install apache2 php libapache2-mod-php php-mysql php-curl php-gd php-intl php-json php-mbstring php-xml php-zip

Pour plus d'infos : https://doc.ubuntu-fr.org/lamp

On créer un lien symbolique de tftpboot sur le serveur LAMP :

ln -s /var/lib/tftpboot /var/www/html/tftpboot

Ces fichiers sont téléchargeables sur le site officiel de ipxe.

cd /var/lib/tftpboot
wget http://boot.ipxe.org/undionly.kpxe
wget http://boot.ipxe.org/ipxe.efi
Ici, le lien vers le serveur HTTP est effectué par le serveur DHCP. Il existe une autre méthode consistant à compiler manuellement pour simplifier le travail du serveur DHCP (le lien vers le serveur HTTP est intégré au fichier).
cd /tmp
git clone git://git.ipxe.org/ipxe.git
cd /tmp/ipxe/src
nano /tmp/ipxe/src/chain.ipxe
/tmp/ipxe/src/chain.ipxe
#!ipxe

dhcp
chain http://10.0.0.200/install.ipxe 
cd /tmp/ipxe/src
make bin-x86_64-efi/ipxe.efi EMBED=chain.ipxe
make bin-i386-efi/ipxe.efi EMBED=chain.ipxe
make undionly.kpxe EMBED=chain.ipxe

cp bin-x86_64-efi/ipxe.efi undionly.kpxe /var/lib/tftpboot/
cp bin-i386-efi/ipxe.efi /var/lib/tftpboot/ipxe32.efi

La construction nécessite les paquets suivants : gcc binutils liblzma-dev

Le menu de iPXE doit être situé sur le serveur web. Le fichier install.ipxe doit selon le reste du tutoriel être situé à la racine du serveur DHCP. Dans le cas contraire, il faut adapter la configuration de DHCP ou le fichier chain.ipxe lors de la compilation.

sudo nano /var/www/html/install.ipxe
/var/www/html/install.ipxe
#!ipxe

set menu-timeout 9000000
set submenu-timeout ${menu-timeout}
isset ${menu-default} || set menu-default item3
set server_ip 10.0.0.200

menu
item --gap --           -------------SÉPARATION 1----------------
item item1            	Item 1
item --gap --           -------------SÉPARATION 2----------------
item item2      	Item 2
item item3		Item 3
item shell              Shell iPXE
item exit              	Exit

choose --timeout ${menu-timeout} --default ${menu-default} target && goto ${target}

:item1
#Paramètres de démarrage pour item 1

:item2
#Paramètres de démarrage pour item 2

:item3
#Paramètres de démarrage pour item 3

:shell
shell

:exit
exit
Ce menu ne sert à rien dans l’état, il est à compléter en fonction de ce que l’on a démarrer. Voir sur le chapitre Compléter le menu iPXE

Utiliser un ordinateur ou une machine virtuelle pour tenter un démarrage PXE. Pour cela, il faut changer l'ordre de boot dans le bios/uefi de votre machine pour sélectionner "PXE" ou "réseau".

Plus d'infos : Modifier l'ordre d'amorçage du BIOS

Si cela ne fonctionne pas dans une machine virtuelle, tentez quand même sur un ordinateur physique. Sur les machines virtuelles, cela a parfois tendance à fonctionner une fois sur deux !

Savoir décompresser une ISO

Souvent, il sera nécessaire d'extraire le contenu d'une ISO pour le mettre sur le serveur TFTP/HTTP.

sudo mount -o loop /chemin/vers/un_systeme.iso /mnt
sudo mkdir /var/lib/tftpboot/un_systeme
sudo cp -r /mnt/* /var/lib/tftpboot/un_systeme
sudo umount /mnt

Il faudra rétablir les bons droits :

sudo chown -R root:root /var/lib/tftpboot
sudo chmod 755 /var/lib/tftpboot

Parce qu'il est parfois plus simple d'appeler les fichiers via http, nous allons créer un lien symbolique pour ne pas avoir à faire doublon et qu'ils soient accessible via les deux protocoles.

sudo ln -s /var/lib/tftpboot /var/www/html/tftpboot
Pour la suite du tutoriel, il faudra toujours vérifier que tous les chemins d'accès aux différents fichiers correspondent à ce que vous avez fait. Les fichiers de configurations doivent être adapté à votre situation ! (Penser à respecter la casse minuscule/majuscule…)

Démarrer une installation Linux (casper)

Après avoir décompressé sur le serveur tftp un Live CD d'installation d'un Linux, il faudra ajouter au menu :

/var/www/html/install.ipxe
item ubuntuinstall      Ubuntu Install

# Plus bas...

:ubuntuinstall
kernel http://${server_ip}/tftpboot/ubuntuinstall/casper/vmlinuz
initrd http://${server_ip}/tftpboot/ubuntuinstall/casper/initrd
imgargs vmlinuz initrd=initrd root=/dev/nfs boot=casper netboot=nfs nfsroot=${server_ip}:/var/lib/tftpboot/ubuntuinstall ip=dhcp --
boot
Il convient évidemment d'adapter les paramètres à sa situation. Les fichiers vmlinuz et initrd étant parfois accompagnés d'une extensions comme .gz, il faudra l'ajouter.

Il faudra ensuite autoriser le partage dans le fichier de configuration de NFS :

sudo echo "/var/lib/tftpboot/ubuntuinstall *(async,no_root_squash,no_subtree_check,ro) /etc/exports" >> /etc/exports
sudo service nfs-kernel-server restart

Démarrer Windows

Pour Windows, la méthode consiste a démarrer un Windows PE, puis, ci-besoin lancer une installation depuis un serveur samba. Il sera utilisé wimboot.

Obtenir wimboot

cd /tmp
wget git.ipxe.org/releases/wimboot/wimboot-latest.zip
unzip wimboot-latest.zip
cp wimboot*/wimboot /var/lib/tftpboot

Créer un Windows PE

Sous Linux
cd /tmp
wget https://download.microsoft.com/download/4/6/C/46C337E7-336A-4199-9117-4D15D6BEC67B/KB3AIK_FR.iso
mount -o loop KB3AIK_FR.iso /mnt
mkwinpeimg --iso --arch=[amd64|x86] --waik-dir=/mnt /var/lib/tftpboot/winpe.iso
umount /mnt
Sous Windows

Pré-requis : Télécharger et installer Windows ADK WinADK

Désactiver votre programme antivirus lors de la manipulation des images.

Dans le menu démarrer taper : "Environnement de déploiement et d’outils de création d’images" et l'ouvrir en tant qu'administrateur.

Copier WinPE

copype amd64 C:\WinPE_am64

Monter l'image de démarrage :

Dism /Mount-Image /ImageFile:"C:\WinPE_amd64\media\sources\boot.wim" /index:1 /MountDir:"C:\WinPE_amd64\mount"
Il est possible a ce stade de rajouter des fichiers/dossier dans C:\WinPE_amd64\mount

Il est aussi possible de modifier le script de démarrage (pour lancer des commandes automatiquement au démarrage) : Exemple :

C:\WinPE_amd64\mount\Windows\System32\Startnet.cmd
wpeinit
net use Y: \\10.0.0.200\win10_1809_custom_x64 /user:user pass
Y:\setup.exe

Pour ajouter des pilotes de périphériques (.inf) :

Un seul à la fois :

Dism /Add-Driver /Image:"C:\WinPE_amd64\mount" /Driver:"C:\SampleDriver\driver.inf"

Tout un dossier de .inf (il peut être nécessaire d'utiliser /ForceUnsigned pour ajouter des pilotes non signés)

Dism /Add-Driver /Image:"C:\WinPE_amd64\mount" /Driver:"C:\SampleDriver" /Recurse

Vérification :

Dism /Image:"C:\WinPE_amd64\mount" /Get-Drivers	
D'autres manipulations et modifications sont possibles : WinPE : Monter et personnaliser

Quand toutes les modifications sont terminées, il faut démonter l'image :

Dism /Unmount-Image /MountDir:"C:\WinPE_amd64\mount" /commit

Création d'un image ISO :

Makewinpemedia /iso C:\winpe_amd64 C:\winpe_amd64.iso

Configuration du menu

Après avoir extrait l'iso dans un dossier comme expliqué plus haut, les paramètres sont les suivants :

/var/www/html/install.ipxe
item winpe            Windows PE

# Plus bas....


:winpe
kernel http://${server_ip}/tftpboot/wimboot
initrd http://${server_ip}/tftpboot/winpe/Boot/BCD         BCD
initrd http://${server_ip}/tftpboot/winpe/Boot/boot.sdi    boot.sdi
initrd http://${server_ip}/tftpboot/winpe/sources/boot.wim boot.wim
boot

Lancer Windows PE

Préalablement, il faudra extraire une ISO de Windows PE comme expliqué plus haut.

Lancer une installation de Windows

Installer et lancer le serveur samba

Pour lancer des installations, un serveur samba sera nécessaire.

sudo apt-get install samba samba-common-bin
sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.save # Par sécurité
sudo nano /etc/samba/smb.conf

Ajouter à la fin du fichier :

/etc/samba/smb.conf
[win10]
path = /var/lib/tftpboot/win10
browseable = no
writable = no
guest ok = yes
create mask = 0775
directory mask = 0775
Lancer setup.exe

Une fois Windows PE de démarrer, saisir dans l'invite de commande cmd : (win10 représente ce qu'il y a entre parenthèses dans le fichier de configuration de samba)

net use Y: \\10.0.0.200\win10 /user:user pass
Y:\setup.exe
Même si le répertoire samba est accessible anonymement (guest ok = yes), il faut saisir un utilisateur et un mot de passe bidon pour que la connexion fonctionne.
Pour les deux solutions, il est possible d'automatiser ces commandes en modifiant le fichier %windir%\System32\startnet.cmd lors de la création du Windows PE. Exemple :
%windir%/System32/startnet.cmd
wpeinit
net use Y: \\10.0.0.200\win10 /user:user pass
Y:\setup.exe

Si ce n'est pas automatiser, un seul Windows PE est suffisant pour plusieurs versions de Windows (7/8/10… x64/x86…). Il suffit de créer plusieurs partages samba.

Démarrer les petites ISO

Pour démarrer des petites ISO, nous allons utiliser sanboot pour sa simplicité.

Les démarrage via sanboot oblige l'ordinateur client de télécharger complétement l'ISO pour pouvoir l'utiliser. C'est pourquoi il faut éviter cette méthode et la réserver à des petits utilitaires comme memtest86 ou gparted par exemple.
/var/www/html/install.ipxe
item memtest86        Memtest86 7.4

# Plus bas...

:memtest86
sanboot http://${server_ip}/tftpboot/Memtest86-7.4.iso

Démarrer une installation de MAC OS

Un projet github propose une solution : https://github.com/mybesttools/macos-netboot-ipxe

Si cela ne fonctionne pas

Si je n'ai pas de menu

  • Tester avec un autre ordinateur
  • Vérifier que la connexion ethernet fonctionne
  • Vérifier si l'ordinateur récupère une adresse IP et les paramètres auprès du serveur DHCP
  • Vérifier les droits du fichier menu (install.ipxe) et des fichiers de démarrage (undionly.kpxe et ipxe.efi)

Si j'ai le menu (dans ce cas là, c'est le système choisi qui ne démarre pas)

  • Vérifier que tous les fichiers pointés dans la configuration du menu sont accessibles et que les chemins sont corrects.
  • Vérifier si il n'y a pas un problème de droit
  • Si vous êtes en EFI, vérifiez que ce que vous voulez démarrer est compatible.

Créer une clé USB d'iPXE

Pour éviter l'utilisation de dhcp par exemple, il est possible de mettre iPXE sur une clé USB bootable. Il faut compiler ipxe.usb à partir des sources pour ensuite le transférer sur la cle usb. Le paquet suivant sera nécessaire : liblzma-dev

cd /tmp
git clone git://git.ipxe.org/ipxe.git
cd ipxe/src
Manipulez la commande dd avec beaucoup de précaution !!

Pour la version bios :

make bin/ipxe.usb
dd if=bin/ipxe.usb of=/dev/sdX status=progress # où sdX représente la clé USB

Pour la version efi :

make bin-x86_64-efi/ipxe.usb
dd if=bin-x86_64-efi/ipxe.usb of=/dev/sdX # où sdX représente la clé USB 

Gagner de la place

Si vos ISO sont déjà dans un autre emplacement sur votre serveur, il est possible d'effectuer des liens symbolique afin d'éviter les doublons.

ln -s /home/user/mon_iso.iso /var/lib/tftpboot/mon_iso.iso

Il est aussi faisable d'automatiser le montage d'ISO au démarrage pour les ISO qui doivent être décompressées. Il suffit d'automatiser toutes les commandes "mount -o loop" qui sont nécessaires. Par exemple avec une tâche cron @reboot : cron (il est préférable de lancer un script contenant toutes les commandes mount)

Ne pas utiliser de lien symbolique à l'intérieur du partage samba. Ils ne seront pas utilisable par le client !

Il est en revanche possible d'en utiliser avant le point de montage du partage.

Bugs connus

Ubuntu Server 18.04.1

Si Ubuntu Server 18.04.1 n'arrive pas a ce lancer (il s'arrête en mode maintenance), rajouter "systemd.mask=tmp.mount" entre "ip=dhcp" et "–"

Source : https://bugs.launchpad.net/ubuntu/+source/casper/+bug/1754777#yui_3_10_3_1_1557065713426_342

Pas de réseau dans Windows PE

Si le retour de la commande ipconfig ne donne rien, alors c'est qu'il n'y a pas le pilote réseau adéquat pour votre carte réseau. Rechercher son pilote chez le constructeur de votre carte réseau, et, intégrez ce pilote lors de la construction de WinPE. (voir paragraphe : Créer un WinPE sous windows)

Site officiel de iPXE

Contributeur

nicolas84

  • ipxe.txt
  • Dernière modification: Le 13/06/2019, 14:44
  • par 193.108.197.178