7.6.3.1. Servidor de ficheros

Comenzaremos por preparar el servidor con los ficheros necesarios para la descarga. Lo más aconsejable es montar tanto un servidor TFTP para descargar el NBP como un servidor HTTP para descargar el resto.

7.6.3.1.1. Estructura

La estructura de ficheros en nuestro disco será esta:

+-- /srv/tftp
       |
       +--- bios
       |     |
       |     +--- lpxelinux.0
       |     +--- syslinux
       |             |
       |             +--- ldlinux.c32
       |             +--- menu.c32
       |             +--- reboot.c32
       |             +--- ... otros módulos ...
       |
       +--- ssoo
       |     |
       |     + memtest86+.bin
       |     + slitaz
       |     |   |
       |     |   +--- bzImage
       |     |   +--- rootfs.gz
       |     |
       |     + ... un directorio por cada sistema arrancable ...
       |
       |
       +--- cfg
       |     |
       |     +--- boot.php
       |
       +--- efi32  (misma estructura que bios)
       +--- efi64  (misma estrctura que bios)

Esto es:

  • Un directorio /srv/tftp que compartiremos mediante los servicios TFTP y HTTP.

  • Un subdirectio bios en el que se almacenarán todos los ficheros que necesite syslinux para hacer su labor. Estos ficheros son los apropiados cuando tenemos una BIOS y no una UEFI.

  • Los subdirectorios efi32 y efi64 contienen las versiones correspondientes de los ficheros de syslinux. Téngase en cuenta que en estos dos casos el NBP no se llama lpxelinux.0 sino syslinux.efi.

  • Un subdirectorio llamado cfg que contendrá los ficheros de configuración de syslinux que permitirán la selección del sistema.

Los ficheros podemos obtenerlos de los siguientes paquetes:

syslinux-common

Contiene los módulos de syslinux necesarios incluidos en los subdirectorios bios, efi32 y efi64.

pxelinux

Contiene el ejecutable lpxelinux.0 del subdirectorio bios.

syslinux-efi

Contiene los ejecutables syslinux.efi de los subdirectorios efi32 y efi64.

memtest86+

Contiene el ejecutable memtest86+.bin.

En consecuencia:

# apt install syslinux-{common,efi} pxelinux memtest86+

Para crear la estructura de directorios podemos ejecutar:

# mkdir -p /srv/tftp/{{bios,efi32,efi64}/{syslinux,pxelinux.cfg},ssoo,cfg}

Para incluir los ficheros que proporcionan estos paquetes en nuestra estructura, basta con hacer enlaces simbólicos. Por ejemplo:

# ln -s /usr/lib/PXELINUX/lpxelinux.0 /srv/tftp/bios/

Nuestra estrategia para las descargas es la siguiente:

  1. El cliente PXE descargará por TFTP el NBP correspondiente (lpxelinux.0 en arquitecturas con BIOS).

  1. El NBP ya es capaz de descargar por HTTP, pero ello exige enviar al cliente la opción DHCP 210, que en dnsmasq se haría del siguiente modo:

    dhcp-option-force=210,http://192.168.255.1/boot/bios/
    

    o, mejor aún, encapsulándola en la opción 43:

    dhcp-option=encap:43,210,http://192.168.255.1/boot/bios/
    
  2. A partir de ahora los módulos y las configuraciones se descargarán por HTTP y ya explicaremos al llegar a él qué estrategia seguimos.

Advertencia

Aunque la estructura se ha creado para poder soportar el arranque tanto desde BIOS como desde UEFI las explicaciones sobre el servicio PXE se ceñirán a dar soporte sólo a la primera arquitectura. Ahora bien, al final, como particularidad, se explicará como hacer que el servicio PXE sea capaz de soportar las tres arquitecturas.

Nota

Si decidimos prescindir de un servidor HTTP y realizar todas las descargas TFTP es obvio que necesitaremos incluir dentro de la estructura de directorios del servidor TFTP un fichero de configuración para syslinux:

+-- /srv/tftp
       |
       +--- bios
       |     |
       |     +--- lpxelinux.0
       |     +--- syslinux
       |     |       |
       |     |       +--- ... modulos ...
       |     |
       |     +--- pxelinux.cfg
       |             |
       |             +--- default
       |
       +--- ssoo (estructura referida más arriba)
       +--- efi32 (misma estructura que bios)
       +--- efi64 (misma estructura que bios)

7.6.3.1.2. TFTP

Habilitar el servicio es sumamente sencillo, si pensamos usar dnsmasq en el primer escenario (en el segundo y tercero es obligatorio su uso), porque incluye un servidor que puede habilitarse, simplemente, con:

