Trucchi con PXE
Questi sono brevi appunti per il seminario di Giovanni Mascellani al Linux Day 2014 di Pisa. Si tratta di appunti, non di istruzioni complete. In particolare non forniscono una panoramica completa sui potenziali problemi di sicurezza che nascono in un setup di questo tipo. Chi utilizza questi appunti lo fa sulla propria responsabilità ed è caldamente invitato a consultare la documentazione di supporto dei programmi utilizzati. In altre parole, se fai quello che c’è scritto qui dentro senza capire cosa significa, corri seri rischi di fare qualche disastro. Anche perché poi è probabile che in questi appunti ci siano degli errori. Se capite cosa state facendo potete sistemarli da voi.
Queste istruzioni assumono che si stia lavorando su sistemi Debian/Ubuntu. In linea di principio le stesse cose possono essere fatte su ogni sistema Linux, però alcuni dettagli tecnici potrebbero cambiare.
Questo documento è stato finito il 25 ottobre 2014. Per contattare l’autore: gio@debian.org.
Installazione dei pacchetti
Su Debian installare: atftpd
, debootstrap
, isc-dhcp-server
, nfs-kernel-server
, syslinux-common
. A partire da Debian jessie bisogna anche installare pxelinux
.
Aprire il firewall
È necessario configurare il firewall per ricevere richieste TFTP, DHCP e NFS. TFTP usa la porta UDP numero 69. Per DHCP bisogna utilizzare configurazioni che dipendono dallo specifico motore di firewall utilizzato (consultare la documentazione). Per NFS la situazione è un po’ complicata: vedere le istruzioni sul wiki di Debian.
ACHTUNG!!
Mai tenere un servizio DHCP attivo sul proprio portatile! Si rischia di danneggiare le reti alle quali ci si collega (e di trovarsi davanti amministratori di rete molto arrabbiati)!
Se la rete sulla quale si vuole offrire il servizio di boot con PXE ha già un server DHCP, allora bisogna modificare le impostazioni di quel server (vedere sotto come fare). Due server DHCP sulla stessa rete significano (quasi sempre) grossi guai!
Creazione di un sistema di base
Usare il comando:
# debootstrap --arch=i386 jessie /srv/jessie
Questo installerà un sistema di base in /srv/jessie
. Ci vorrà un po’ per scaricare tutti i pacchetti e metterli a posto. Si può scegliere l’architettura amd64
se si è sicuri che il sistema verrà utilizzato solo su processori a 64 bit. Si possono ovviamente anche scegliere altre versioni di Debian e di Ubuntu. Si può opzionalmente anche specificare un mirror da utilizzare per scaricare i pacchetti:
# debootstrap --arch=i386 jessie /srv/jessie http://http.debian.net/debian/
Servire il sistema via NFS
Scrivere qualcosa del genere in /etc/exports
/srv/jessie *(ro,no_root_squash,async,subtree_check)
E poi ricaricare la configurazione di NFS con
# service nfs-kernel-server reload
Configurare la rete ed il server DHCP
Modificare la riga in /etc/default/isc-dhcp-server
:
INTERFACES="eth0"
Configurare un indirizzo statico sull’interfaccia di rete da usare (perché la configurazione diventi permanente bisogna replicarla in /etc/network/interfaces
, oppure utilizzare il proprio configuratore di rete di fiducia):
ip addr add dev eth0 192.168.1.1/24
Scrivere la configurazione del demone DHCP in /etc/dhcp/dhcpd.conf
:
authoritative;
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.10 192.168.1.100;
option routers 192.168.1.1;
option domain-name-servers 8.8.8.8;
next-server 192.168.1.1;
filename "pxelinux.0";
}
A seconda dei casi bisogna anche configurare il server per fare IP forwarding e masquerading, in modo da permettere al client DHCP di navigare su Internet.
Installare il kernel nel sistema di base (e configurare altre cose di base)
Il sistema di base creato per ora è senza kernel, quindi non può essere avviato dai client. Per installare il kernel bisogna prima entrare nel sistema con chroot
. Però bisogna anche montare i file system di appoggio come /proc
ed altri:
# cd /srv/jessie
# mount -o bind /proc /srv/jessie/proc
# mount -o bind /dev /srv/jessie/dev
# mount -o bind /sys /srv/jessie/sys
# chroot .
[ dentro il sistema nuovo ]
# apt-get update
# apt-get install linux-image-486
[ opzionalmente si possono anche installare e aggiornare altri pacchetti ]
# passwd
[ impostare un password per root ]
# echo "minion" > /etc/hostname
# exit
[ di nuovo nel sistema del server ]
# umount /srv/jessie/proc
# umount /srv/jessie/dev
# umount /srv/jessie/sys
(naturalmente a seconda dei casi bisogna installare la variante del kernel che si intende usare; la -486
è quella più conservativa, che funziona ovunque; in molti casi la -686-pae
andrà bene)
C’è un ultima cosa da fare: l’installazione del kernel creerà dei link a kernel e initrd nella directory /srv/tftp
. Per qualche strano motivo che non so, il link al kernel va bene, mentre invece quello all’initrd no (perché è assoluto invece che relativo; dall’interno della chroot è la stessa cosa, ma dall’esterno no). Bisogna quindi sistemarlo (e ricordarsi di sistemarlo di nuovo ogni volta che si installa un nuovo kernel):
cd /srv/jessie
rm initrd.img
ln -s boot/initrd.img-3.16-2-486 initrd.img
Installare Pxelinux
Copiare il file pxelinux.0
in /srv/tftp
. Il file si può trovare nel pacchetto syslinux-common
oppure pxelinux
, a seconda della versione di Debian/Ubuntu che si usa. Poi creare il file /srv/tftp/pxelinux.cfg/default
nel quale sta la configurazione di Pxelinux. La sintassi della configurazione ed il funzionamento del sistema sono praticamente identici a quella di Syslinux.
Creiamo una configurazione minimale. Copiamo anche il file menu.c32
(dal pacchetto syslinux-common
) in /srv/tftp
e mettiamo questo contenuto nel file /srv/tftp/pxelinux.cfg/default
:
prompt 0
timeout 50
menu title Boot menu
label jessie
menu label Debian jessie i386
kernel jessie/vmlinuz
append rw verbose ip=dhcp initrd=jessie/initrd.img root=/dev/nfs nfsroot=192.168.1.1:/srv/jessie vga=791 init=/lib/systemd/systemd
ui menu.c32
(se non volete usare systemd
dovete togliere il parametro init=...
, ma dovete anche assicurarvi che qualche altro sistema init sia installato; anche gli altri parametri richiedono di essere adattati alla situazione, in particolare l’indirizzo IP del server NFS; tutti i path che compaiono sono relativi a /srv/tftp
)
Bisogna poi creare la cartella /srv/tftp/jessie
e copiare (oppure mettere dei link simbolici) kernel e initrd del sistema guest:
cd /srv/tftp
mkdir jessie
cd jessie
ln -s ../../jessie/initrd.img
ln -s ../../jessie/vmlinuz
Configurare aufs
A questo punto è possibile fare il boot del nuovo sistema. Tuttavia se ci provate scoprirete che ci sono un sacco di problemi, perché il file system di root è montato in sola lettura (e NFS è configurato per permettere solo la lettura, non la scrittura). Permettere la lettura a NFS sarebbe una pessima idea, perché diversi computer interferirebbero malamente tra di loro. Bisogna fare in modo che ogni volta che il computer si avvia monti sopra il livello NFS in sola lettura un altro livello che sta interamente in RAM e che è in lettura-scrittura. Tutte le modifiche fatte a questo livello verranno perse ogni volta che il computer viene riavviato. Questo permette di avere un sistema pulito ogni volta che si riavvia il computer!
Creare due file con il seguente contenuto:
/srv/jessie/etc/initramfs-tools/scripts/init-bottom/aufsroot
#!/bin/sh
PREREQ=''
prereqs() {
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
# Boot normally when the user selects single user mode.
if grep single /proc/cmdline >/dev/null; then
exit 0
fi
ro_mount_point="${rootmnt%/}.ro"
rw_mount_point="${rootmnt%/}.rw"
# Create mount points for the read-only and read/write layers:
mkdir "${ro_mount_point}" "${rw_mount_point}"
# Move the already-mounted root filesystem to the ro mount point:
mount --move "${rootmnt}" "${ro_mount_point}"
# Mount the read/write filesystem:
mount -t tmpfs root.rw "${rw_mount_point}"
# Mount the union:
mount -t aufs -o "dirs=${rw_mount_point}=rw:${ro_mount_point}=ro" root.union "${rootmnt}"
# Correct the permissions of /:
chmod 755 "${rootmnt}"
# Make sure the individual ro and rw mounts are accessible from within the root
# once the union is assumed as /. This makes it possible to access the
# component filesystems individually.
mkdir "${rootmnt}/ro" "${rootmnt}/rw"
mount --move "${ro_mount_point}" "${rootmnt}/ro"
mount --move "${rw_mount_point}" "${rootmnt}/rw"
/srv/jessie/etc/initramfs-tools/hooks/aufsroot
#!/bin/sh
PREREQ=''
prereqs() {
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
manual_add_modules aufs
manual_add_modules tmpfs
copy_exec /bin/chmod /bin
Poi renderli entrambi eseguibili:
chmod 755 /srv/jessie/etc/initramfs-tools/scripts/init-bottom/aufsroot
chmod 755 /srv/jessie/etc/initramfs-tools/hooks/aufsroot
Inoltre bisogna ricompilare l’initrd. Serve quindi entrare nel sistema guest come indicato sopra (quando si è installato il kernel) e all’interno del sistema guest dare il comando:
update-initramfs -k all -u
A questo punto il sistema PXE partirà perfettamente!
Altre cose utili da fare nel sistema guest
Il sistema di base è veramente di base! Per avere un po’ di supporto in più si possono fare le seguenti cose (sempre da eseguire dentro il sistema con chroot
come indicato sopra).
# apt-get install locales
# dpkg-reconfigure locales
[ configurare opportunamente i locales ]
# dpkg-reconfigure tzdata
[ configurare opportunamente il fuso orario ]
# apt-get install aptitude vim less ntp dbus
# adduser utente
[ configurare opportunamente l'utente ]
# apt-get install xfce4
Montare una cartella home scrivibile dagli utenti
Per ora tutte le modifiche fatte al sistema (per esempio, i file utilizzati dagli utenti nelle loro directory home) vengono perse ad ogni riavvio. Per evitare questo problema bisogna montare le home in lettura-scrittura via NFS. Per fare questo bisogna creare una cartella per le home:
# mkdir /srv/home
ed aggiungere a /etc/export
:
/srv/home 192.168.1.0/24(rw,root_squash,async,subtree_check)
Poi bisogna montare il volume all’avvio. Scriviamo in /srv/jessie/etc/fstab
:
192.168.1.1:/srv/home /home nfs hard,nointr 0 0
(ovviamente bisogna anche creare le singole home dei vari utenti, con i permessi giusti. Occhio, perché gli UID e GID numerici devono essere quelli del sistema guest, non quelli del sistema host!).
Con il patrocinio di:
Provincia |
Comune |
Comune |
Comune di |
Comune di |
Comune di |
Fondazione Toscana |
Università |
Wikimedia |