yvix-dhcp-server: выдача IP через REST API
yvix-dhcp-server — DHCP-сервер на Go, собранный на базе CoreDHCP. От классических DHCP-серверов он отличается тем, что решение «какой адрес выдать клиенту» принимает не статичный конфиг с пулом, а внешний REST API. Плюс есть файловый кеш выданных адресов — чтобы сеть продолжала работать, если API на время отвалится.
Из чего состоит
Сервер собирается из плагинов: в конфиге перечисляется список, и входящий запрос проходит по ним по очереди. Порядок важен.
Собственные плагины:
yvix— запрашивает IP у REST API и уведомляет об освобождении адреса;cacheplugin— кешMAC → IPв файле;ntp4— отдаёт клиенту опцию NTP-серверов.
Встроенные плагины из CoreDHCP: dns, lease_time, mtu, searchdomains, server_id, netmask, router, staticroute, range (динамический пул), file (статические привязки), autoconfigure, prefix (для DHCPv6).
Конфигурация
Конфиг — YAML. Вот рабочий пример: выдача через API плюс кеш и пара стандартных опций.
server4:
listen:
- "0.0.0.0%enp3s0:67"
plugins:
- yvix:
- https://your-domain.com
- 0aaaaaaaaaaaaaaaabbbbbbbbbbbbbcccccccccc
- if:enp3s0.123(123,124,125)
- ip:10.153.0.1(130,131)
- cacheplugin:
- /var/lib/yvix-dhcpd/cache.bin
- 86400
- dns: 10.12.1.9
- ntp4: 10.12.1.9
- lease_time: 7200s
- searchdomains: example.com
- server_id: 192.168.12.1
Как сервер спрашивает у API
Плагин yvix принимает три обязательных параметра: базовый URL, секретный токен и карты if:/ip: (о них ниже). Из URL формируются два эндпоинта:
POST <url>/api/radius/customer/ydhcp/assign/— запросить адрес;POST <url>/api/radius/customer/ydhcp/release/— сообщить об освобождении.
Запрос уходит как JSON с заголовком Authorization: Token <токен>. Таймаут — 15 секунд, проверка TLS-сертификата отключена, поэтому работают и самоподписанные сертификаты.
Запрос на выдачу:
{
"clientMac": "18:c0:4d:95:d0:30",
"hostname": "PCName",
"circuitId": "0x...",
"remoteId": "0x...",
"seconds": 1800,
"yourIpAddr": "0.0.0.0",
"gatewayIp": "10.153.0.1",
"clientId": "",
"poolId": 101
}
clientMac— MAC-адрес клиента;hostname— имя хоста, очищенное до латинских букв;circuitId/remoteId— поля из Option 82 (в виде0x...), если запрос прошёл через relay;seconds— сколько секунд клиент ждёт (полеsecsиз DHCP-запроса);yourIpAddr— полеyiaddrиз запроса;gatewayIp— полеgiaddr, то есть адрес relay-агента;clientId— идентификатор клиента (сейчас не заполняется);poolId— идентификатор пула.
Ответ API:
{
"yourIpAddr": "10.153.0.50",
"mask": "255.255.255.0",
"router": "10.153.0.1",
"leaseTime": 7200
}
Сервер применяет из ответа yourIpAddr, mask и router. Время аренды в DHCP-ответе задаёт отдельный плагин lease_time, а не поле leaseTime.
При DHCPRELEASE уходит короткий запрос:
{
"clientMac": "18:c0:4d:95:d0:30",
"ipAddr": "10.153.0.50"
}
Как выбирается пул
У API нет «одного пула на всё» — в запросе передаётся poolId, по которому ваш бэкенд понимает, в какой сети искать адрес. poolId — это uint16, и в текущей реализации это фактически VLAN ID, но семантически это «что угодно, что уникально привязано к сети и позволяет выбрать нужную подсеть».
Сопоставление задаётся прямо в конфиге плагина:
if:enp3s0.123(123,124,125)— запрос пришёл на локальный интерфейс → берёмpoolIdиз скобок;ip:10.153.0.1(130,131)— запрос пришёл от relay с таким адресом → берёмpoolId.
То есть при прямой выдаче смотрится интерфейс, а за relay — IP-адрес источника пакета.
Кеш
cacheplugin хранит пары MAC → IP в бинарном файле. Логика простая:
- если после всех плагинов адрес так и не выдан (например, API не ответил) — сервер достаёт прежний IP из кеша по MAC;
- если адрес выдан — сохраняет его в кеш с
deadline = now + время.
Поэтому, когда API лежит, клиенты продолжают получать свои прежние адреса, и сеть не встаёт. Срок жизни записи задаётся вторым аргументом плагина в секундах. Посмотреть содержимое кеша можно так:
yvix_dhcpd -S /var/lib/yvix-dhcpd/cache.bin
Что можно реализовать в API
Раз решение принимает ваш код, сценарии ограничены только фантазией:
- Белый список MAC. Адрес получают только известные устройства, остальные — отказ.
- Резервирование по абоненту. IP берётся из карточки абонента в биллинге, а не из общего пула.
- Разные опции по тарифу. Дорогому тарифу — одни DNS, дешёвому — другие.
- Динамические пулы. Адрес выбирается по
poolId— то есть по VLAN, точке подключения или relay-агенту. - Логирование и метрики. Каждое решение проходит через ваш API — его легко писать в лог, считать и алертить.
Итог
yvix-dhcp-server превращает выдачу IP из «настройки конфига» в «вызов вашего кода». С одной стороны это максимальная гибкость и интеграция с бэкендом, с другой — зависимость от доступности API, которую закрывает кеш: если API отвалился, клиенты продолжают получать прежние адреса, и сеть не встаёт.