Привет, Хабр!
Если коротко, DNS это последний открытый протокол в вашей сети, по которому провайдер (и любой джентльмен в кафе на open WiFi) видит, куда вы ходите. HTTPS закрыли, SNI потихоньку прячут через ECH, а DNS как был в плейне на 53-м порту, так в большинстве домашних сетей и остался. DoH (DNS over HTTPS) это лечит, но не на устройстве, а на роутере, чтобы один раз настроил и забыл про все смартфоны, тостеры и умные лампочки.
Я три месяца пилю свой DNS-резолвер с фильтрацией и за это время насмотрелся на чужие конфиги достаточно, чтобы написать инструкцию без воды. Разберу OpenWRT, Mikrotik (RouterOS 7+) и Asus с Merlin, плюс подводные камни, в которые я лично наступил.
В конце ссылки на бесплатный эндпойнт без регистрации, если хочется потыкать.
Зачем DoH вообще на роутере, а не на устройстве
Можно поставить DoH-клиент на ноут и считать, что готово. Я так и делал года полтора, пока не задумался про остальное барахло в сети. Телевизор LG ходит куда-то в Корею двести раз в день, плейстейшн резолвит телеметрию, робот-пылесос подключается к китайскому MQTT-брокеру и о чём-то с ним беседует. Ни на одном из этих устройств вы DoH не настроите штатно.
Роутер это единственная точка, где вся сеть выходит наружу. Настраиваешь DoH там, и:
Провайдер больше не видит DNS-запросы. Не «не может расшифровать», а буквально не видит: наружу уходит TLS-поток на 443-й порт к резолверу. Для ISP это просто HTTPS-трафик к какому-то домену.
Защита от DNS-спуфинга на open WiFi и в гостиничных сетях с отравленным аплинком. Это не теория: я ловил MITM на DNS в одном азиатском отеле в 2023-м, где
paypal.comрезолвился во что-то очень не похожее на PayPal.Обход блокировок DNS-резолверов уровня ISP. У кого-то RKN, у кого-то корпоративный фильтр, у кого-то отель режет 53-й порт целиком. На 443-м режут редко, потому что заодно умрёт половина интернета.
Единая фильтрация рекламы и трекеров для всех устройств без танцев с бубном на каждом из них. Pi-hole делает то же самое, но локально и без шифрования наружу. DoH на роутере закрывает оба фронта сразу.
Не серебряная пуля: TLS SNI и IP destination провайдер всё ещё видит. Но DNS-метаданные это самый болтливый канал, и закрыть его стоит первым.
Что нужно
Минимум:
Роутер, который умеет DoH сам или на который можно поставить
https-dns-proxy/dnscrypt-proxy/stubby. На стоковой прошивке от провайдера обычно ничего не выйдет — там в DNS можно только ввести IP-адрес и помолиться.DoH-эндпойнт. Любой подойдёт для теста: Cloudflare
https://cloudflare-dns.com/dns-query, Quad9https://dns.quad9.net/dns-query. В примерах ниже я буду использовать свойhttps://dns.vantagedns.com/<config_id>/dns-query, потому что у меня там фильтрация и статистика, но синтаксис идентичен.Доступ к роутеру по SSH или к веб-интерфейсу. Не пытайтесь делать это через мобильное приложение от вендора, оно не умеет.
Дальше по платформам.
OpenWRT
Самый чистый вариант. В OpenWRT начиная с 22.03 в репозиториях лежит https-dns-proxy, маленький бинарник, который локально слушает на 5053 и проксирует в DoH. Связка: dnsmasq отдаёт ответы клиентам, https-dns-proxy резолвит наружу.
Установка:
opkg update opkg install https-dns-proxy luci-app-https-dns-proxy /etc/init.d/rpcd restart
LuCI-модуль опциональный, но если у вас тот редкий случай, когда веб-интерфейс действительно удобнее CLI, это он.
Конфиг в /etc/config/https-dns-proxy:
config https-dns-proxy 'config' option bootstrap_dns '1.1.1.1,8.8.8.8' option resolver_url 'https://dns.vantagedns.com/abc123/dns-query' option listen_addr '127.0.0.1' option listen_port '5053' option user 'nobody' option group 'nogroup'
bootstrap_dns нужен, чтобы первоначально отрезолвить домен самого DoH-резолвера. Курица и яйцо, без этого никак.
Дальше говорим dnsmasq использовать локальный прокси как upstream. В /etc/config/dhcp секция dnsmasq:
list server '127.0.0.1#5053' option noresolv '1'
noresolv '1' отключает чтение /etc/resolv.conf, иначе dnsmasq будет шизофренически использовать ещё и DNS от провайдера, и логи будут показывать половину запросов мимо вашего DoH.
Перезапуск:
/etc/init.d/https-dns-proxy restart /etc/init.d/dnsmasq restart
Проверка:
dig @127.0.0.1 -p 5053 example.com nslookup example.com 192.168.1.1
Первая команда тестирует прокси напрямую. Вторая проверяет, что dnsmasq на роутере отдаёт ответ клиенту через DoH.
Mikrotik (RouterOS 7+)
С RouterOS 7 DoH встроен в /ip dns, и это лучшее, что Mikrotik сделал за последние пять лет (не считая вынужденного переезда на Linux-ядро в v7).
/ip dns set use-doh-server="https://dns.vantagedns.com/abc123/dns-query" verify-doh-cert=yes /ip dns set servers="" allow-remote-requests=yes
Важный момент: servers="" (пустая строка) это не баг, а лечение. Пока туда вписан хотя бы один обычный IP, RouterOS будет ходить в plain-DNS параллельно с DoH, и verify-doh-cert=yes мало что меняет, если рядом течёт незашифрованный трафик.
С verify-doh-cert=yes у Mikrotik есть нюанс: если корневые сертификаты на устройстве старые (бывает на роутерах, которые годами не обновлялись), валидация упадёт с непонятной ошибкой cant verify chain. Лечится загрузкой свежего корня:
/tool fetch url="https://curl.se/ca/cacert.pem" mode=https /certificate import file-name=cacert.pem passphrase=""
После импорта в /certificate print появится пачка корневых CA. Дальше DoH должен заработать.
Проверка с самого роутера:
/resolve example.com
Если хочется убедиться, что трафик реально идёт через 443-й порт:
/tool sniffer quick interface=ether1 port=853,443,53
В дампе на 53-м порту наружу не должно быть ничего. На 443-м должны быть TLS-сессии к домену вашего резолвера. На 853-м (это DoT) пусто, если только не настраивали отдельно.
Asus с прошивкой Merlin
Стоковая прошивка Asus не умеет DoH толком. Asuswrt-Merlin это кастомная прошивка от энтузиаста, которая совместима с большинством Asus RT-AX и старше, и в ней уже есть встроенный dnscrypt-proxy (он умеет и DNSCrypt, и DoH).
Включается в веб-интерфейсе: WAN → DNS Privacy Protocol → DNS-over-HTTPS, дальше выбираете провайдера из списка либо вписываете свой через Custom. Если вашего провайдера в списке нет (моего, например, нет, я слишком маленький), можно через SSH:
nvram set dnspriv_enable=1 nvram set dnspriv_profile=custom nvram set dnspriv_url="https://dns.vantagedns.com/abc123/dns-query" nvram commit service restart_dnsmasq
Merlin перезагружает dnsmasq и поднимает dnscrypt-proxy с вашим эндпойнтом. Логи в /tmp/syslog.log, ищите по dnscrypt.
Если у вас Asus без Merlin (стоковая) и на неё кастом не встаёт, единственный путь это поставить DoH-прокси на отдельную малинку в сети и прописать её IP как DNS на роутере. Не идеально, но работает.
Как убедиться, что DoH реально работает
Три способа, от простого к параноидальному.
Открыть https://1.1.1.1/help в браузере с устройства за роутером. Cloudflare покажет, какие протоколы видит, и через какой резолвер пришёл запрос. Если DoH работает корректно через ваш сторонний резолвер, Cloudflare скажет «Using DNS over HTTPS (DoH): No», но IP резолвера будет вашим. Это нормально, 1.1.1.1/help проверяет соединение с Cloudflare, а не вообще.
Через dig с поддержкой DoH (нужен dig из bind 9.18+, в Ubuntu 22.04 ставится через apt install bind9-dnsutils):
dig @dns.vantagedns.com +https=/abc123/dns-query example.com
Запрос напрямую через DoH без участия роутера, чтобы убедиться, что эндпойнт жив. Если ответил NOERROR и адекватный IP — значит резолвер ваш достижим и сертификат валиден. Дальше уже разбираемся с роутером.
Самый честный способ это tcpdump на WAN-интерфейсе роутера:
tcpdump -i eth1 -n port 53
Если после настройки DoH на 53-м порту наружу всё ещё что-то летит, значит какое-то устройство в сети ходит мимо роутера в публичный DNS. Чаще всего это Android с hardcoded 8.8.8.8 в каком-нибудь системном сервисе, или умная колонка. Лечится правилом firewall, которое весь исходящий 53-й порт заворачивает на роутер либо дропает.
И если у вас есть аккаунт в любом NextDNS-подобном сервисе с дашбордом (свой включая), там видно поток запросов в реальном времени. Если он есть и совпадает с тем, что вы ожидаете увидеть, всё работает.
Подводные камни
Ради этого раздела статью и стоит сохранить в закладки.
Корневой CA-сертификат. У роутеров, которые не обновлялись с 2020 года, истекли промежуточные сертификаты Let’s Encrypt и старые корни DST Root CA X3. DoH к любому резолверу на LE-сертификате будет падать с ошибкой валидации. На OpenWRT лечится opkg install ca-bundle, на Mikrotik импортом cacert.pem руками (см. выше). На Asus Merlin обычно нормально, прошивка свежая.
ISP блокирует исходящий 443-й от роутера. Видел один раз, у мобильного оператора в Юго-Восточной Азии. Решение: использовать DoH на нестандартном порту, если резолвер это умеет, или DoT (853-й), который реже режут. Большинство домашних ISP в Европе не вмешиваются.
Captive portal в кафе и отелях. Классика: подключаешься к WiFi, открываешь браузер, ждёшь redirect на страницу авторизации. Но redirect работает через DNS-spoofing на уровне точки доступа: вместо реального IP вам отдают IP captive-portal. С DoH к внешнему резолверу этот трюк не работает — DNS-ответ приходит честный, captive-portal не показывается, интернета нет, и непонятно почему. Решение либо временно отключить DoH (на ноуте проще, на роутере боль), либо использовать роутер только дома, а в дороге — отдельный профиль на устройстве.
DNS rebinding protection в OpenWRT. dnsmasq по умолчанию отбрасывает ответы, где публичный домен резолвится в RFC1918-адрес (192.168.x.x, 10.x.x.x). Это защита от DNS rebinding атак, реальная штука, не теоретическая. Но если у вас домашний домен типа nas.lan или сервис на .local, или Synology с Quick Connect, всё это начинает падать. Полностью отключать rebind_protection я бы не стал, лучше точечно через rebind_domain для нужных доменов.
Гостевая сеть. Если на роутере есть гостевой WiFi, имеет смысл сделать ему отдельный config_id (или хотя бы отдельный профиль), чтобы статистика не смешивалась с домашней. У меня дома это разные профили: «дом» с обычным AdBlock, «гости» с более жёсткой фильтрацией трекеров и без логов. На OpenWRT это делается через несколько инстансов https-dns-proxy на разных портах + правила firewall по zone.
И последнее: DoH через CGNAT и двойной NAT иногда даёт странные тайминги: handshake занимает 200+ мс на первый запрос, потом норма. Это не баг резолвера, это TLS handshake через узкий канал. Решение либо включить TLS session resumption на клиенте (https-dns-proxy умеет), либо смириться, что первый запрос после простоя будет медленным.
Что в итоге
DoH на роутере — не «хайтек», а разумный дефолт, как WPA2 был десять лет назад. Час времени, два кофе, и вы перекрыли провайдеру самый разговорчивый канал в своей сети. На OpenWRT — прозрачно, на Mikrotik с RouterOS 7 — удобно, на Asus с Merlin — терпимо.
Если хочется попробовать с фильтрацией рекламы и трекеров без регистрации:
vantagedns.com/try: DoH-эндпойнт без регистрации, выдаётся за 30 секунд, можно сразу прописать в роутер
vantagedns.com: сам сервис, free-план 300k запросов в месяц
vantagedns.com/press-kit: Pro-тариф на 90 дней бесплатно для авторов и блогеров
Если в комментариях напишете, на каком ещё железе нужна инструкция (Keenetic, pfSense, OPNsense, Ubiquiti), добавлю в следующую часть. Особенно интересно, у кого получилось завести DoH на стоковой прошивке провайдерского роутера.
