Google Public DNS тихо включили поддержку DNS over TLS
Внезапно, без предварительного анонса, на 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='1.1.1.1'},
{'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='1.1.1.1'},
{'8.8.4.4', hostname='8.8.4.4'}
})))
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
Проверяем, что локальный резолвер отвечает корректно.
Установка в качестве системного резолвера
Если все работает правильно, можно назначить системный резолвер в свойствах сетевого адаптера: