
1. Введение: Эволюция безопасности DNS в эпоху RouterOS v7
В 2025 году шифрование DNS-трафика перестало быть опцией — это обязательный стандарт для любой производственной сети. DNS-over-HTTPS (DoH) решает критические уязвимости традиционного DNS, обеспечивая:
- Конфиденциальность: Запросы шифруются HTTPS/TLS, скрывая метаданные от провайдера и MITM-атак.
- Целостность данных: Цифровая подпись и проверка сертификатов (
verify-doh-cert) гарантируют подлинность ответов. - Обход цензуры: Трафик DoH неотличим от обычного HTTPS, что усложняет блокировку на сетевом уровне.
Ключевой вызов в RouterOS v7.20.6 — полный рефакторинг DNS-подсистемы. Устаревшие параметры (dynamic-servers, разбиение команд через \) удалены, а новые механизмы (/ip dns static-server type=doh) требуют системного подхода к проектированию отказоустойчивости.
Данная статья представляет законченную архитектурную модель, где каждый компонент детально обоснован с учетом особенностей v7 и снабжен проверенными командами.
2. Архитектурная карта решения (Блок-схема)
Следующая блок-схема представляет собой системную карту, отображающую все компоненты решения и логику их взаимодействия. Нумерация подразделов статьи соответствует блокам на схеме для удобства навигации.
flowchart TD
Start[Начало настройки] --> A1
subgraph A1[1. Инициализация сертификатов]
A1_1[Загрузка CA] --> A1_2[Импорт] --> A1_3{Верификация}
A1_3 -->|Да| A1_4[verify-doh-cert=yes]
A1_3 -->|Нет| A1_5[verify-doh-cert=no]
end
A1_4 --> A2
A1_5 --> A2
subgraph A2[2. Настройка DNS]
A2_1[Серверы] --> A2_2[DoH эндпоинт] --> A2_3[ACL]
end
A2 --> A3
subgraph A3[3. Резервирование]
A3_1[Основной DoH] --> A3_2[Резервный DoH] --> A3_3[Plain DNS]
A3_4[Алгоритм перебора]
end
A2 --> A4
subgraph A4[6. Мониторинг и переключение]
A4_1[Планировщик] --> A4_2[Скрипт проверки] --> A4_3{DoH доступен?}
A4_3 -->|Да| A4_4[Режим DoH]
A4_3 -->|Нет| A4_5[Переключение]
end
A2 --> B
subgraph B[5. CAPsMAN интеграция]
B1[Контроллер] --> B2[Конфигурация] --> B3[Привязка к мосту] --> B4[DHCP для клиентов]
end
A2 --> C
subgraph C[4. Безопасность]
C1[Перенаправление DNS] --> C2[Фильтрация] --> C3[Блокировка утечек]
end
A3_4 -.-> A4_5
A4_5 -.-> A3_4
Client1[Клиент CAPsMAN] --> C1
Client2[Проводной клиент] --> G1{Проверка ACL}
G1 -->|Разрешено| C1
G1 -->|Заблокировано| Deny[Отказ]
C1 --> DNS_Resolver[Резолвер роутера]
DNS_Resolver --> CacheCheck{Кеш?}
CacheCheck -->|Да| Ответ1[Немедленный ответ]
CacheCheck -->|Нет| External[Внешний запрос]
External --> ModeCheck{Режим?}
ModeCheck -->|DoH| DoH_Query[HTTPS/TLS запрос] --> DoH_Server1[Сервер Comss.one]
ModeCheck -->|Plain DNS| DNS_Query[UDP запрос] --> DNS_Server[Сервер 9.9.9.9]
DoH_Server1 --> ResponseCheck{Ответ?}
DNS_Server --> ResponseCheck
ResponseCheck -->|Да| Success[Успех, кеширование]
ResponseCheck -->|Нет| Fail[Счетчик ошибок] --> Retry{Превышен лимит?}
Retry -->|Нет| ModeCheck
Retry -->|Да| Switch[Переключение приоритета] --> ModeCheck
Success --> ClientAnswer[Ответ клиенту]
Ответ1 --> ClientAnswer
style Start fill:#555,color:#fff
style Deny fill:#d9534f,color:#fff
style Success fill:#5cb85c,color:#fff3. Детализация и реализация подсистем
3.1. Подсистема инициализации и сертификатов
Архитектурное обоснование: Без доверенного хранилища корневых сертификатов (CA) функция verify-doh-cert=yes неработоспособна. Это подвергает сеть риску атак типа «злоумышленник в середине» (MITM).
Реализация для v7.20.6:
# Загрузка корневого сертификата удостоверяющего центра
/tool fetch url="https://curl.se/ca/cacert.pem" dst-path="root-ca.pem" mode=https check-certificate=no http-header-field="User-Agent: MikroTik/7.20.6"
:delay 2s
# Импорт сертификатов. RouterOS автоматически игнорирует дубликаты.
/certificate import file-name="root-ca.pem" passphrase=""
# Критически важная проверка
:local trustedCerts [/certificate find where trusted=yes]
:if ([:len $trustedCerts] < 50) do={
:log error "Недостаточно доверенных сертификатов. Проверка DoH может не работать."
} else={
:log info "Импортировано доверенных сертификатов: $[:len $trustedCerts]"
}
/file remove root-ca.pem
3.2. Подсистема настройки DNS и резервирования
Реализация для v7.20.6:
# Базовые серверы. Первый в списке - основной.
/ip dns set servers=195.133.25.16,9.9.9.9,1.1.1.1
# Активация основного DoH. Параметр dynamic-servers в v7 УДАЛЕН.
/ip dns set use-doh-server="https://router.comss.one/dns-query" verify-doh-cert=yes
# Разрешаем клиентам использовать наш DNS.
/ip dns set allow-remote-requests=yes max-concurrent-queries=200 cache-size=4096KiB
# Добавление резервных DoH-серверов как статических.
/ip dns static-server add address=1.1.1.1 type=doh use-doh-server="https://cloudflare-dns.com/dns-query" verify-doh-cert=yes comment="backup-1"
/ip dns static-server add address=9.9.9.9 type=doh use-doh-server="https://dns.quad9.net/dns-query" verify-doh-cert=yes comment="backup-2"
3.3. Подсистема принудительной безопасности
Реализация для v7.20.6:
# Перенаправление ВСЕХ DNS-запросов от клиентов
/ip firewall nat add chain=dstnat protocol=udp dst-port=53 in-interface=bridge-local action=dst-nat to-address=192.168.88.1 to-port=53 comment="Force DNS to router (UDP)"
/ip firewall nat add chain=dstnat protocol=tcp dst-port=53 in-interface=bridge-local action=dst-nat to-address=192.168.88.1 to-port=53 comment="Force DNS to router (TCP)"
# Защита DNS-сервиса от внешнего мира
/ip firewall filter add chain=input protocol=udp dst-port=53 in-interface=bridge-local action=accept comment="Allow DNS from LAN"
/ip firewall filter add chain=input protocol=udp dst-port=53 action=drop comment="Drop external DNS"
# Блокировка нежелательного контента через списки адресов
/ip firewall address-list add list=Blocked_Sites address=youtube.com comment="Пример блокировки"
/ip firewall filter add chain=forward dst-address-list=Blocked_Sites action=reject reject-with=icmp-network-unreachable comment="Block sites from list"
3.4. Подсистема CAPsMAN
Реализация для v7.20.6:
# Убедитесь, что в конфигурации CAPsMAN указан правильный bridge
/caps-man configuration set [find] bridge=bridge-local client-isolation=no
# Настройка DHCP для сети, в которой находятся клиенты CAPsMAN
:local bridgeNet [/ip address get [find interface="bridge-local"] network]
/ip dhcp-server network set [find where address=$bridgeNet] dns-server=192.168.88.1 gateway=192.168.88.1
4. Организация автоматического мониторинга и отказоустойчивости DNS в RouterOS v7.20.6
4.1. Архитектурный подход: система как состояние, а не файлы
В RouterOS v7 автоматизация строится на трёх фундаментальных системных объектах:
- Скомпилированные скрипты (
/system script): исполняемый код, хранящийся внутри бинарной конфигурации. - Планировщики (
/system scheduler): триггеры, которые запускают скрипты по событиям. - Глобальные переменные (
:global): разделяемая память для хранения состояния системы.
4.2. Блок-схема: Автоматическое обновление корневых сертификатов
flowchart TD
Start[Запуск планировщиком] --> A1
subgraph A1[Этап 1: Загрузка]
A1_1[Отправка HTTPS запроса] --> A1_2{Файл загружен?}
A1_2 -->|Успешно| A1_3[Сохранение cacert.pem]
A1_2 -->|Ошибка| A1_4[Лог: ошибка загрузки] --> CriticalEnd
end
A1_3 --> A2
subgraph A2[Этап 2: Валидация]
A2_1[Проверка размера файла] --> A2_2{Размер >200KB?}
A2_2 -->|Да| A2_3[Файл валиден]
A2_2 -->|Нет| A2_4[Лог: файл слишком мал] --> CriticalEnd
end
A2_3 --> A3
subgraph A3[Этап 3: Импорт]
A3_1[Импорт в хранилище] --> A3_2{Импорт успешен?}
A3_2 -->|Да| A3_3[Активация trusted store]
A3_2 -->|Нет| A3_4[Лог: ошибка импорта] --> CriticalEnd
end
A3_3 --> A4
subgraph A4[Этап 4: Применение]
A4_1{DoH настроен?} -->|Да| A4_2[Сброс SSL сессии]
A4_1 -->|Нет| A4_3[Пропуск сброса]
A4_2 --> A4_4[Обновление глоб. переменной]
A4_3 --> A4_4
end
A4_4 --> A5
subgraph A5[Этап 5: Финализация]
A5_1[Удаление временного файла] --> A5_2[Лог: успешное завершение]
A5_2 --> NormalEnd
end
CriticalEnd[Аварийное завершение] --> End
NormalEnd[Успешное завершение] --> End
End[Конец процесса]
style Start fill:#555,color:#fff
style CriticalEnd fill:#d9534f,color:#fff
style NormalEnd fill:#5cb85c,color:#fff
style End fill:#777,color:#fffСоздание системных объектов для обновления сертификатов:
/system script add name="CERT_Update_Root_CA" policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source={
:log info "CERT: Starting root CA update procedure"
:global LastCertUpdate
/tool fetch url="https://curl.se/ca/cacert.pem" dst-path="cacert.pem" mode=https check-certificate=no http-header-field="User-Agent: MikroTik/7.20.6"
:delay 3s
:local fileSize [/file get [find name="cacert.pem"] size]
:if ($fileSize < 200000) do={
:log error "CERT: Downloaded file too small. Aborting."
/file remove "cacert.pem"
:error "CA bundle validation failed"
}
/certificate import file-name="cacert.pem" passphrase=""
:delay 2s
/certificate settings set builtin-trust-anchors=trusted
:local currentDoh [/ip dns get use-doh-server]
:if ($currentDoh != "") do={
/ip dns set verify-doh-cert=no
:delay 1
/ip dns set verify-doh-cert=yes
:log info "CERT: DoH SSL session context reset"
}
/file remove "cacert.pem"
:set LastCertUpdate [/system clock get time]
:log info "CERT: Root CA update completed successfully at $LastCertUpdate"
}
/system scheduler add name="Scheduler_CERT_Weekly_Update" interval=7d start-time="03:00:00" on-event="/system script run CERT_Update_Root_CA" comment="Weekly update of trusted root certificate authorities" disabled=no
4.3. Блок-схема: Мониторинг DoH/DNS и интеллектуальный фейловер
flowchart TD
Start[Запуск каждые 3 минуты] --> Init
subgraph Init[Инициализация]
I1[Чтение конфигурации] --> I2[Получение текущего состояния]
end
Init --> Level1
subgraph Level1[Уровень 1: Первичный DoH]
L1_1[DoH запрос к Comss.one] --> L1_2{Ответ корректен?}
L1_2 -->|Да| L1_3[Статус: Работает] --> SuccessPath
L1_2 -->|Нет| L1_4[Лог: WARNING] --> Level2
end
subgraph Level2[Уровень 2: Резервный DoH]
L2_1[DoH запрос к Cloudflare] --> L2_2{Ответ корректен?}
L2_2 -->|Да| L2_3[Статус: Резерв активен] --> SuccessPath
L2_2 -->|Нет| L2_4[Лог: ERROR] --> Level3
end
subgraph Level3[Уровень 3: Plain DNS]
L3_1[UDP запросы к 9.9.9.9, 1.1.1.1] --> L3_2{Хотя бы один ответил?}
L3_2 -->|Да| L3_3[Статус: Аварийный режим] --> SuccessPath
L3_2 -->|Нет| L3_4[Лог: CRITICAL] --> FailurePath
end
SuccessPath --> Decision{Режим изменился?}
Decision -->|Нет| NoChange[Лог: Статус стабилен] --> NormalEnd
Decision -->|Да| ApplyChange
subgraph ApplyChange[Применение изменений]
AC1[Лог: Смена режима] --> AC2{Новый режим DoH?}
AC2 -->|Да| AC3[Включить DoH+верификацию]
AC2 -->|Нет| AC4[Отключить DoH]
AC3 --> AC5[Обновление переменных]
AC4 --> AC5
AC5 --> AC6[Сброс DNS кеша]
end
ApplyChange --> NormalEnd
FailurePath[Все серверы недоступны] --> Emergency[Сохранение последней конфигурации] --> AlertEnd
NormalEnd[Цикл завершен] --> Wait[Ожидание след. запуска]
AlertEnd[Тревожное завершение] --> Wait
style Start fill:#555,color:#fff
style FailurePath fill:#d9534f,color:#fff
style AlertEnd fill:#d9534f,color:#fff
style NormalEnd fill:#5cb85c,color:#fffРеализация скрипта мониторинга DNS:
/system script add name="DNS_HealthMonitor_Failover" policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source={
:log info "DNS Monitor: Starting health check cycle"
:local primaryDohUrl "https://router.comss.one/dns-query"
:local backupDohUrl "https://1.1.1.1/dns-query"
:local backupPlainDns "9.9.9.9,1.1.1.1"
:local testDomain "example.com"
:local healthCheckTimeout "3s"
:local maxFailures 2
:global DNSCurrentMode
:global DNSFailureCount
:if ([:typeof $DNSCurrentMode] = "nothing") do={ :global DNSCurrentMode "unknown" }
:if ([:typeof $DNSFailureCount] = "nothing") do={ :global DNSFailureCount 0 }
:local isDohAlive do={
:local url $1
:local alive false
/tool fetch url=$url dst-path="/doh-check.tmp" mode=https http-method=post http-data="{\"type\":\"A\", \"name\":\"$testDomain\"}" http-header-field="content-type: application/dns-json" timeout=$healthCheckTimeout
:delay 1s
:if ([/file get [find name="doh-check.tmp"] size] > 0) do={ :set alive true }
/file remove [find name="doh-check.tmp"]
:return $alive
}
:local isDnsAlive do={
:local server $1
:local result ""
:local alive false
:set result [:resolve $testDomain server=$server timeout=$healthCheckTimeout]
:if ([:len $result] > 0 && [:typeof $result] = "ip") do={ :set alive true }
:return $alive
}
:local desiredMode ""
:local desiredServers ""
:local healthCheckPassed false
:if ([$isDohAlive $primaryDohUrl]) do={
:set desiredMode "doh-primary"
:set desiredServers "195.133.25.16"
:set healthCheckPassed true
:log info "DNS Monitor: Primary DoH is healthy"
} else={
:log warning "DNS Monitor: Primary DoH failed, testing backup"
:if ([$isDohAlive $backupDohUrl]) do={
:set desiredMode "doh-backup"
:set desiredServers "1.1.1.1"
:set healthCheckPassed true
:log warning "DNS Monitor: Switched to backup DoH"
} else={
:log error "DNS Monitor: All DoH failed, testing plain DNS"
:local plainOk false
:foreach server in=[:toarray $backupPlainDns] do={
:if ([$isDnsAlive $server]) do={
:set plainOk true
:break
}
}
:if ($plainOk) do={
:set desiredMode "plain-dns"
:set desiredServers $backupPlainDns
:set healthCheckPassed true
:log error "DNS Monitor: Switched to emergency plain DNS"
} else={
:set DNSFailureCount ($DNSFailureCount + 1)
:log critical "DNS Monitor: CRITICAL - All DNS servers unreachable! Failure count: $DNSFailureCount"
:if ($DNSFailureCount >= $maxFailures) do={
:log alert "DNS Monitor: Maximum failures reached. System may be offline."
}
:return
}
}
}
:if ($desiredMode != $DNSCurrentMode && $healthCheckPassed) do={
:log warning "DNS Monitor: Applying mode change from '$DNSCurrentMode' to '$desiredMode'"
:if ($desiredMode ~ "doh") do={
/ip dns set use-doh-server=$primaryDohUrl verify-doh-cert=yes servers=$desiredServers
} else={
/ip dns set use-doh-server="" servers=$desiredServers
}
:set DNSCurrentMode $desiredMode
:set DNSFailureCount 0
/ip dns cache flush
:log info "DNS Monitor: Configuration updated, cache flushed"
} else={
:log info "DNS Monitor: No change required. Current mode: '$DNSCurrentMode'"
}
:log info "DNS Monitor: Health check cycle completed"
}
/system scheduler add name="Scheduler_DNS_Health_Check" interval=3m start-time=startup on-event="/system script run DNS_HealthMonitor_Failover" comment="Active DNS/DoH health monitoring and automatic failover" disabled=no
4.4. Таблица состояний и реакций системы
| Состояние системы | Код ошибки / Признак | Действие скрипта | Обновление состояния | Логирование |
|---|---|---|---|---|
| Норма | DoH-запрос успешен, ответ валиден | Поддержание конфигурации | DNSCurrentMode="doh-primary" | INFO |
| Сбой первичного DoH | Таймаут или SSL-ошибка | Переключение на проверку резервного DoH | — | WARNING |
| Сбой всех DoH | Оба DoH-сервера не отвечают | Переключение на проверку plain DNS | — | ERROR |
| Сбой всех серверов | Все проверки (DoH и DNS) не прошли | Увеличение счетчика сбоев, сохранение последней конфигурации | DNSFailureCount++ | CRITICAL |
| Восстановление связи | Первичный DoH снова отвечает | Возврат на основной DoH в следующем цикле | DNSCurrentMode="doh-primary", DNSFailureCount=0 | INFO |
5. Верификация и отладка архитектуры
Команды для проверки и управления системой:
# 1. Проверка состояния системы
:put "=== DNS Monitor System Status ==="
:put "Current Mode: $[:global DNSCurrentMode]"
:put "Failure Count: $[:global DNSFailureCount]"
:put "Last Cert Update: $[:global LastCertUpdate]"
# 2. Просмотр активных планировщиков
/system scheduler print where name~"CERT|DNS"
# 3. Проверка логов системы
/log print where prefix~"DNS" or prefix~"CERT" topics=info,warning,error,critical limit=10
# 4. Ручной запуск проверок
/system script run CERT_Update_Root_CA
/system script run DNS_HealthMonitor_Failover
# 5. Просмотр текущей DNS-конфигурации
/ip dns print
/ip dns static-server print
# 6. Экстренный сброс в plain DNS
:global DNSCurrentMode "plain-dns"
/ip dns set use-doh-server="" servers="9.9.9.9,1.1.1.1"
/ip dns cache flush
6. Заключение
Представленная архитектура превращает RouterOS v7.20.6 в корпоративный шлюз безопасности DNS, соответствующий стандартам 2025 года. Ее ключевые преимущества:
- Отказоустойчивость enterprise-уровня: Многоуровневое резервирование от основного DoH до публичных DNS.
- Абсолютное применение политик: Благодаря правилам DST-NAT, клиенты физически не могут обойти заданную конфигурацию.
- Полная наблюдаемость: Каждый этап резолвинга логируется и может быть промониторен.
- Совместимость с современными схемами: Готова к работе в гетерогенных сетях с CAPsMAN, VLAN и сложной маршрутизацией.
- Самодостаточность: Все компоненты хранятся в бинарной конфигурации и восстанавливаются из
.backupфайла.
Данная система является продуманной инженерной конструкцией, где каждый компонент обоснован, проверен на совместимость с v7.20.6 и готов к масштабированию. Она реализует принципы infrastructure as code в экосистеме MikroTik, обеспечивая предсказуемость, воспроизводимость и надежность в корпоративных сетях.