Встроенная раздача адресов в домашнем маршрутизаторе устраивает до первого нетипового требования: зафиксировать адрес за конкретной машиной, передать клиентам собственный сервер имён, выдать параметры для сетевой загрузки или просто понять, кто и когда получал адрес. Отдельная служба DHCP на Linux решает все четыре задачи и даёт журнал, которого в потребительском устройстве обычно нет. Разбираем установку, структуру конфигурации, резервирование адресов и типовые ошибки.

Зачем выносить раздачу адресов на отдельную службу

Потребительский маршрутизатор выдаёт адреса из ограниченного набора настроек: диапазон, срок аренды, шлюз и один-два сервера имён. Резервирование по MAC-адресу либо отсутствует, либо доступно для десятка устройств, а журнал выдачи не сохраняется.

Отдельная служба даёт полный набор возможностей: произвольное число резервирований, любые стандартные параметры, группы устройств с разными настройками, адрес для сетевой загрузки и подробный журнал. Дополнительно она снимает зависимость от прошивки маршрутизатора: при замене устройства схема адресации сохраняется.

Расплатой становится необходимость следить за единственностью источника. Два сервера DHCP в одном сегменте приводят к тому, что клиенты получают параметры от того, кто ответил первым, и картина становится непредсказуемой. Поэтому перед включением собственной службы раздачу на маршрутизаторе отключают либо переводят её в непересекающийся диапазон, а лучше полностью выключают.

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

sudo dhclient -v -1 eth1
cat /var/lib/dhcp/dhclient.leases

Установка службы и базовая структура конфигурации

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

sudo apt install isc-dhcp-server

Список интерфейсов задают в файле параметров службы либо в отдельном конфигурационном файле, в зависимости от дистрибутива.

# /etc/default/isc-dhcp-server
INTERFACESv4="eth0"
INTERFACESv6=""

Основная конфигурация описывает подсеть, диапазон выдаваемых адресов и параметры, которые получают клиенты.

# /etc/dhcp/dhcpd.conf
authoritative;
default-lease-time 3600;
max-lease-time 86400;
log-facility local7;

subnet 192.168.10.0 netmask 255.255.255.0 {
    range 192.168.10.100 192.168.10.200;
    option routers 192.168.10.1;
    option domain-name-servers 192.168.10.5;
    option domain-name "lan.example";
    option broadcast-address 192.168.10.255;
    option ntp-servers 192.168.10.5;
}

Директива authoritative указывает, что служба считает себя ответственной за эту сеть, и это влияет на поведение при получении запроса об освобождении адреса для неизвестной ей подсети. Без неё сервер ведёт себя осторожно и может не отвечать в ряде случаев, поэтому для единственного источника в сегменте директиву оставляют.

Диапазон стоит выбирать так, чтобы он не пересекался с адресами, заданными вручную. Адреса вне диапазона остаются свободными для статической настройки, и это проще, чем искать конфликт потом.

Срок аренды определяет, как часто клиент обращается за продлением. Короткий срок полезен в сетях с большим потоком случайных устройств, длинный снижает нагрузку и делает адреса устойчивее. Для домашней сети подходит час, для офиса с постоянным набором устройств день и больше.

sudo systemctl restart isc-dhcp-server
sudo systemctl status isc-dhcp-server --no-pager
sudo journalctl -u isc-dhcp-server -n 30 --no-pager

Резервирование адресов по MAC-адресу

Постоянное соответствие адреса устройству описывается блоком host. Такой блок может находиться как внутри описания подсети, так и на верхнем уровне конфигурации; во втором случае он применяется к любой подсети, где встретился указанный адрес.

host printer {
    hardware ethernet 00:11:22:33:44:55;
    fixed-address 192.168.10.30;
}

host nas {
    hardware ethernet aa:bb:cc:dd:ee:ff;
    fixed-address 192.168.10.40;
    option host-name "nas";
}

Имя блока служит только для читаемости конфигурации, на выдачу влияет пара из аппаратного адреса и фиксированного адреса. Зарезервированный адрес должен лежать внутри описанной подсети и вне диапазона динамической выдачи, иначе служба сообщит о конфликте при запуске.

Для групп устройств с одинаковыми параметрами применяют блоки group, внутри которых описывают общие настройки и список устройств.

group {
    option domain-name-servers 192.168.10.5, 1.1.1.1;
    default-lease-time 7200;

    host ws1 { hardware ethernet 00:11:22:33:44:01; fixed-address 192.168.10.51; }
    host ws2 { hardware ethernet 00:11:22:33:44:02; fixed-address 192.168.10.52; }
}

Отдельный механизм позволяет ограничить выдачу адресов только известными устройствами. При такой настройке случайные посетители сети останутся без адреса, что уместно в закрытой сети и неприемлемо в гостевой.

subnet 192.168.10.0 netmask 255.255.255.0 {
    range 192.168.10.100 192.168.10.200;
    deny unknown-clients;
}

Классификация клиентов даёт больше гибкости: можно выделить класс по содержимому запроса и назначить ему отдельный диапазон или набор параметров.

class "phones" {
    match if substring(option vendor-class-identifier, 0, 6) = "phone-";
}

Передача дополнительных параметров клиентам

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

    option routers 192.168.10.1;
    option domain-search "lan.example", "example.ru";
    next-server 192.168.10.5;
    option bootfile-name "undionly.kpxe";

Параметр next-server указывает адрес, с которого клиент забирает загрузочный файл, а bootfile-name задаёт его имя. Для разных типов прошивки имя файла различается, и выбор организуют через классы либо через проверку архитектуры клиента.

