Сервер сетевой загрузки iPXE

iPXE — это реализация клиентского программного обеспечения Preboot eXecution Environment (PXE) и загрузчика с открытым исходным кодом, созданная в 2010 году как ответвление gPXE. Позволяет запустить и/или установить ОС (Linux, Windows и прочее.) на компьютере с помощью сетевого подключения к выделенному серверу.

Для удачной загрузки компьютер должен поддерживать загрузку по сети (настраивается в bios системной платы).

На сервер будет установлено:

  1. Служба DNS — необязательная, но очень полезная служба, чтобы писать вместо ip имя. Инструкция в статье Сервер dns на debian
  2. Служба DHCP — будет выдавать настройки сети + информацию о том где искать загрузочные файлы и какой из них запускать первым (isc-dhcp-server). Инструкция в статье Сервер dhcp на debian
  3. Служба TFTP — будет раздавать загрузочные файлы на начальном этапе (tftpd-hpa).
  4. Cлужба доступа к файлам — будет раздавать файлы на поздних этапах по протоколам SMB, NBD, HTTP, NFS и пр.
  5. Дополнительные файлы для сборки пакетов.
Система: Debian 11
Подсеть: 10.5.5.0/24
IP адрес сервера: 10.5.5.5
Имя сервера: srv
Домен: lct.loc

Начальную настройку сервера можно сделать по инструкции из статьи: Начальная настройка сервера debian

Служба TFTP

Устанавливаем tftpd-hpa — ТFTP сервер с поддержкой специфичных требований к PXE. Позволяет работать с идеологией именования файлов от Microsoft

sudo apt install tftpd-hpa

Во время установки указываем путь к корневому каталогу с загрузочными файлами. Например /srv/pxe/

Теперь необходимо настроить сервер tftp. Файл настроек находится в /etc/default/tftpd-hpa

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

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/pxe"
TFTP_ADDRESS="10.5.5.5:69"
TFTP_OPTIONS="-4 -s -m /srv/pxe/images/winxp/tftpd.rules -vvv"
  • TFTP_USERNAME — имя пользователя, от которого будет работать tftp сервер. Не изменяем
  • TFTP_DIRECTORY — директория, из которой tftp будет отдавать файлы
  • TFTP_ADDRESS — ip адресс и порт, на котором tftp сервер будет слушать запросы (0.0.0.0 — на всех адресах) 
  • TFTP_OPTIONS — опции tftp сервера, -4 работает только с ipv4, -vvv подробный лог работы tftp сервера (можно уменьшить количество букв v), tftpd.rules файл с правилами, который меняет windows слэш «\» на нормальный «/». Расположение файла может быть любое.

Создадим файл правил tftp сервера

sudo nano /srv/pxe/images/winxp/tftpd.rules
r ntldr /images/winxp/ntldr
r ntdetect.com /images/winxp/ntdetect.com
r winnt.sif /images/winxp/winnt.sif
r BOOTFONT.BIN /images/winxp/BOOTFONT.BIN

rg \\ /
# Переводим имена запрашиваемых файлов в нижний регистр
r .* \L\0

r winxp/distrib/i386 /images/winxp/distrib/i386

Служба Samba

Установка службы samba для передачи файлов по протоколу smb

sudo apt install samba

Настройки службы хранятся в файле /etc/samba/smb.conf

sudo nano /etc/samba/smb.conf
[global]
        load printers = no
        deadtime = 10
        os level = 20
        printing = bsd
        server string = "srv file server"
        passdb backend = tdbsam
        netbios name = share
        security = user
        hosts allow = 10.5.5.0/24 127.0.0.0/8
        interfaces = 10.5.5.5
        printcap name = /dev/null
        log file = /var/log/samba/log.%m
        name resolve order = host lmhosts wins bcast
        socket address = 10.5.5.5
        workgroup = lct
        map to guest = bad user
        syslog = 0
        bind interfaces only = no
        client min protocol = NT1
        client max protocol = SMB3
        server min protocol = NT1

[images]
        wide links = no
        path = /srv/pxe/images
        allow hosts = 10.5.5.0/24
        browseable = no
        public = yes

Служба NFS

Установка nfs сервера

sudo apt install nfs-kernel-server

Настройки хранятся в файле /etc/exports

sudo nano /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#
/srv/pxe        10.5.5.0/24(ro)

Служба HTTP

Установим http сервер nginx

sudo apt install nginx

Основной файл настроек nginx находится в /etc/nginx/nginx.conf

sudo nano /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 1024;
    use epoll;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    types_hash_max_size 2048;
    server_tokens off;
    client_header_timeout 30;
    client_body_timeout 30;
    reset_timedout_connection on;
    client_max_body_size 32m;
    client_body_buffer_size 128k;
    keepalive_timeout  30;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    ##
    # Logging Settings
    ##

    log_format  main    '$remote_addr - $remote_user [$time_local] "$request" '
          '$status $body_bytes_sent "$http_referer" '
          '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;

    gzip_disable "msie6";
    gzip_proxied any;
    gzip_min_length 1024;
    gzip_comp_level 4;
    gzip_types text/plain text/css application/json application/jаvascript application/x-jаvascript text/xml application/xml application/xml+rss text/jаvascript application/atom+xml application/rdf+xml;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

В папке /etc/nginx/sites-enabled/ удалим ссылку на сайт по-умолчанию

sudo rm /etc/nginx/sites-enabled/default

В папке /etc/nginx/sites-available/ создадим файл конфигурации своего сайта

sudo nano /etc/nginx/sites-available/srv.lct.loc.conf
server {
  listen 80 default;

  server_name srv.lct.loc;
  charset utf-8;

  root /srv/pxe;
  index index.html index.htm index.php;

  access_log /var/log/nginx/srv.lct.loc_access.log;
  error_log /var/log/nginx/srv.lct.loc_error.log;

  include /etc/nginx/templates/autoindex.conf;
}

server {

  listen 80;

  server_name www.srv.lct.loc;
  rewrite ^(.*) http://srv.lct.loc$1 permanent;
}

Создадим папку для шаблонов web сервера

sudo mkdir /etc/nginx/templates

Создадим файл для отображения содержимого папки pxe сервера на сайте

sudo nano /etc/nginx/templates/autoindex.conf
location / {
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
}

Включим сайт, создав ссылку в папке /etc/nginx/sites-enabled/

sudo ln -s /etc/nginx/sites-available/srv.lct.loc.conf /etc/nginx/sites-enabled/

Загрузчик iPXE

Установка зависимостей для сборки загрузчиков iPXE

sudo apt install gcc binutils make perl liblzma-dev mtools git

Копирование репозитория iPXE

git clone git://git.ipxe.org/ipxe.git

Далее необходимо перейти в папку с исходниками и отредактировать некоторые файлы

cd ipxe/src/
  • в файле config/gereral.h раскомментировать строки с CONSOLE_CMDIMAGE_PNG
  • в файле config/console.h раскомментировать строку с CONSOLE_FRAMEBUFFER

После загрузки iPXE от DHCP появится приглашение командной строки iPXE. Чтобы не вводить команды вручную, можно встроить скрипт в сам бинарник.

Создаем скрипт start.ipxe

nano start.ipxe
#!ipxe
:start
# Механизм получения ip. В случае ошибки - предлагает нажать "s" для запуска командной строки.
# Иначе - начать снова.
dhcp && goto next || prompt --key s --timeout 1500 Press "s" for the iPXE command line... && shell || goto start
:next
# Случае успеха - загрузить "меню" с tftp-сервера (о нём - позже).
chain tftp://10.0.2.5/boot.ipxe

Сборка загрузчиков

Внимание! Строка имени файла является и его целевой конфигурацией, т.е. какое имя будет выбрано, для той платформы и будет сборка. В ключе EMBED= указывается имя ранее созданного скрипта.

Так же в случае ошибок при сборке, необходимо добавить ключ -fno-pie в Makefile.housekeeping на 451 строке. Предполагается, что это из-за ошибок в gcc.

make bin-i386-efi/ipxe.efi EMBED=start.ipxe
make bin-i386-pcbios/undionly.kpxe EMBED=start.ipxe

Копируем полученные загрузчики в папку tftp PXE сервера

cp bin-i386-efi/ipxe.efi /srv/pxe/
cp bin-i386-pcbios/undionly.kpxe /srv/pxe/

Меню загрузки

Ранее, в загрузчики был встроен скрипт, который в случае успешного получения ip, загружал и запускал скрипт boot.ipxe.

Теперь создадим файл boot.ipxe

sudo nano /srv/pxe/boot.ipxe
#!ipxe
# Глобальные параметры
set http-server http://srv.lct.loc:80

set nfs-server 10.5.5.5
set nfs-root /srv/pxe/images/
set boot-nfs-url nfs://${nfs-server}${nfs-root}

set menu-timeout 15000 # таймаут выхода из меню

goto next || goto cancel

:cancel
echo You change "Exit". Boot from disk...
sleep 1
exit

:next
chain --replace --autofree menu.ipxe

Следующим, если все хорошо, то будет загружаться файл menu.ipxe. Он содержит меню загружаемых утилит и операционных систем. Создадим файл menu.ipxe

sudo nano /srv/pxe/menu.ipxe
#!ipxe

######## Графика ########

#Pair index    Usage                   Foreground colour index        Background colour index
#0           Default colour               9 (default: white)          9 (default: black or transparent)
#1           Normal user interface text   7 (white)                   4 (blue or transparent)
#2           Highlighted text             7 (white)                   1 (red)
#3           Separators                   6 (cyan)                    4 (blue or transparent)
#4           Editable text                0 (black)                   6 (cyan)
#5           Error messages               7 (white)                   1 (red)
#6           Help URLs                    6 (cyan)                    4 (blue or transparent)
#7           PXE menu selection           0 (black)                   7 (white)

# Цвет по-умолчанию (индекс 0)
cpair -f 6 -b 9 0

# Нормальный текст (индекс 1)
cpair -f 9 -b 9 1

# Разделители (индекс 3)
cpair -f 6 -b 9 3

# Строка выбора (индекс 2)
colour --basic 2 7
cpair -f 7 -b 9 2

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

# Main menu
:start
menu                Welcome to iPXE Boot Menu (${platform})
item
item --gap -- ---------------- Boot menu ----------------
item exit           Exit iPXE and continue BIOS boot
item pxeboot        Boot old pxe menu
item grldr          Boot old GRUB menu
item
item --gap -- ---------------- Tools and utilities ----------------
item menu-diag      Diagnostics tools...
item menu-liveos    Live OS...
item menu-install   Installers...
item
item --gap -- ---------------- Advanced options ----------------
item shell          Enter iPXE shell
item config         Enter iPXE config
item reboot         Reboot computer
item poweroff       Shutdown computer
echo                Boot iPXE by root.by - https://4srv.by
choose --default exit target && goto ${target} || goto cancelled

Это часть моего файла menu.ipxe. Чтобы все заработало нужно много чего дописывать. Если статья будет интересна и полезна, тогда напишу новую про наполнение pxe сервера.

Теперь, когда все настроено, необходимо перезагрузить все наши службы. Можно такой командой

sudo systemctl restart bind9 isc-dhcp-server tftpd-hpa smbd nmbd nfs-server nginx

Статус служб можно узнать введя команду

sudo systemctl status bind9 isc-dhcp-server tftpd-hpa smbd nmbd nfs-server nginx

На этом все. Надеюсь статья будет понятной и полезной. Всем добра и успехов!