Через опции клиент получает DNS, NTP, адрес TFTP-сервера для PXE, прошивку для VoIP-телефона и любые вендор-специфичные параметры.
Каждая опция кодируется в формате TLV: код (1 байт) + длина (1 байт) + значение.
На Cisco настраивается в ip dhcp pool через ключевое слово option, на MikroTik — через /ip dhcp-server option add с последующей привязкой к сети.
DHCP Options в Cisco и MikroTik: Option 12, 42, 43, 60, 66, 67, 82 — примеры настройки
Настроил DHCP, раздал адреса — и думаешь, всё. А потом телефоны не находят CallManager. PXE-клиенты грузятся вслепую. NTP не синхронизируется. Знакомая история.
IP-адрес — это минимум. Реальная сеть живёт на опциях. В этой статье разберём все основные DHCP Options с конкретными конфигами для Cisco IOS и MikroTik RouterOS, объясним формат данных, покажем типичные ошибки и дадим инструменты диагностики.
Времени займёт 20-30 минут. На выходе — рабочие конфиги для PXE, VoIP, NTP и понимание того, почему Option 82 иногда ломает выдачу адресов.
Как работает DHCP: процесс DORA и место опций
Протокол DHCP строится на четырёх сообщениях. Клиент ищет сервер broadcast-пакетом Discover. Сервер отвечает Offer с предложением адреса. Клиент принимает через Request. Сервер подтверждает через ACK.
Опции передаются в Offer и ACK. Клиент заранее сообщает, что хочет получить, через Option 55 — Parameter Request List в пакете Discover. Если опция в списке не запрошена — сервер её не отправит, даже если она настроена. Это важно для диагностики.
Формат TLV — как кодируется каждая опция
Каждая опция в DHCP-пакете кодируется по схеме TLV: Type-Length-Value.
- Type — 1 байт, номер опции от 0 до 255
- Length — 1 байт, длина поля Value в байтах
- Value — данные переменной длины
Исключения: Option 0 (Pad) и Option 255 (End) — без Length и Value, это служебные маркеры. Все остальные — строго TLV по RFC 2132.
Тип данных в Value зависит от конкретной опции: это может быть IP-адрес (4 байта), список IP-адресов, ASCII-строка или бинарные данные произвольного формата. Cisco IOS при настройке явно указывает тип через ключевые слова ip, ascii, hex. MikroTik RouterOS определяет тип по формату значения: строки в одинарных кавычках, hex через префикс 0x.
Таблица основных DHCP Options
| Код | Название | RFC | Тип данных | Применение |
|---|---|---|---|---|
| 6 | DNS Servers | RFC 2132 | IP-список | Адреса DNS-серверов |
| 12 | Host Name | RFC 2132 | ASCII | Имя хоста клиента |
| 15 | Domain Name | RFC 2132 | ASCII | DNS search domain |
| 42 | NTP Servers | RFC 2132 | IP-список (hex) | Синхронизация времени |
| 43 | Vendor Specific | RFC 2132 | Бинарные данные | VoIP, точки доступа, WLC |
| 55 | Parameter Request List | RFC 2132 | Список кодов | Клиент запрашивает опции |
| 60 | Vendor Class Identifier | RFC 2132 | ASCII | Идентификация типа клиента |
| 66 | TFTP Server Name | RFC 2132 | ASCII или IP | PXE-загрузка, IP-телефоны |
| 67 | Bootfile Name | RFC 2132 | ASCII | Файл PXE-загрузчика |
| 82 | Relay Agent Information | RFC 3046 | TLV подопции | Circuit-ID, Remote-ID в relay |
| 150 | TFTP Server Address | Cisco | IP | Cisco IP Phones (CUCM) |
Совместимость версий
| Платформа | Минимальная версия | Рекомендуется | Примечание |
|---|---|---|---|
| Cisco IOS | 12.4(T) | 15.x и выше | DHCP class (Option 60) — от 12.4 |
| Cisco IOS-XE | 3.x | 17.x и выше | Полная поддержка всех опций |
| MikroTik RouterOS 6 | 6.40 | 6.49.x | Нет add-relay-info для Option 82 |
| MikroTik RouterOS 7 | 7.1 | 7.x stable | add-relay-info, улучшенные option sets |
| ISC DHCP | 3.x | Переходи на Kea | ISC DHCP Server — legacy, не поддерживается |
| ISC Kea | 1.6 | 2.x | REST API, базы данных, hooks |
| dnsmasq | 2.60 | 2.89+ | Лёгкий, для небольших сетей |
На момент публикации актуальна RouterOS 7.x stable. Перед обновлением проверяй свежие релизы на mikrotik.com/download и changelog — синтаксис DHCP опций между мажорными версиями стабилен, но поведение relay менялось.
Архитектура: кто что передаёт и когда
Вот тут важно понять картину целиком, прежде чем лезть в конфиги. Option 82 добавляет relay. Option 43 зависит от Option 60. Option 67 бессмысленен без Option 66. Всё связано.
Ключевой момент — сервер возвращает только те опции которые клиент запросил в Option 55. Если опция настроена на сервере, но клиент не включил её код в Parameter Request List — она не придёт. Это частая причина «опция не работает».
Разбор каждой опции: назначение, формат, конфиги
Option 6 — DNS Servers
Передаёт список IP-адресов DNS-серверов в порядке приоритета. Клиент использует первый как основной, второй как резервный. Формат: список IPv4-адресов, каждый 4 байта, минимум один адрес.
На Cisco это встроено в стандартный синтаксис пула:
ip dhcp pool LAN
network 192.168.1.0 255.255.255.0
default-router 192.168.1.1
dns-server 192.168.1.10 8.8.8.8
На MikroTik DNS задаётся прямо в сети DHCP:
/ip dhcp-server network set 0 dns-server=192.168.1.10,8.8.8.8
Option 12 — Host Name
Вот тут читай внимательно — большинство путается. Option 12 чаще отправляет клиент серверу, а не сервер клиенту. Клиент сообщает своё имя в Discover/Request. Сервер читает это имя и может использовать для регистрации в DNS или логирования.
Сервер может передать имя хоста обратно в Offer, но поведение клиента при получении Option 12 от сервера зависит от реализации. Windows в домене его проигнорирует. Linux с dhclient — применит если настроен.
На MikroTik создание опции с именем хоста:
/ip dhcp-server option add code=12 name=hostname value="'workstation-01'"
/ip dhcp-server network set 0 dhcp-option=hostname
Практический смысл: Option 12 полезен когда надо зафиксировать имя клиента на сервере для DNS-регистрации. Для массового назначения имён — смотри в сторону статических маппингов по MAC.
Option 15 — Domain Name
Передаёт DNS search domain. Клиент добавляет этот суффикс к коротким именам при резолвинге. Запрос fileserver с Option 15 = corp.local резолвится как fileserver.corp.local.
Cisco IOS:
ip dhcp pool CORP
network 10.10.0.0 255.255.255.0
default-router 10.10.0.1
domain-name corp.local
dns-server 10.10.0.10
MikroTik RouterOS:
/ip dhcp-server network set 0 domain=corp.local
Option 42 — NTP Servers
Передаёт IP-адреса NTP-серверов. Критично для Kerberos (допустимое расхождение 5 минут), SSL-сертификатов и корректных логов. Формат — список IPv4-адресов в бинарном виде, то есть в hex.
Только IP-адреса, не доменные имена. Протокол требует бинарный IPv4. Доменные имена не поддерживаются спецификацией RFC 2132 для Option 42.
Перевод IP в hex — простое правило: каждый октет отдельно в двузначный hex. Лидирующий ноль обязателен: 1 = 01, не 1. 192=C0, 168=A8, 1=01, 1=01. Итого 192.168.1.1 = C0A80101.
Быстрая таблица перевода для частых адресов:
| IP-адрес | HEX для value |
|---|---|
| 192.168.1.1 | 0xC0A80101 |
| 192.168.0.1 | 0xC0A80001 |
| 10.0.0.1 | 0x0A000001 |
| 172.16.0.1 | 0xAC100001 |
| 10.10.0.1 | 0x0A0A0001 |
Для любого IP — быстро перевести через bash:
python3 -c "
import socket
ip = '192.168.1.1'
h = socket.inet_aton(ip).hex().upper()
print(f'{ip} -> 0x{h}')
"
Cisco IOS — Option 42 поддерживает прямой синтаксис:
ip dhcp pool LAN
option 42 ip 192.168.1.1
MikroTik RouterOS требует hex:
# Один NTP-сервер: 192.168.1.1
/ip dhcp-server option add code=42 name=ntp-server value=0xC0A80101
# Два NTP-сервера: 192.168.1.1 и 192.168.1.2 - байты подряд без разделителя
/ip dhcp-server option add code=42 name=ntp-pair value=0xC0A80101C0A80102
/ip dhcp-server network set 0 dhcp-option=ntp-server
Проверить что Linux-клиент получил NTP через DHCP:
# Через NetworkManager
nmcli -f DHCP4 dev show eth0 | grep -i ntp
# Через lease file
grep "ntp-servers" /var/lib/dhclient/dhclient.leases
Option 60 — Vendor Class Identifier
Клиент отправляет этот идентификатор серверу в Discover, чтобы сообщить свой тип и производителя. Сервер использует Option 60 чтобы понять, какое содержимое Option 43 вернуть конкретному клиенту.
Примеры значений от разных клиентов:
- PXE BIOS:
PXEClient:Arch:00000:UNDI:002001 - PXE UEFI:
PXEClient:Arch:00007:UNDI:003016 - Cisco IP Phone:
Cisco Systems, Inc. IP Phone CP-7941G - Ubiquiti AP:
ubnt - Windows:
MSFT 5.0
На Cisco IOS можно разделять клиентов по Option 60 через DHCP classes:
ip dhcp class VOIP-PHONES
option 60 ascii "Cisco Systems"
ip dhcp pool MAIN
network 192.168.1.0 255.255.255.0
default-router 192.168.1.1
class VOIP-PHONES
address range 192.168.1.200 192.168.1.250
Так телефоны автоматически получают адреса из отдельного диапазона — без ручного прописывания MAC.
Option 66 — TFTP Server Name
Передаёт адрес TFTP-сервера. Два основных сценария: PXE-загрузка и автопровизионирование IP-телефонов. Формат — ASCII-строка с доменным именем или IP-адресом как текстом.
Cisco IOS:
ip dhcp pool PXE
network 192.168.10.0 255.255.255.0
default-router 192.168.10.1
option 66 ascii 192.168.10.5
MikroTik RouterOS — строки всегда в одинарных кавычках внутри двойных:
/ip dhcp-server option add code=66 name=tftp-server value="'192.168.10.5'"
/ip dhcp-server network set 0 dhcp-option=tftp-server
Option 67 — Bootfile Name
Имя загрузочного файла на TFTP-сервере. Работает только вместе с Option 66. Без Option 66 клиент не знает где искать файл.
Выбор файла зависит от типа клиента:
- BIOS-клиенты:
pxelinux.0 - UEFI 64-бит:
bootx64.efiилиgrubx64.efi - UEFI 32-бит:
bootia32.efi
Cisco IOS — пара Option 66 + 67 для PXE:
ip dhcp pool PXE
network 192.168.10.0 255.255.255.0
default-router 192.168.10.1
dns-server 192.168.10.1
option 66 ascii 192.168.10.5
option 67 ascii pxelinux.0
MikroTik RouterOS с применением через option set:
/ip dhcp-server option add code=66 name=pxe-tftp value="'192.168.10.5'"
/ip dhcp-server option add code=67 name=pxe-file value="'pxelinux.0'"
/ip dhcp-server option sets add name=pxe-options options=pxe-tftp,pxe-file
/ip dhcp-server network set 0 dhcp-option-set=pxe-options
Option 43 — Vendor Specific Information
Поле для передачи вендор-специфичных данных. Сервер возвращает Option 43 только если знает тип клиента — определяет по Option 60. Содержимое Option 43 одинаковое по структуре (TLV подопции), но интерпретируется по-разному у каждого производителя.
Cisco IP Phones ищут адрес Cisco Unified Communications Manager через Option 43. Формат Cisco: субтип 0xF1 + длина 0x04 + IP в hex.
Расчёт: CUCM 10.1.1.10 = 0A.01.01.0A. Итого: f104.0A01.010A
ip dhcp pool VOIP
network 10.1.1.0 255.255.255.0
default-router 10.1.1.1
dns-server 10.1.1.5
option 43 hex f104.0A01.010A
Cisco Aironet / Catalyst AP ищут WLC (Wireless LAN Controller) через Option 43. Формат тот же, но адрес WLC. WLC 192.168.100.10 = C0.A8.64.0A:
ip dhcp pool WIRELESS
network 192.168.100.0 255.255.255.0
default-router 192.168.100.1
option 43 hex f104.C0A8.640A
MikroTik — Option 43 для Ubiquiti UniFi. Ubiquiti использует простой строковый формат: IP-адрес контроллера как ASCII:
/ip dhcp-server option add code=43 name=unifi-controller value="'192.168.1.100'"
/ip dhcp-server network set 0 dhcp-option=unifi-controller
Option 82 — Relay Agent Information
Добавляется не сервером, а relay-агентом при перенаправлении запроса. Позволяет серверу знать откуда физически пришёл запрос.
Содержит две ключевые подопции:
- Subtype 1 — Circuit-ID: порт и VLAN на коммутаторе. Формат зависит от вендора.
- Subtype 2 — Remote-ID: идентификатор relay-агента, обычно MAC или hostname.
Применяется в трёх сценариях: политики выдачи адресов по порту подключения, безопасность (DHCP snooping), биллинг у операторов.
Option 43 для разных вендоров — полный справочник
Option 43 — это контейнер. Что внутри — решает вендор. Один и тот же код 43, но для Cisco это одно, для Ubiquiti другое, для HP Aruba третье. Разбираем каждый случай.
Cisco IP Phone + Cisco Unified Communications Manager
Cisco использует субтип 0xF1 (241 в десятичной) для передачи адреса CUCM. Формат: F1 + длина в байтах + IP-адреса.
Один CUCM (4 байта):
# CUCM: 10.1.1.10 = 0A 01 01 0A
# f1(субтип) + 04(4 байта) + 0A01010A
option 43 hex f104.0A01.010A
Два CUCM (8 байт — Primary + Backup):
# Primary: 10.1.1.10 = 0A01010A
# Backup: 10.1.1.11 = 0A01010B
# f1(субтип) + 08(8 байт) + оба IP подряд
option 43 hex f108.0A01.010A.0A01.010B
Cisco Wireless — WLC через Option 43
Точки доступа Cisco Aironet, Catalyst 9100 используют Option 43 для поиска Wireless LAN Controller при первом включении. Формат тот же: субтип F1 + длина + IP WLC.
# WLC: 192.168.100.10 = C0 A8 64 0A
ip dhcp pool WIRELESS
network 192.168.100.0 255.255.255.0
default-router 192.168.100.1
option 43 hex f104.C0A8.640A
# WLC кластер из двух контроллеров
# 192.168.100.10 и 192.168.100.11
ip dhcp pool WIRELESS
network 192.168.100.0 255.255.255.0
default-router 192.168.100.1
option 43 hex f108.C0A8.640A.C0A8.640B
Ubiquiti UniFi — Option 43
UniFi точки доступа в factory-reset состоянии ищут контроллер через Option 43. Ubiquiti использует простой формат: IP-адрес контроллера как ASCII-строку.
На Cisco IOS:
ip dhcp pool UNIFI
network 192.168.1.0 255.255.255.0
default-router 192.168.1.1
option 43 ascii "192.168.1.100"
На MikroTik:
/ip dhcp-server option add code=43 name=unifi-ctrl value="'192.168.1.100'"
/ip dhcp-server network set 0 dhcp-option=unifi-ctrl
HP Aruba IAP — Option 43
Aruba Instant AP при активации ищет AirWave или Central через Option 43. Формат: строка вида ArubaInstantOn:AirWaveIP.
# Cisco IOS
ip dhcp pool ARUBA
network 10.10.0.0 255.255.255.0
default-router 10.10.0.1
option 43 ascii "ArubaInstantOn:10.10.0.50"
Рассчитать hex для Option 43 вручную
Если нет под рукой калькулятора — bash помогает:
# Перевести IP в hex для Option 43
python3 -c "
import socket
import struct
ip = '10.1.1.10'
packed = socket.inet_aton(ip)
hex_str = packed.hex()
print(f'IP: {ip}')
print(f'Hex: {hex_str.upper()}')
print(f'Cisco Option 43 (single): f104{hex_str}')
"
Таблица: Option 43 по вендорам
| Вендор | Формат значения | Пример |
|---|---|---|
| Cisco IP Phone / AP | HEX: f1 + длина + IP | f104.0A01.010A |
| Ubiquiti UniFi | ASCII: IP-адрес строкой | «192.168.1.100» |
| HP Aruba IAP | ASCII: ArubaInstantOn:IP | «ArubaInstantOn:10.0.0.50» |
| Ruckus ZoneDirector | ASCII: IP контроллера | «10.0.0.100» |
| Cambium cnMaestro | ASCII: URL или IP | «https://controller.corp» |
Перед применением — всегда проверяй документацию своей версии. Форматы Option 43 иногда меняются между прошивками. Что работало с Cisco 7941 — может не работать с 8865.
Cisco DHCP Options — полная настройка
Базовый DHCP pool со всеми основными опциями
ip dhcp excluded-address 192.168.10.1 192.168.10.20
ip dhcp pool OFFICE
network 192.168.10.0 255.255.255.0
default-router 192.168.10.1
dns-server 192.168.10.5 8.8.8.8
domain-name office.local
lease 0 8
option 42 ip 192.168.10.1
option 66 ascii 192.168.10.5
option 67 ascii pxelinux.0
DHCP Relay и ip helper-address
DHCP Discover — broadcast. Маршрутизатор не пропускает broadcast между подсетями по умолчанию. Если DHCP-сервер в другой подсети — нужен relay.
На Cisco relay настраивается через ip helper-address на интерфейсе, смотрящем в сторону клиентов:
interface Vlan10
ip address 192.168.10.1 255.255.255.0
ip helper-address 10.0.0.5
interface Vlan20
ip address 192.168.20.1 255.255.255.0
ip helper-address 10.0.0.5
По умолчанию ip helper-address пересылает не только DHCP, но и TFTP (69), DNS (53), NetBIOS (137/138). Если нужен только DHCP:
no ip forward-protocol udp 69
no ip forward-protocol udp 137
no ip forward-protocol udp 138
Option 82 на Cisco — DHCP Snooping и Relay
На коммутаторах Catalyst Option 82 добавляется через DHCP Snooping:
! Включить DHCP snooping глобально
ip dhcp snooping
ip dhcp snooping vlan 10,20,30
! Указать доверенный uplink
interface GigabitEthernet1/0/24
ip dhcp snooping trust
! На маршрутизаторе - принять Option 82 от relay
ip dhcp relay information trust-all
Если сервер отбрасывает запросы с Option 82:
! Глобально
ip dhcp relay information trust-all
! На конкретном интерфейсе
interface GigabitEthernet0/1
ip dhcp relay information trusted
Схема работы DHCP Relay с Option 82
MikroTik DHCP Options — настройка в RouterOS
Логика работы — опции создаются отдельно и привязываются
В MikroTik архитектура другая по сравнению с Cisco. Опции создаются глобально как именованные объекты, потом привязываются к конкретной сети. Одну опцию можно использовать в нескольких сетях. Это удобно — не дублируешь конфиг для каждого пула.
Два способа привязки:
- dhcp-option — одна или несколько опций через запятую прямо в network
- dhcp-option-set — именованная группа опций, удобно для PXE или VoIP
Создание всех базовых опций
# DNS (Option 6) - hex: 192.168.10.10 = C0A80A0A
/ip dhcp-server option add code=6 name=dns-local value=0xC0A80A0A
# NTP (Option 42) - hex: 192.168.1.1 = C0A80101
/ip dhcp-server option add code=42 name=ntp-local value=0xC0A80101
# Domain Name (Option 15) - строка в кавычках
/ip dhcp-server option add code=15 name=domain-name value="'office.local'"
# Host Name (Option 12)
/ip dhcp-server option add code=12 name=hostname value="'srv01'"
# TFTP Server (Option 66)
/ip dhcp-server option add code=66 name=tftp-srv value="'192.168.1.5'"
# Bootfile (Option 67)
/ip dhcp-server option add code=67 name=bootfile-bios value="'pxelinux.0'"
/ip dhcp-server option add code=67 name=bootfile-uefi value="'bootx64.efi'"
Option Sets — группировка для PXE
# Группа для PXE BIOS
/ip dhcp-server option sets add name=pxe-bios options=tftp-srv,bootfile-bios
# Группа для PXE UEFI
/ip dhcp-server option sets add name=pxe-uefi options=tftp-srv,bootfile-uefi
# Полная группа для офисной сети
/ip dhcp-server option sets add name=office-full options=dns-local,ntp-local,domain-name
# Привязка к сети
/ip dhcp-server network set 0 dhcp-option-set=office-full
DHCP Relay с Option 82 в MikroTik
RouterOS 7 добавил параметр add-relay-info для включения Option 82:
# RouterOS 7 - relay с Option 82
/ip dhcp-relay add \
name=relay-vlan10 \
interface=vlan10 \
dhcp-server=10.0.0.5 \
add-relay-info=yes \
local-address=10.0.0.1
При add-relay-info=yes MikroTik добавляет:
- Circuit-ID (subtype 1): имя интерфейса RouterOS
- Remote-ID (subtype 2): MAC-адрес интерфейса relay-агента
RouterOS 6 — синтаксис без add-relay-info:
/ip dhcp-relay add name=relay1 interface=ether2 dhcp-server=10.0.0.5 local-address=10.0.0.1
Сравнение синтаксиса Cisco vs MikroTik
| Параметр | Cisco IOS | MikroTik RouterOS |
|---|---|---|
| Relay | ip helper-address | /ip dhcp-relay add |
| Option 82 | ip dhcp snooping | add-relay-info=yes |
| Circuit-ID | Vlan/Port или имя интерфейса | Имя интерфейса RouterOS |
| Remote-ID | MAC коммутатора | MAC интерфейса relay |
| Строковые опции | option 66 ascii «значение» | value=»‘значение'» |
| IP-опции | option 42 ip 192.168.1.1 | value=0xC0A80101 |
| Группировка опций | Нет (по одной в пуле) | dhcp-option-set |
| Фильтрация по Option 82 | Через DHCP class / pools | Не поддерживается нативно |
Практические сценарии: PXE, VoIP, OpenVPN
PXE-загрузка — Option 66 и 67 для BIOS и UEFI
PXE (Preboot Execution Environment) нужен для сетевой загрузки: разворачивание ОС, WDS, Clonezilla, диагностика. Требует TFTP-сервер с загрузочными файлами и двух опций DHCP.
Проблема: BIOS и UEFI клиенты нужны разные загрузчики. Отличить их можно по Option 60: BIOS отправляет PXEClient:Arch:00000, UEFI 64-бит — PXEClient:Arch:00007.
Cisco IOS — раздельные пулы:
# Для BIOS-клиентов
ip dhcp pool PXE-BIOS
network 192.168.10.0 255.255.255.0
default-router 192.168.10.1
option 66 ascii 192.168.10.5
option 67 ascii pxelinux.0
# Для UEFI-клиентов
ip dhcp pool PXE-UEFI
network 192.168.10.0 255.255.255.0
default-router 192.168.10.1
option 66 ascii 192.168.10.5
option 67 ascii bootx64.efi
Проблема с раздельными пулами на одну подсеть — Cisco поднимет конфликт. Правильный подход через классы:
ip dhcp class PXE-BIOS-CLASS
option 60 ascii "PXEClient:Arch:00000"
ip dhcp class PXE-UEFI-CLASS
option 60 ascii "PXEClient:Arch:00007"
ip dhcp pool PXE-NETWORK
network 192.168.10.0 255.255.255.0
default-router 192.168.10.1
option 66 ascii 192.168.10.5
class PXE-BIOS-CLASS
option 67 ascii pxelinux.0
class PXE-UEFI-CLASS
option 67 ascii bootx64.efi
MikroTik — через разные option sets с привязкой по MAC или через статические маппинги:
/ip dhcp-server option add code=66 name=pxe-tftp value="'192.168.10.5'"
/ip dhcp-server option add code=67 name=boot-bios value="'pxelinux.0'"
/ip dhcp-server option add code=67 name=boot-uefi value="'bootx64.efi'"
/ip dhcp-server option sets add name=pxe-bios options=pxe-tftp,boot-bios
/ip dhcp-server option sets add name=pxe-uefi options=pxe-tftp,boot-uefi
# Привязка через статический lease по MAC для UEFI-клиентов
/ip dhcp-server lease add mac-address=AA:BB:CC:DD:EE:FF address=192.168.10.100 dhcp-option-set=pxe-uefi
Cisco VoIP — Option 43 и Option 150
Cisco IP Phone при загрузке ищет Cisco Unified Communications Manager (CUCM). Два механизма, которые работают по-разному:
- Option 150 — Cisco-проприетарная, передаёт IP-адрес TFTP-сервера (где лежат конфиги телефонов). Бинарный IP.
- Option 43 — стандартная vendor-specific с адресом CUCM в формате Cisco (subtype 0xF1).
Старые модели телефонов понимают только Option 150. Современный UCM рекомендует Option 150 как основной.
# TFTP = 10.1.1.50, CUCM = 10.1.1.10
# Option 43 hex: f1(тип Cisco) + 04(4 байта) + 0A01010A (10.1.1.10)
ip dhcp pool VOIP
network 10.1.1.0 255.255.255.0
default-router 10.1.1.1
dns-server 10.1.1.5
option 150 ip 10.1.1.50
option 43 hex f104.0A01.010A
Если CUCM кластер с несколькими серверами — увеличиваешь длину в Option 43. Два CUCM: f108 (8 байт) + оба IP подряд.
OpenVPN — push dhcp-option
OpenVPN позволяет серверу передавать сетевые параметры клиентам через директиву push. Это не настоящий DHCP, но семантика опций та же. Клиент получает параметры при установке туннеля.
# /etc/openvpn/server.conf
# DNS для клиентов VPN
push "dhcp-option DNS 10.0.0.1"
push "dhcp-option DNS 10.0.0.2"
# Домен поиска
push "dhcp-option DOMAIN corp.local"
# NTP через VPN
push "dhcp-option NTP 10.0.0.1"
# Маршрут к внутренней сети
push "route 192.168.0.0 255.255.0.0"
# Блокировка DNS-утечек на Windows
push "block-outside-dns"
Как обновлять DHCP-конфигурацию безопасно
Что проверить перед изменением опций
Изменение DHCP Options в продакшне — это не «поправил и забыл». Клиенты получают новые значения только при следующем обновлении lease. Существующие lease — со старыми опциями до истечения срока.
Порядок действий:
- Сохрани текущий конфиг (на Cisco:
copy running-config startup-config, на MikroTik: export) - Определи время lease в пуле — через столько клиенты получат новые опции
- Проверь на тестовом клиенте через
ipconfig /release && ipconfig /renewилиdhclient -r && dhclient - Убедись через Wireshark что опция пришла правильно
- Для форсированного обновления всех клиентов — сократи lease time на период обновления, потом верни
Как откатиться
Cisco — откат конфига:
# Откат к сохранённой конфигурации
copy startup-config running-config
# Или вручную удалить изменённую опцию
ip dhcp pool OFFICE
no option 42
MikroTik — откат через export/import или удаление опции:
# Удалить привязку опции к сети
/ip dhcp-server network set 0 dhcp-option=""
# Или удалить саму опцию
/ip dhcp-server option remove ntp-server
# Откат через импорт бэкапа
/import file=dhcp-backup.rsc
Форсировать обновление lease на клиентах
После изменения опций клиенты со старым lease не получат новые значения сразу. Варианты ускорить:
# Windows - обновить lease
ipconfig /release
ipconfig /renew
# Linux - через dhclient
dhclient -r eth0
dhclient eth0
# Linux - через NetworkManager
nmcli con down eth0 && nmcli con up eth0
# На Cisco - очистить все lease принудительно (используй осторожно в продакшне)
clear ip dhcp binding *
MikroTik — расширенные примеры и нюансы
Привязка опций к конкретному клиенту по MAC
Иногда нужно дать разные опции разным клиентам в одной сети. Например, телефонам — NTP и Option 150, компьютерам — только DNS. В MikroTik это делается через статические lease с привязкой option-set:
# Создать option sets для телефонов и компьютеров
/ip dhcp-server option sets add name=voip-options options=ntp-local,tftp-cisco
/ip dhcp-server option sets add name=pc-options options=dns-local,domain-name
# Привязать к конкретным lease по MAC
/ip dhcp-server lease add \
mac-address=AA:BB:CC:DD:EE:F1 \
address=192.168.1.101 \
dhcp-option-set=voip-options \
comment="Cisco Phone"
/ip dhcp-server lease add \
mac-address=AA:BB:CC:DD:EE:F2 \
address=192.168.1.201 \
dhcp-option-set=pc-options \
comment="Workstation"
Скрипт для проверки всех привязанных опций
# Посмотреть все опции
/ip dhcp-server option print detail
# Посмотреть все option sets
/ip dhcp-server option sets print detail
# Посмотреть сети с привязанными опциями
/ip dhcp-server network print detail
# Проверить конкретный lease
/ip dhcp-server lease print detail where mac-address="AA:BB:CC:DD:EE:F1"
Переход с RouterOS 6 на RouterOS 7 — что меняется в DHCP
Синтаксис создания опций одинаков в обеих версиях — миграция конфига опций проблем не вызывает. Ключевые изменения:
- RouterOS 7 добавил
add-relay-info=yesв dhcp-relay — теперь Option 82 поддерживается нативно - В RouterOS 7 улучшена работа с IPv6 DHCP (DHCPv6)
- Команды
/ip dhcp-serverне изменились — конфиги совместимы
При обновлении с ROS 6 на ROS 7 — проверь что relay работает корректно, так как реализация изменилась:
# После обновления - проверить relay
/ip dhcp-relay print
/ip dhcp-relay monitor
/log print where topics~"dhcp"
Troubleshooting: частые ошибки и как их лечить
Ошибка 1: неверный тип данных — ip вместо ascii или наоборот
Cisco IOS принципиально различает тип после номера опции:
option 66 ip 192.168.10.5 # передаёт 4 байта бинарного IP
option 66 ascii 192.168.10.5 # передаёт строку "192.168.10.5" (12 символов)
Большинство клиентов для Option 66 ожидают ASCII-строку. Для DNS (Option 6) — бинарный IP. Если клиент не получает опцию или ведёт себя некорректно — первым делом открывай Wireshark и смотри что реально пришло.
Диагностика на сервере:
debug ip dhcp server events
debug ip dhcp server packets
Ошибка 2: MikroTik — забытые кавычки в строковых опциях
Это самая частая ошибка в RouterOS. Без одинарных кавычек внутри двойных RouterOS пытается интерпретировать значение как hex-число или константу.
# НЕПРАВИЛЬНО - RouterOS не поймёт как строку
/ip dhcp-server option add code=15 name=domain value="office.local"
# ПРАВИЛЬНО - одинарные кавычки внутри двойных
/ip dhcp-server option add code=15 name=domain value="'office.local'"
Проверить созданную опцию:
/ip dhcp-server option print detail
Ошибка 3: сервер отбрасывает запросы с Option 82
Симптом: клиенты в подсетях через relay не получают адреса. Клиенты в той же подсети что и сервер — получают нормально.
Диагностика:
debug ip dhcp server events
В логах увидишь что-то вроде: DHCP: Dropping packet: relay information policy is replace
Решение:
# Принять Option 82 от всех relay
ip dhcp relay information trust-all
# Или на конкретном интерфейсе
interface Vlan10
ip dhcp relay information trusted
Ошибка 4: клиент не запрашивает опцию
Сервер настроен правильно, но клиент не получает опцию. Причина: клиент не включил код опции в свой Option 55 (Parameter Request List).
Проверить что запрашивает клиент:
tcpdump -i eth0 port 67 -vv | grep -A 20 "DHCP Discover"
Ищи строку Parameter-Request Option-55 — там список кодов которые клиент хочет получить. Если нужного кода нет — сервер его не отправит.
Для Linux-клиентов можно добавить запрос опции через dhclient.conf:
# /etc/dhcp/dhclient.conf
also request ntp-servers; # Option 42
request subnet-mask, broadcast-address, routers, domain-name,
domain-name-servers, ntp-servers;
Ошибка 5: неверный hex в Option 42 или 43
Потерял байт при переводе — и NTP-сервер указывает куда-то в никуда, или телефон не может найти CUCM.
Проверка через tcpdump:
tcpdump -i eth0 -n port 67 or port 68 -vv
Или dhcpdump если установлен:
dhcpdump -i eth0
В Wireshark фильтр bootp или dhcp, затем в пакете DHCP ACK раскрой Bootstrap Protocol — Options. Каждая опция показана с номером, длиной и значением.
Ошибка 6: несовпадение Circuit-ID после смены оборудования
Заменил коммутатор или переименовал интерфейс — и клиенты перестали получать адреса из правильного пула. Сервер выдаёт адреса на основе Circuit-ID из Option 82, а Circuit-ID изменился вместе с именем интерфейса.
Захвати трафик на сервере и проверь содержимое Option 82:
tcpdump -i eth0 -n port 67 -vv 2>&1 | grep -A 5 "relay"
На Wireshark: DHCP Request — Option 82 — Circuit ID — смотришь что за строка пришла. Обновляешь политику на сервере под новое значение.
Ошибка 7: PXE клиент получает опции но не грузится
Опции 66 и 67 пришли — клиент видит TFTP-сервер и имя файла, но загрузка не идёт. Три причины:
- TFTP-сервер недоступен с IP клиента (проверь firewall, порт UDP 69)
- Файл указан в Option 67, но физически отсутствует на TFTP-сервере
- UEFI-клиент получил BIOS-файл или наоборот (проверь Option 60 в Wireshark)
Проверка доступности TFTP с клиента Linux:
# Проверить что TFTP-сервер отвечает
tftp 192.168.10.5 -c get pxelinux.0
# Проверить firewall на сервере TFTP (Linux)
sudo ufw status
iptables -L INPUT -n | grep 69
Ошибка 8: Option 43 для Cisco AP — точка не находит WLC
Точка доступа получила адрес, но в logs WLC не появляется. Порядок диагностики:
# На WLC - посмотреть лог попыток регистрации AP
# GUI: Monitor -> Statistics -> AP Join
# На роутере Cisco - убедиться что hex правильный
show ip dhcp pool WIRELESS
# Захватить трафик AP при загрузке
tcpdump -i vlan100 -n port 67 -vv 2>&1 | grep -A 5 "option 43"
Частая ошибка: WLC IP 192.168.100.10 и неправильно переведённый hex. Проверяем:
python3 -c "
ip = '192.168.100.10'
parts = ip.split('.')
hex_str = ''.join(f'{int(p):02X}' for p in parts)
print(f'IP: {ip} -> HEX: {hex_str}')
print(f'Cisco Option 43: f104.{hex_str[:4]}.{hex_str[4:]}')
"
Ошибка 9: MikroTik relay не добавляет Option 82
Включил add-relay-info=yes но сервер не видит Option 82 в пакетах. Проверь версию RouterOS — параметр появился в RouterOS 7. На RouterOS 6 Option 82 в relay не поддерживается.
# Проверить версию RouterOS
/system resource print | grep version
# Проверить настройку relay
/ip dhcp-relay print detail
Ошибка 10: опция настроена но клиент не обновляется
Изменил Option на сервере — клиент продолжает использовать старые значения. Всё потому что lease ещё не истёк. Клиент запросит новые параметры только при обновлении аренды адреса.
На Linux — принудительно обновить:
sudo dhclient -r eth0 && sudo dhclient eth0
Проверить что нового пришло:
cat /var/lib/dhclient/dhclient.leases | tail -50
nmcli -f DHCP4 dev show eth0
Порты DHCP — таблица для firewall
| Протокол | Порт | Направление | Назначение |
|---|---|---|---|
| UDP | 67 | Клиент -> Сервер | DHCP Server (Discover, Request) |
| UDP | 68 | Сервер -> Клиент | DHCP Client (Offer, ACK) |
| UDP | 69 | Клиент -> TFTP | TFTP для PXE-загрузки |
| UDP | 67 | Relay -> Сервер (unicast) | Перенаправление от relay |
Безопасность DHCP-инфраструктуры
DHCP Snooping — защита от Rogue DHCP
Rogue DHCP-сервер — когда кто-то в сети поднимает свой DHCP и начинает раздавать адреса с кривым шлюзом или DNS. Классический вектор атаки «человек посередине».
DHCP Snooping на Catalyst защищает от этого: помечает порты как trusted (только туда ходит DHCP-трафик от серверов) и untrusted (клиентские порты, DHCP Offer с них блокируется).
! Включить глобально
ip dhcp snooping
ip dhcp snooping vlan 10,20,30
! Uplink к серверу или вышестоящему коммутатору - trusted
interface GigabitEthernet1/0/24
ip dhcp snooping trust
! Верифицировать MAC-адреса (защита от DHCP starvation)
ip dhcp snooping verify mac-address
! Ограничить rate DHCP на клиентском порту
interface GigabitEthernet1/0/1
ip dhcp snooping limit rate 15
Ограничение пула адресов
Всегда исключай служебные адреса из динамического пула. Адреса шлюзов, серверов, принтеров — через excluded-address, не через статические маппинги в пуле.
! Cisco - исключить диапазон
ip dhcp excluded-address 192.168.10.1 192.168.10.50
! MikroTik - через статические lease или исключение из диапазона
/ip dhcp-server network set 0 address=192.168.10.0/24 gateway=192.168.10.1
/ip pool set dhcp-pool ranges=192.168.10.51-192.168.10.254
Логирование выдачи адресов
MikroTik пишет DHCP-события в системный лог. Включить явное логирование:
/system logging add topics=dhcp action=memory
/system logging add topics=dhcp action=remote
Cisco:
service dhcp
ip dhcp pool ...
update arp
logging buffered 65536 debugging
Проверка работы DHCP Options
На клиентах — проверить полученные опции
Linux — ipconfig или dhclient:
# Посмотреть текущий lease с опциями
cat /var/lib/dhclient/dhclient.leases
# Обновить lease и посмотреть в реальном времени
dhclient -v eth0 2>&1 | head -50
# Через nmcli
nmcli -f DHCP4 dev show eth0
Windows:
# Полная информация по адаптеру включая DHCP-опции
ipconfig /all
# Сбросить и получить новый lease
ipconfig /release && ipconfig /renew
На сервере Cisco — статистика и дебаг
! Список выданных адресов
show ip dhcp binding
! Статистика DHCP-сервера
show ip dhcp server statistics
! Конфликты (адреса которые ping-проверка показала занятыми)
show ip dhcp conflict
! Дебаг выдачи адресов
debug ip dhcp server events
! Отключить дебаг
no debug ip dhcp server events
На MikroTik
# Список выданных адресов
/ip dhcp-server lease print
# Мониторинг relay
/ip dhcp-relay print
/ip dhcp-relay monitor
# Список созданных опций
/ip dhcp-server option print detail
# Список option sets
/ip dhcp-server option sets print
# Логи DHCP
/log print where topics~"dhcp"
Через Wireshark — захват DHCP-трафика
Фильтр: bootp или dhcp
На Linux без Wireshark:
# Полный захват DHCP-трафика
tcpdump -i eth0 -n port 67 or port 68 -vv
# Сохранить в файл для анализа в Wireshark
tcpdump -i eth0 -n port 67 or port 68 -w /tmp/dhcp.pcap
# dhcpdump - читаемый вывод
apt install dhcpdump
dhcpdump -i eth0
В пакете DHCP ACK смотришь раздел Bootstrap Protocol -> Options. Каждая опция с кодом, длиной и декодированным значением. Если опция есть в ACK но клиент её игнорирует — проблема на стороне клиента.
Чеклист перед выкаткой в продакшн
— Время на DHCP-сервере синхронизировано (важно для Kerberos и логов)
— IP-адреса в hex-опциях переведены побайтово и проверены
— Строковые значения в MikroTik обёрнуты в «‘ ‘»
— Cisco DHCP-сервер настроен на trust Option 82 если используется relay
— PXE: загрузочные файлы для BIOS и UEFI присутствуют на TFTP-сервере
— Option 43 для VoIP проверен по формуле вендора (f1 + длина + IP hex)
— DHCP lease обновлён на тестовых клиентах после изменения опций
— Клиенты проверены через Wireshark — опция присутствует в ACK
— Option 55 клиента включает коды нужных опций
— Для OpenVPN: push-директивы в секции сервера, не клиента
— DHCP Snooping включён на клиентских VLAN (защита от Rogue DHCP)
— Логирование DHCP-событий настроено
Альтернативы и смежные решения
ISC DHCP и KEA — когда Cisco и MikroTik не подходят
Если нужна гибкая политика выдачи на основе Option 82 с кастомными Circuit-ID правилами — рассмотри ISC Kea DHCP. Kea пришёл на замену legacy ISC DHCP Server, поддерживает REST API, базы данных для хранения lease и гибкие hook-плагины.
Dnsmasq — для небольших сетей и embedded. Поддерживает все основные опции, конфигурируется просто:
# /etc/dnsmasq.conf - опции через dhcp-option
dhcp-option=42,192.168.1.1 # NTP
dhcp-option=66,"192.168.1.5" # TFTP
dhcp-option=67,"pxelinux.0" # Bootfile
dhcp-option=vendor:PXEClient,1,0 # Vendor-specific
DHCPv6 и IPv6 — опции работают иначе
В DHCPv6 (RFC 3315) нет понятия Option 82 — его роль выполняет другой механизм. DNS передаётся через Option 23 (DNS Recursive Name Server), NTP через Option 56. Option 43 не существует в DHCPv6 — вендор-специфичные данные передаются по другой схеме.
Если переходишь на IPv6 — не переноси конфигурацию DHCPv4 один в один, там другая логика.
Профилактика — как не сломать снова
Документируй hex-значения
Hex без комментария — это тикающая бомба. Через полгода сам не поймёшь что за 0xC0A80101 в конфиге. Всегда добавляй комментарий рядом.
На Cisco — через remark в конфиге или в описании интерфейса:
! Option 42: NTP = 192.168.1.1 (C0A80101)
option 42 ip 192.168.1.1
На MikroTik — через имя опции, делай имена говорящими:
# Плохо
/ip dhcp-server option add code=42 name=opt42 value=0xC0A80101
# Хорошо
/ip dhcp-server option add code=42 name=ntp-192-168-1-1 value=0xC0A80101
Держи таблицу всех опций в документации
Создай документ или страницу в wiki с таблицей: код опции, имя, значение, что за IP за hex, для какого пула используется. Когда через год придёт джун и спросит «а что за f104.0A01.010A» — ты скажешь «открой wiki». Иначе будет «спроси у Андрея», а Андрей уже давно не помнит.
Тестируй изменения в тестовом VLAN
Никогда не меняй опции сразу в продакшн-пуле. Создай тестовый VLAN, подключи один клиент, проверь что опции приходят корректно через Wireshark. Потом переноси в продакшн.
Это правило кажется очевидным, пока первый раз не выкатишь неправильный hex для Option 43 в офисный пул с 300 телефонами в понедельник утром. Чем глубже в продакшн, тем страшнее архитектура последствий.
Мониторинг DHCP-пула
Отслеживай заполненность пула. Когда пул заканчивается — новые клиенты не получат адреса. Это тихая авария: старые клиенты работают, новые нет.
Cisco — проверить заполненность:
show ip dhcp pool
show ip dhcp binding | include Total
show ip dhcp server statistics
MikroTik — базовый мониторинг:
# Количество активных lease
/ip dhcp-server lease print count-only where status=bound
# Все lease с временем истечения
/ip dhcp-server lease print detail where status=bound
# Посмотреть пул адресов
/ip pool print detail
Для автоматического оповещения — скрипт MikroTik который шлёт уведомление когда пул заполнен более чем на 80%:
# /system scheduler + скрипт проверки пула
:local leaseCount [/ip dhcp-server lease print count-only where status=bound]
:local poolTotal 200
:local threshold 160
:if ($leaseCount > $threshold) do={
/log warning ("DHCP pool: " . $leaseCount . "/" . $poolTotal . " addresses used")
}
Автозапуск DHCP-сервера
Cisco — DHCP-сервер запускается автоматически из конфига. Убедись что в конфиге нет no service dhcp:
show running-config | include dhcp
! Должно быть: service dhcp (или отсутствовать)
! Не должно быть: no service dhcp
MikroTik — DHCP-сервер активен пока disabled=no:
/ip dhcp-server print
# Колонка DISABLED должна быть no
/ip dhcp-server enable dhcp1
Резервное копирование DHCP-конфигурации
Что бэкапить: конфиг пулов, список опций, option sets, статические lease (если их много).
Cisco — конфиг включает DHCP-пулы в running-config:
# Сохранить конфиг на TFTP
copy running-config tftp://10.0.0.5/router-backup-2026.cfg
# Или в flash с датой
copy running-config flash:backup-20260501.cfg
MikroTik — экспорт только DHCP-части:
# Экспорт только DHCP
/ip dhcp-server export file=dhcp-options-backup
/ip dhcp-server option export file=dhcp-options-list
/ip dhcp-server network export file=dhcp-networks
# Полный системный бэкап
/system backup save name=full-backup-20260501
Как часто: после каждого изменения конфига и по расписанию раз в неделю. Хранить: минимум два последних бэкапа + один на удалённом хранилище. Проверять восстановление: хотя бы раз в квартал на тестовом стенде.
FAQ по DHCP Options
В чём разница между Option 66 и Option 150?
Option 66 — стандартная опция RFC 2132, передаёт адрес TFTP-сервера как ASCII-строку. Option 150 — Cisco-проприетарная, передаёт IP-адрес в бинарном виде. Cisco IP Phones поддерживают оба варианта. Старые модели телефонов (CP-7900 серия) понимают только Option 150. Современный Cisco UCM рекомендует Option 150. Если телефоны не находят TFTP — попробуй оба варианта, смотри через Wireshark какой клиент запрашивает в Option 55.
Может ли Option 82 использоваться без DHCP relay?
Нет. Option 82 добавляется исключительно relay-агентом при перенаправлении запроса. Клиент не добавляет Option 82 самостоятельно. Если DHCP-сервер находится в той же подсети что и клиент — relay не нужен, Option 82 не используется.
Почему Windows в домене игнорирует NTP из Option 42?
Доменные Windows-машины управляют временем через W32tm по иерархии домена. PDC-эмулятор — корневой источник времени для всего домена. Option 42 на доменных клиентах Windows игнорируется намеренно — это защита от конфликтов с доменной синхронизацией времени. Настраивай NTP на PDC через w32tm /config, остальные машины синхронизируются через него автоматически.
Как передать несколько NTP-серверов в Option 42 на MikroTik?
IP-адреса записываются подряд в hex-строке без разделителей. 192.168.1.1 = C0A80101, 192.168.1.2 = C0A80102:
/ip dhcp-server option add code=42 name=ntp-dual value=0xC0A80101C0A80102
Как проверить что DHCP-сервер отправляет нужные опции?
Wireshark с фильтром bootp. В пакете DHCP ACK раскрой Bootstrap Protocol -> Options. Каждая опция отображается с кодом, длиной и декодированным значением. Альтернатива на Linux: dhcpdump -i eth0 или tcpdump -i eth0 port 67 -vv.
Почему MikroTik не применяет опцию к клиентам?
Три самые частые причины. Первая — опция создана, но не привязана к сети (забыл dhcp-option=имя в /ip dhcp-server network set). Вторая — строковое значение без одинарных кавычек внутри двойных. Третья — клиент не запрашивает этот код опции в своём Option 55. Проверяй через /ip dhcp-server option print detail и Wireshark.
Можно ли передавать кастомные опции с произвольными кодами?
Да. Диапазон 128-254 зарезервирован для частного использования (site-specific). Если нужна опция с кодом 200 для своего приложения — создаёшь её как обычно. На Cisco:
ip dhcp pool CUSTOM
option 200 ascii "custom-value"
На MikroTik:
/ip dhcp-server option add code=200 name=my-app-option value="'custom-value'"
Клиент должен знать что запрашивать в Option 55 и как интерпретировать полученное значение. Это уже задача на уровне приложения.
Чем Kea DHCP лучше ISC DHCP Server?
ISC DHCP Server (dhcpd) фактически снят с поддержки в 2022 году. ISC Kea — его современная замена: REST API для управления, поддержка MySQL/PostgreSQL/Cassandra для хранения lease, hooks для расширения функциональности, лучшая производительность. Если поднимаешь новый Linux-сервер DHCP — ставь сразу Kea, не dhcpd.
Итог
DHCP Options — это не украшение конфига. Это разница между сетью которая просто раздаёт адреса и сетью которая работает: телефоны находят CallManager автоматически, клиенты PXE грузятся с правильного файла, время синхронизировано везде, не только там где ты помнишь настроить.
Cisco и MikroTik реализуют одни и те же RFC по-разному. На Cisco всё внутри пула, на MikroTik — опции как отдельные объекты с привязкой. Оба подхода рабочие, просто привыкаешь к синтаксису. Главное — всегда проверяй через Wireshark что реально пришло клиенту, а не только что написано в конфиге.
Если потерялся где-то в hex или Option 43 не работает — начинай с tcpdump на стороне сервера. Смотришь что пришло в Discover от клиента (Option 55, Option 60), смотришь что ушло в ACK. Девяносто процентов проблем находятся именно там.
Оставайтесь на связи
Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.
Подписаться на IT-Аптеку →


