PXE es una extensión de DHCP, y sus creadores lo hicieron compatible con redes que ya disponían de un servicio DHCP implementado, para que fuese posible tener los servicios separados y sin interferencias entre ellos.
En ese caso, el servidor PXE es en realidad un proxy del servicio DHCP, que añade la funcionalidad PXE pero no realiza la asignación de direcciones IP.
Para implementar este servicio como proxy de DHCP, usaremos dnsmasq, que es una herramienta Linux que combina un servidor DNS, un servidor DHCP y un servidor TFTP; de estos servicios, al menos los dos últimos son necesarios.
El ordenador que vamos a utilizar tiene instalado un Ubuntu 18.04 y, para comenzar, instalaremos los siguientes paquetes:
user@localhost:~$ sudo apt install dnsmasq pxelinux syslinux-common
Una vez instalados estos paquetes, procedemos a configurar el servicio DHCP de dnsmasq:
user@localhost:~$ sudo service dnsmasq stop
user@localhost:~$ sudo nano /etc/dnsmasq.conf
Copiamos lo siguiente en el archivo de configuración:
# Inhabilitamos el servidor DNS port=0 # Habilitamos el log del servidor DHCP log-dhcp # Respondemos a las peticiones PXE en la red indicada; # corre como un proxy DHCP dhcp-range=192.168.24.0,proxy dhcp-boot=pxelinux.0 # Anunciamos el servicio PXE "Arranque por red". pxe-service=x86PC,"Arranque por red",pxelinux # Habilitamos el servidor TFTP enable-tftp tftp-root=/netboot/tftp/
Guardamos el archivo /etc/dnsmasq y modificamos el archivo /etc/default/dnsmasq:
user@localhost:~$ sudo nano /etc/default/dnsmasq
Añadiremos lo siguiente al final del archivo:
DNSMASQ_EXCEPT=lo
Sin esta línea, el sistema operativo enviará todas las consultas al servicio DNS a través de dnsmasq; como el servicio DNS está deshabilitado, nuestras consultas no recibirían ninguna respuesta.
Archivos de arranque
Tras realizar la configuración del servicio PXE, vamos a modificar el sistema de archivos para que permita el acceso al arranque a través de la red; para ello, creamos una carpeta donde copiaremos los archivos de arranque, y el menú del servicio:
user@localhost:~$ sudo mkdir -p /netboot/tftp/pxelinux.cfg user@localhost:~$ sudo nano /netboot/tftp/pxelinux.cfg/default
Copiamos lo siguiente en el archivo default:
default vesamenu.c32 label install_1 menu label ^Instalar Ubuntu 18.04 menu default kernel ubuntu-18.04/vmlinuz append initrd=ubuntu-18.04/initrd boot=casper netboot=nfs nfsroot=192.168.24.2:/netboot/nfs/ubuntu-18.04/ splash toram --- label install_2 menu label ^Instalar Ubuntu 18.04 desde internet kernel net-install-18.04/linux append vga=788 initrd=net-install-18.04/initrd.gz locale=es_ES.UTF-8 keyboard-configuration/layoutcode=es hostname=ubuntu-1804 label boot_1 menu label ^Iniciar Ubuntu 18.04 kernel boot/vmlinuz append initrd=boot/initrd nfsroot=192.168.24.2:/home/nfsroot ip=dhcp rw
Ahora nuestro servicio PXE ofrece un menú al cliente para que se realice una de varias posibles acciones: arrancar por red o instalar por red.
NOTA: Durante el arranque del cliente, éste envía su UUID y su dirección MAC al servidor PXE para que busque la configuración apropiada; si no la encuentra, entonces usará la configuración del archivo default.
Los archivos de configuración se buscan en un orden determinado:
-
Se busca un archivo con nombre como el UUID del cliente, todo en minúsculas.
-
Si no lo encuentra, buscará uno con nombre igual al tipo de hardware + dirección MAC.
-
Si tampoco encuentra este, buscará uno como la dirección IP del cliente en formato hexadecimal.
-
Por ultimo, intentará encontrar archivos de configuración para las subredes IP en formato hexadecimal.
-
Cuando no encuentra ningún archivo como los descritos, intentará cargar uno con nombre default.
Copiamos los archivos necesarios para que funcione el menú:
user@localhost:~$ sudo cp -v /usr/lib/syslinux/modules/bios/{ldlinux.c32,libcom32.c32,libutil.c32,vesamenu.c32} /netboot/tftp
Una vez copiados estos archivos, el sistema puede arrancar el proceso de instalación por red.
Instalación local
Descargamos un archivos de instalación desde la red, y la copiamos en la carpeta compartida; también copiamos los archivos de arranque de casper y otorgamos permisos:
user@localhost:~$ sudo mount -o loop ubuntu-18.04.05-desktop-amd64.iso /mnt user@localhost:~$ sudo cp -Rfv /mnt/* /netboot/nfs/ubuntu-18.04 user@localhost:~$ sudo cp -v /netboot/nfs/ubuntu-18.04/casper/{vmlinuz,initrd} /netboot/tftp/ubuntu-18.04 user@localhost:~$ sudo chmod -Rfv 777 /netboot
Editamos ahora el archivo /etc/exports para compartir las carpetas de red:
user@localhost:~$ sudo nano /etc/exports
Copiamos lo siguiente dentro del archivo:
## Entradas del servidor PXE /netboot/nfs *(ro,sync,no_wdelay,insecure_locks,no_root_squash,insecure,no_subtree_check)
A continuación, publicamos la carpeta e iniciamos el servicio:
user@localhost:~$ sudo exportfs -rv user@localhost:~$ sudo service dnsmasq start
Instalación tipo netinstall
Veamos ahora como implementar una instalación desde internet.
Comenzaremos descargando un arranque netinstall del sistema, y a continuación copiaremos los archivos de arranque a una carpeta asociada al menú.
user@localhost:~$ wget http://http://archive.ubuntu.com/ubuntu/ubuntu/dists/bionic/main/installer-amd64/current/images/netboot/netboot.tar.gz user@localhost:~$ sudo mkdir -p /netboot/tftp/net-install-18.04 user@localhost:~$ sudo tar -xzv netboot.tar.gz --strip-components 3 -C /netboot/tftp/net-install-18.04 ./ubuntu-installer/amd64/{linux,initrd.gz} user@localhost:~$ sudo chmod -Rfv 777 /netboot/tftp/net-install-18.04
Y con esto ya tenemos la opción de instalar desde internet.
Arrancar un sistema sin discos
Hasta ahora tenemos implementadas las dos opciones "Instalar" del menú. Ahora vamos a implementar la opción de "Iniciar" un sistema Ubuntu 18.04 clonado del local. Para comenzar, creamos las carpetas necesarias:
user@localhost:~$ sudo mkdir -v /netboot/tftp/boot user@localhost:~$ sudo mkdir -v /home/nfsroot
Necesitamos un sistema Ubuntu 18.04 operativo y funcional para ser usado por todas las máquinas de la red. Hay que optar por una de estas alternativas:
-
debbootstrap: método usado en ocasiones para instalar el servidor Apache con chroot.
-
Copiar la instalación del servidor, que ya está operativa.
-
Hacer una instalación nueva en la máquina cliente, y copiarla al servidor.
Optamos en esta ocasión por la segunda opción, y comenzamos copiando los archivos de arranque:
user@localhost:~$ cp -v /boot/vmlinuz-`uname -r` /netboot/tftp/boot
Ahora vamos a crear el archivo initrd.img para ser utilizado en el arranque por red. Comenzamos editando el archivo /etc/initramfs-tools/initramfs.conf:
# BOOT: [ local | nfs ] # local - Inicia con los medios locales (disco, cd, usb, etc). # nfs - Inicia usando un disco NFS para / BOOT=nfs
A continuación, modificamos la configuración para que los módulos se carguen desde la red, y creamos la lista de módulos incluyendo sólo los que sean estrictamente necesarios:
# MODULES: [ most | netboot | dep | list ] # most - Añade todos los módulos que sean necesarios: framebuffer, acpi, filesystem, y controladores de disco. # dep - Prueba y determina cuales son los módulos a cargar. # netboot - Añade los módulos básicos y los de red, pero evita los dispositivos de bloque. # list - Sólo se incluyen los módulos de la lista 'additional modules'. MODULES=netboot
Comprobamos en el cliente cuales son los módulos de red necesarios, y añadimos la lista en /etc/initramfs-tools/modules:
user@client:~$ sudo lshw -C network *-network descripción: Ethernet interface producto: NetXtreme BCM5754 Gigabit Ethernet PCI Express fabricante: Broadcom Inc. and subsidiaries id físico: 0 información del bus: pci@0000:02:00.0 nombre lógico: enp2s0 versión: 02 serie: 00:18:8b:6e:bd:99 tamaño: 100Mbit/s capacidad: 1Gbit/s anchura: 64 bits reloj: 33MHz capacidades: pm vpd msi pciexpress bus_master cap_list ethernet physical tp 10bt 10bt-fd 100bt 100bt-fd 1000bt 1000bt-fd autonegotiation configuración: autonegotiation=on broadcast=yes driver=tg3 driverversion=3.137 duplex=full firmware=5754-v3.15 ip=192.168.1.36 latency=0 link=yes multicast=yes port=twisted pair speed=100Mbit/s recursos: irq:25 memoria:fe7f0000-fe7fffff
A la vista de esta información, copiaremos "enp2s0" en la lista de módulos. A continuación, creamos la imagen:
user@localhost:~$ sudo mkinitramfs -o /netboot/tftp/boot/initrd.img-`uname -r`
NOTA: Una vez creada la imagen en la carpeta de arranque, debemos dejar los archivos editados como estaban. En caso contrario, cuando se produzca una actualización del kernel y se cree una nueva imagen, el sistema dejará de arrancar.
Procedemos ahora a clonar la instalación de nuestro sistema, para usarla en los clientes de red:
user@localhost:~$ sudo rsync -auvz --exclude 'home' --exclude 'proc' --info=progress2 ../../ /home/nfsroot
Esto copiará todo el sistema a la carpeta /home/nfsroot.
Modificamos ahora la configuración de red del sistema de arranque, porque durante el proceso el servidor DHCP ya ha asignado una IP a la tarjeta de red y no queremos que accidentalmente se le asigne otra diferente al cargar el sistema.
Modificaremos el archivo /home/nfsroot/etc/network/interfaces para que nuestra tarjeta de red se configure de forma manual; esto impedirá la recarga de IP.
auto lo iface lo inet loopback iface eth0 inet manual
Modificaremos ahora el archivo /home/nfsroot/etc/fstab para retirar cualquier referencia a los dispositivos de bloque locales, dado que no estarán disponibles. Copiaremos lo siguiente:
/dev/nfs / nfs defaults 1 1 none /tmp tmpfs defaults 0 0 none /var/run tmpfs defaults 0 0 none /var/lock tmpfs defaults 0 0 none /var/tmp tmpfs defaults 0 0
¡Ni siquiera se puede usar swap!
Dado que los sistemas sin disco local no necesitan grub para arrancar, lo mejor es deshabilitar la actualización, editando el archivo /home/nfsroot/etc/kernel/postinst.d/zz-update-grub para comentar la línea exec.
Finalmente, editamos el archivo /etc/exports para compartir las carpetas necesarias para el arranque; copiaremos lo siguiente:
/home/nfsroot *(rw,no_root_squash,async,insecure)
Publicamos la carpeta:
user@localhost:~$ sudo exportfs -rv
Monitorizar
Si queremos visualizar lo que está ocurriendo con el servidor PXE, usamos el terminal:
user@localhost:~$ journalctl -efu dnsmasq sep 23 08:37:09 localhost systemd[1]: Starting dnsmasq - A lightweight DHCP and caching DNS server... sep 23 08:37:09 localhost dnsmasq[8617]: dnsmasq: sintaxis correcta. sep 23 08:37:09 localhost systemd[1]: Started dnsmasq - A lightweight DHCP and caching DNS server. sep 23 08:37:09 localhost dnsmasq[8626]: iniciado, versión 2.79 DNS desactivado sep 23 08:37:09 localhost dnsmasq[8626]: opciones al compilar: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth nettlehash DNSSEC loop-detect inotify sep 23 08:37:09 localhost dnsmasq-dhcp[8626]: DHCP, proxy on subnet 192.168.24.0 sep 23 08:37:09 localhost dnsmasq-tftp[8626]: TFTP root está /netboot/tftp sep 23 08:38:51 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/pxelinux.0 to 192.168.24.42 sep 23 08:38:51 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/ldlinux.c32 to 192.168.24.42 sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/9c9d68ae-4fd6-11da-b84d-000fb0bb1bd5 no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/01-00-0f-b0-bb-1b-d5 no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/C0A8182A no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/C0A8182 no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/C0A818 no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/C0A81 no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/C0A8 no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/C0A no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/C0 no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: archivo /netboot/tftp/pxelinux.cfg/C no encontrado sep 23 08:38:51 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/pxelinux.cfg/default to 192.168.24.42 sep 23 08:38:51 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/vesamenu.c32 to 192.168.24.42 sep 23 08:38:51 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/libcom32.c32 to 192.168.24.42 sep 23 08:38:51 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/libutil.c32 to 192.168.24.42 sep 23 08:38:51 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/pxelinux.cfg/default to 192.168.24.42 sep 23 08:42:47 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/netinstall-18.04/linux to 192.168.24.42 sep 23 08:42:59 localhost dnsmasq-tftp[8626]: sent /netboot/tftp/netinstall-18.04/initrd.gz to 192.168.24.42 sep 23 08:43:51 localhost dnsmasq-dhcp[8626]: 2533296700 available DHCP subnet: 192.168.24.0/255.255.255.0 sep 23 08:43:51 localhost dnsmasq-dhcp[8626]: 2533296700 vendor class: d-i sep 23 08:43:51 localhost dnsmasq-dhcp[8626]: 2533296700 available DHCP subnet: 192.168.24.0/255.255.255.0 sep 23 08:43:51 localhost dnsmasq-dhcp[8626]: 2533296700 vendor class: d-i sep 23 08:48:25 localhost dnsmasq-dhcp[8626]: 568859713 available DHCP subnet: 192.168.24.0/255.255.255.0 sep 23 08:48:25 localhost dnsmasq-dhcp[8626]: 568859713 vendor class: "" sep 23 08:58:26 localhost dnsmasq-dhcp[8626]: 568859713 available DHCP subnet: 192.168.24.0/255.255.255.0 sep 23 08:58:26 localhost dnsmasq-dhcp[8626]: 568859713 vendor class: ""
Y esto, más o menos, es todo por hoy.