option arch code 93 = unsigned integer 16;

if option arch = 00:07 {
    option bootfile-name "ipxe.efi";
} else {
    option bootfile-name "undionly.kpxe";
}

Собственные параметры объявляют конструкцией option с числовым кодом и типом, после чего их можно использовать наравне со стандартными.

option local-config code 224 = text;
option local-config "http://192.168.10.5/config.json";

Коды с 224 по 254 отведены для локального использования и не конфликтуют со стандартными значениями. Такой приём применяют для передачи служебных сведений устройствам собственной разработки, которые понимают согласованный формат.

Проверить, что клиент действительно получает ожидаемый набор, удобно с тестовой машины.

sudo dhclient -v -1 eth1 2>&1 | grep -E 'option|address'

Обслуживание нескольких сегментов и ретрансляция запросов

Запросы DHCP распространяются широковещательно и не проходят через маршрутизатор, поэтому в сети из нескольких сегментов нужен посредник. Роль посредника выполняет либо маршрутизатор, либо отдельная служба на машине в нужном сегменте.

На маршрутизаторе задают адрес сервера DHCP для интерфейса, смотрящего в сегмент клиентов. В системах с интерфейсом командной строки это параметр помощника DHCP, в OpenWrt соответствующая настройка relay.

# пример на маршрутизаторе Cisco-подобного синтаксиса
interface vlan20
 ip address 192.168.20.1 255.255.255.0
 ip helper-address 192.168.10.5

Посредник преобразует широковещательный запрос в обычный пакет с адресом сервера и добавляет сведения об интерфейсе, через который запрос пришёл. Сервер использует эти сведения, чтобы выбрать правильное описание подсети.

Конфигурация сервера при этом содержит несколько блоков subnet, по одному на каждый сегмент, и в каждом указан свой диапазон и свой маршрут по умолчанию.

subnet 192.168.20.0 netmask 255.255.255.0 {
    range 192.168.20.100 192.168.20.200;
    option routers 192.168.20.1;
}

Если посредника нет, а сервер должен обслуживать сегмент напрямую, его подключают к этому сегменту вторым интерфейсом и указывают его в списке обслуживаемых.

Отдельно проверяют, что служба слушает нужные интерфейсы: при пустом списке служба завершает работу с сообщением об отсутствии интерфейсов, и это самая частая причина отказа после установки.

Файл аренд, журнал и типовые сбои

Выданные адреса и сроки аренды служба хранит в файле, который служит её памятью между перезапусками.

sudo grep -A6 'lease 192.168.10.120' /var/lib/dhcp/dhcpd.leases | tail -n 20
sudo journalctl -u isc-dhcp-server -f

Файл дописывается при каждом изменении и периодически переписывается заново, поэтому в нём встречаются устаревшие записи. Ориентироваться стоит на последнюю запись для адреса, а не на первую.

Журнал содержит строки о выдаче, продлении и освобождении адресов вместе с аппаратными адресами клиентов, и по нему восстанавливают картину за любой период. Для долговременного хранения журнал направляют в отдельный файл настройкой log-facility и правилами системного журнала.

Типовые сбои разделяются на несколько групп. Служба не запускается при синтаксической ошибке в конфигурации, и сообщение с номером строки выводится в журнал. Служба запускается, но не отвечает, когда интерфейс не указан в списке либо адрес машины не входит ни в одну описанную подсеть. Адреса выдаются, но клиенты теряют сеть, когда параметр маршрута по умолчанию указывает на несуществующий адрес. Часть устройств получает неверные параметры при работе двух серверов в сегменте.

Проверка синтаксиса конфигурации выполняется запуском в режиме разбора.

sudo dhcpd -t -cf /etc/dhcp/dhcpd.conf

Команда сообщает об ошибках без запуска службы, и её удобно использовать перед каждым перезапуском.

Со стороны клиента диагностика выполняется освобождением и повторным запросом адреса с выводом полученных параметров.

sudo dhclient -r eth0
sudo dhclient -v eth0
ip -4 addr show dev eth0

Если адрес получен, но сеть недоступна, проверяют таблицу маршрутов и доступность шлюза, а затем сверяют выданные параметры с ожидаемыми.

Более лёгкая альтернатива и выбор решения

Для небольшой сети подходит dnsmasq, который совмещает раздачу адресов, кэширование имён и службу загрузки по сети в одном процессе с одним файлом конфигурации.

# /etc/dnsmasq.conf
interface=eth0
dhcp-range=192.168.10.100,192.168.10.200,12h
dhcp-host=00:11:22:33:44:55,printer,192.168.10.30
dhcp-host=aa:bb:cc:dd:ee:ff,nas,192.168.10.40
dhcp-option=option:router,192.168.10.1
dhcp-option=option:dns-server,192.168.10.5
dhcp-option=option:ntp-server,192.168.10.5

Резервирование задаётся строкой dhcp-host с аппаратным адресом, именем и адресом, а параметры строками dhcp-option. Возможности классификации клиентов и собственные параметры в таком объёме, как у isc-dhcp-server, здесь отсутствуют, но для десятка устройств их обычно и не требуется.

Выбор между двумя решениями определяется числом устройств и сложностью требований. Для домашней и небольшой офисной сети с резервированием адресов и передачей параметров достаточно dnsmasq. Для сети с сегментами, классификацией устройств, собственными параметрами и подробным журналом подходит isc-dhcp-server.

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

Завершает настройку фиксация схемы в тексте: диапазоны, зарезервированные адреса, переданные параметры и срок аренды. Конфигурацию удобно держать в системе контроля версий, поскольку правки в ней редки, а цена ошибки высока.