![](https://habrastorage.org/webt/re/rt/iq/rertiqvfycgdfitrxn-uqn16oja.png)
Внезапно, без предварительного анонса, на 8.8.8.8 заработал DNS over TLS. Ранее Google анонсировал только поддержку DNS over HTTPS.
Публичный резолвер от компании CloudFlare с IP-адресом 1.1.1.1 поддерживает DNS over TLS с момента запуска проекта.
Зачем это нужно
При использовании классической схемы DNS, провайдеры могут лезть своими грязными лапами в ваши DNS-пакеты, просматривать, какие домены вы запрашиваете, и подменять ответы как угодно. Этим же занимаются мошенники, подменяя резолверы на взломанных роутерах, чтобы направить пользователя на поддельный сервер.
C DNS over TLS/HTTPS запросы посылаются внутри зашифрованного тоннеля так, что провайдер не может подменить или просмотреть запрос.
А с приходом шифрования имени домена в сертификатах X.509 (ESNI) станут невозможны блокировки через DPI по SNI (Server Name Indication, специальное поле, в котором передается имя домена в первом TLS-пакете), которые сейчас применяются у некоторых крупных провайдеров.
Как это работает
На порт TCP:853 выполняется TLS-подключение, при этом проверка сертификата резолвера происходит с использованием системных корневых сертификатов, точно так же, как HTTPS в браузере. Это избавляет от необходимости добавлять какие-либо ключи вручную. Внутри тоннеля выполняется обычный DNS-запрос. Это создает меньше накладных расходов по сравнению с DNS over HTTPS, который добавляет HTTP-заголовки к запросу и ответу.
К сожалению, на текущий момент только в Android 9 (Pie) поддержка DNS over TLS встроена в системный резолвер. Инструкция по настройке для Android 9.
Для остальных систем предлагается использовать сторонний демон, а системный резолвер направлять на localhost (127.0.0.1).
Настройка на macOS
Разберем настройку DNS over TLS на последней версии macOS, на примере резолвера knot
Установка
brew install knot-resolver
По умолчанию knot будет работать как обычный рекурсивный резолвер, подобно dnsmasq.
Редактируем конфиг
nano /usr/local/etc/kresd/config
И добавляем в конец файла:
policy.add(
policy.all(
policy.TLS_FORWARD({
{'8.8.8.8', hostname='8.8.8.8'},
{'8.8.4.4', hostname='8.8.4.4'}
})))
В итоге мой конфиг выглядит так:
Раскрыть спойлер
-- Config file example useable for personal resolver.
-- The goal is to have a validating resolver with tiny memory footprint,
-- while actively tracking and refreshing frequent records to lower user latency.
-- Refer to manual: https://knot-resolver.readthedocs.io/en/latest/daemon.html#configuration
-- Listen on localhost (default)
-- net = { '127.0.0.1', '::1' }
-- Drop root privileges
-- user('knot-resolver', 'knot-resolver')
-- Auto-maintain root TA
trust_anchors.file = 'root.keys'
-- Load Useful modules
modules = {
'policy', -- Block queries to local zones/bad sites
'hints', -- Load /etc/hosts and allow custom root hints
'stats', -- Track internal statistics
'predict', -- Prefetch expiring/frequent records
}
-- Smaller cache size
cache.size = 10 * MB
policy.add(
policy.all(
policy.TLS_FORWARD({
{'8.8.8.8', hostname='8.8.8.8'},
{'8.8.4.4', hostname='8.8.4.4'}
})))
Подробнее про hostname и проверку подлинности TLS-сертификата
Параметр
Вот какие значения SAN у сертификата, который используется при подключении на 8.8.8.8:853
Любое из этих значений можно использовать в качестве параметра hostname. Если же вы будете разворачивать собственный публичный рекурсивный резолвер, у вас вряд ли получится выпустить X.509-сертификат на IP-адрес, поэтому в параметре hostname придется указывать доменное имя.
hostname
в данном случае — Common Name (CN) или Subject Alt Name (SAN) сертификата. То есть, доменное имя, для которого выпущен сертификат. По нему проверяется подлинность сертификата сервера. Вот какие значения SAN у сертификата, который используется при подключении на 8.8.8.8:853
dns.google
8888.google
8.8.4.4
8.8.8.8
2001:4860:4860:0:0:0:0:64
2001:4860:4860:0:0:0:0:6464
2001:4860:4860:0:0:0:0:8844
2001:4860:4860:0:0:0:0:8888
Любое из этих значений можно использовать в качестве параметра hostname. Если же вы будете разворачивать собственный публичный рекурсивный резолвер, у вас вряд ли получится выпустить X.509-сертификат на IP-адрес, поэтому в параметре hostname придется указывать доменное имя.
Запуск демона
sudo brew services start knot-resolver
Проверить, успешно ли запустился демон, можно командой:
sudo lsof -i -P -n | grep kresd
процесс kresd должен слушать порт 53 на localhost.
Если что-то пошло не так, смотрим лог ошибок:
cat /usr/local/var/log/kresd.log
Проверка работы резолвера
dig @127.0.0.1 habr.com
Проверяем, что локальный резолвер отвечает корректно.
Установка в качестве системного резолвера
Если все работает правильно, можно назначить системный резолвер в свойствах сетевого адаптера:
![](https://habrastorage.org/webt/wc/ez/lr/wcezlrsk9e3wep7vyimwb7uoruk.png)
UPD
В чем разница между DNSCrypt, DNSSEC, DNS over TLS/HTTPS.
DNSCrypt может работать по UDP и TCP. Подключение на порт 443. Для шифрования используется собственный протокол, который отличается от HTTPS. Может быть легко выделен с помощью DPI. Это скорее черновик, который тестировали до внедрения DNS over TLS/HTTPS, так как он не имеет RFC, то есть не является официальным стандартом интернета. Вероятнее всего, в скором, времени он будет полностью вытеснен последними.
DNS over TLS (DoT) — TCP-подключение происходит на порт 853, внутри тоннеля передается обычный DNS-запрос. Провайдер видит, что это DNS запрос но не может в него вмешаться. При прочих равных, в DNS over TLS должно быть чуть меньше накладных расходов на каждый запрос, чем в over HTTPS.
DNS over HTTP (DoH) — TCP-подключение на порт 443, подобно обычному HTTPS. Внутри другой формат запроса, с HTTP-заголовками. Однако для провайдера такой запрос будет виден как обычное HTTPS-подключение. Полагаю, этот протокол был придуман на случай, когда DNS-запросы к чужим серверам будут заблокированы, чтобы маскировать под обычный веб трафик. А также, чтобы браузеры могли сами резолвить домены и не создавать при этом аномальный трафик.
По сути, DNS over HTTPS и over TLS — одно и то же, с немного отличающемся форматом запросов. Оба эти протокола приняты в качестве стандартов и имеют RFC. Вероятнее всего, в ближайшее время мы увидим массовое распространение их обоих.
DNSSEC — протокол цифровой подписи DNS-записей. Не имеет отношения к шифрованию, так как все запросы передаются в открытом виде. Может работать как по старому классическому протоколу DNS, то есть UDP/TCP на порту 53, так и внутри DNS over TLS/HTTPS. Целью DNSSEC является подтверждение подлинности DNS-записи. Владелец домена может добавить публичный ключ на корневые сервера своей доменной зоны и подписывать все записи на мастер NS-серверах. По сути, к каждой DNS записи, например, A-записи или MX-записи, добавляется еще одна запись типа RRSIG, содержащая подпись. Процедура валидации DNSSEC на рекурсивном резолвере позволяет установить, действительно эта запись была создана владельцем домена.
Более подробное сравнение всех протоколов dnscrypt.info/faq (абзац Other protocols)