enable-tftp
tftp-root=/srv/tftp

En cambio, si en el primer escenario usamos el servidor del ISC tendremos que instalar un servidor aparte. El más simple es el que proporciona el paquete tftpd, pero tiene dos inconvenientes:

  • Sólo está preparado para usarse con inetd.

  • No soporta descargas de más de 32MB, lo cual es un incoveniente si no pensamos montar un servidor HTTP.

Por tanto, instalaremos atftp:

# apt-get --no-install-recommends install atftpd

para cuya configuración basta con editar el fichero de configuración /etc/default/atftpd y evitar que se use inetd:

USE_INETD=false

Podremos ver, además, que la configuración ya viene preparada para compartir el contenido de /srv/tftp, que es lo que pretendemos.

7.6.3.1.3. HTTP

Nota

Utilizaremos nginx como servidor HTTP.

Al tratar los ficheros que serviremos, redefinimos el directorio de trabajo como:

http://192.168.255.1/boot/bios/

y esto requiere algunas puntualizaciomes. Mirando la estructura de ficheros, está claro que el directorio que queremos hacer accesible a través de HTTP es /srv/tftp. Que este directorio sea accesible mediante la dirección http://192.168.255.1/boot/ es, sin embargo, discutible. Una solución alternativa sería hacer accesible el directorio a través de la dirección http://boot/, pero tal cosa exigiría configurar un servidor DNS que permitiera resolver el nombre boot.aula.ies a la dirección IP.

Seguiremos el camino preestablecido y en las particularidades veremos cómo rematar la configuración haciendo uso de un nombre. El fichero de configuración para nginx es el siguiente:

# Configuración dinámica (PHP)

server {
   listen 80;
   server_name 192.168.255.1;

   try_files $uri $uri/ =404;
   error_page 403 =404 /404.html;

   location /boot {
      alias /srv/tftp;

      # Sólo acceso local
      allow 10.0.0.0/8;
      allow 172.16.0.0/12;
      allow 192.168.0.0/16;
      deny  all;

      # Convertimos la petición http://IP/boot/bios/pxelinux.cfg/01-MAC-DE-LA-TARJETA
      # en http://IP/boot/cfg/boot.php?mac=MAC-DE-LA-TARJETA&arch=bios
      rewrite "([^/]+)/pxelinux.cfg/01-(?i)((?:[0-9a-f]{2}-){5}[0-9a-f]{2})$" /boot/cfg/boot.php?arch=$1&mac=$2 last;

      # Para que no se hagan varios intentos al cargar módulos.
      if (!-e $request_filename) {
         rewrite "^(.*)/([^/]+\.c32)$" $1/syslinux/$2 last;
      }

      location ~ "^/boot/cfg/.+\.php$" {
         include snippets/fastcgi-php.conf;
         fastcgi_pass php;
         fastcgi_param SCRIPT_FILENAME $request_filename;
      }
   }
}

Un vistazo al fichero de configuración descubre nuestra industria: en principio, al cargar por segunda vez el NBP redefinimos el directorio de trabajo simplemente para cambiar de protocolo, pero nada más. Por tanto, éste seguirá buscando la configuración probando los mismos ficheros. La consecuencia es que volveríamos a leer el mismo pxelinux.cfg/default y se entraría en un bucle infinito. Sin embargo, la línea resaltada captura la petición del fichero cuyo nombre coincide con la MAC de la tarjeta, que es anterior, y posibilita que se ejecute el script de PHP cfg/boot.php haciéndole accesibles a través de los argumentos la propia MAC y la arquitectura de arranque. Como en el script se puede preguntar por la IP del cliente, podemos usar estos tres datos para particularizar la configuración.

Si no tenemos propósito de hacer configuraciones dinámicas, podemos simplificar un poco:

# Configuración estática

server {
   listen 80;
   server_name 192.168.255.1;

   try_files $uri $uri/ =404;
   error_page 403 =404 /404.html;

   location /boot {
      alias /srv/tftp;

      # Sólo acceso local
      allow 10.0.0.0/8;
      allow 172.16.0.0/12;
      allow 192.168.0.0/16;
      deny  all;

      # Para que no se hagan varios intentos al cargar módulos.
      if (!-e $request_filename) {
         rewrite "^(.*)/([^/]+\.c32)$" $1/syslinux/$2 last;
      }

      location ~* "([^/]+)/pxelinux.cfg/01-(?i)((?:[0-9a-f]{2}-){5}[0-9a-f]{2})$" {
         alias /srv/tftp/cfg/default;
      }
   }
}

Por último, quedaría escribir cfg/boot.php o cfg/default según el caso, pero eso lo dejaremos para más adelante.