Ресурсы: техническое описание TLS, LaTeX - в картинки (img), криптографическая библиотека Arduino, шифр "Кузнечик" на ассемблере AMD64/AVX и ARM64
В Cloudflare сделали для резолвера 1.1.1.1 выдачу DNS-сигнала о том, что для заданного имени на резолвере отключена валидация DNSSEC. Речь идёт про использование так называемых NTA (Negative Trust Anchor) – это способ, позволяющий избирательно отключать валидацию DNSSEC-записей, который должен применяться в исключительных случаях, например, если DNSSEC поломалась в целой зоне первого уровня – как, всего за минувшие пару пару лет, происходило и с .RU, и с .DE, и вот совсем недавно с .AL (Албания). Сигнал об использовании NTA передаётся в расширенных кодах ошибок DNS. Нельзя сказать, что это прямо вот совсем не очередной “костыль” в процессах DNSSEC, потому что на “костыль” всё равно очень похоже, но всё же это сильно лучше, чем просто DNSSEC-валидацию тихо отключать, если “ой, оно опять сломалось”.
Кстати, о поломках DNSSEC и реалиях “технического совершенства” современных интернетов. Вот я только что привёл примеры недавних фатальных сбоев DNSSEC. И среди этих примеров: .RU и .DE. Оба – крупнейшие ccTLD. Домен Германии .DE – вообще на первом месте по количеству зарегистрированных имён, .RU – входит в пятёрку. Имён – миллионы. То есть, это давно уже не про то, что сломался какой-то где-то забытый страновой домен. Вовсе нет. Так что проблема с внедрением DNSSEC – вполне себе масштабная. Да и не только с DNSSEC, конечно.
Комментировать »
Кстати, эта странная история с t.me только очередной раз подчёркивает всю “виртуальность доменной географии”: многие думают, что, мол, домен – это строгая система, а имя – идентифицирует узел (вот и в обсуждениях про t.me такая же история: типа, “попробуйте запомнить IP”); в реальности же – это просто идентификатор в чужой базе данных, над которым нет никакого контроля у администратора: администратор лишь получает некоторую временную, иллюзорную возможность управления. Нельзя про это забывать. Особенно, если речь про некий “центральный мессенджер”, к сожалению.
Комментировать »
ACME – это протокол автоматизации, применяемый для запроса и выпуска TLS-сертификатов. Нередко заходит речь о том, как этот протокол использовать правильно, чтобы получить какие-то выгоды в плане, что называется, архитектуры безопасности. Поделюсь некоторыми соображениями, в том числе, схемой. Возможно, это будет полезно, в том числе, в качестве образовательного материала.
Прежде всего, несколько базовых моментов. Естественно, на каких-то веб-ресурсах, типа “личный сайт”, можно использовать банальный механизм – тот или иной готовый ACME-клиент, который исполняется хоть бы прямо и на той же виртуальной машине, где и сам веб-сервер. Но для мало-мальски серьёзного сервиса – такое, конечно, является неграмотным решением и недопустимо: нельзя держать вместе с веб-сервером некоторое непонятное внешнее ПО, которое, потенциально, имеет права суперпользователя и может работать с серверными секретными ключами и сертификатами (насчёт ограничений прав пользователя: тут, конечно, нельзя забывать, что в большинстве современных ОС, – в том числе, серверных, – от “обычного” пользователя до суперпользователя – дорога весьма коротка и часто пряма; впрочем, это другая тема).
Итак: нельзя держать системное ПО внешнего предназначения, да ещё и связанное с криптографическими артефактами, там же, где работает защищаемый веб-сервер, и там же, где генерируются ключи. ACME этого не требует. Напротив – под ACME можно построить безопасную архитектуру с полной автоматизацией. Однако защищённая архитектура, с разделением ролей, получается сложнее (см. схему).
Ниже мы разберёмся с тем, как не только можно разделить процесс запроса TLS-сертификата и процесс использования TLS-сертификата, но ещё и вспомним, что секретный ключ, соответствующий сертификату, можно (и нужно) унести и с машины, на которой работает TLS-сервер (это не обязательно, но именно такой вариант рассматривается ниже).
Несколько важных тезисов.
ACME-клиенту нужен доступ только до ACME-сервиса выпускающего Удостоверяющего Центра (УЦ), больше никаких доступов не требуется. То есть, не требуется ни доступ к веб-серверу, ни доступ к DNS-серверу. Понятно, что размещать код подтверждения всё равно нужно, но это может делать другой компонент – ещё раз обратите внимание: роль ACME-клиента ограничивается взаимодействием с ACME-сервисом УЦ, такое взаимодействие – необходимо, а всё остальное, что сейчас привычно навешивают на единственный клиент, является опциональным. Навешивать опциональные фукнции на ACME-клиент, в случае серьёзного сервиса, – неграмотно.
Секретный серверный ключ TLS-сервера не требуется при выпуске сертификата – этот ключ не нужно передавать в УЦ, не нужно показывать его и ACME-клиенту. В схеме, которую мы рассмотрим ниже, секретные ключи вообще хранятся на отдельном подписывающем сервере, их нет даже на TLS-узлах, принимающих входящий трафик пользователей.
Валидация права управления именем (DCV), в защищённом распределённом сервере, должна происходить строго через DNS. Поэтому мы спроектируем отдельный набор “микросервисов”, реализующих такую проверку. Прохождение DCV в ACME требует специального префикса (или “суффикса”, тут как посмотреть): _acme-challenge. Это сделано специально, поскольку позволяет вынести проверку на отдельные DNS-серверы, которые не поддерживают основную зону. Размещение DNS-записей для DCV не требует передачи ACME-клиенту каких-то ключей доступа к авторитативным серверам DNS-зоны (далее они обозначаются – NS). Мы будем использовать самый верный вариант настройки DNS – делегирование ACME-имени _acme-challenge на отдельные NS (можно размещать запись непосредственно на NS основной зоны, можно настроить и CNAME, но этот последний вариант – не рекомендуется использовать). Никакая разумная конфигурация DNS для ACME-DCV не требует передачи ACME-клиенту контроля над зоной или каких-то ключей управления, всегда можно сделать безопасную схему.
Итак, архитектурное решение для реализации выпуска и использования TLS-сертификатов при помощи ACME-автоматизации. Решение состоит из трёх основных элементов: подсистема DNS – для обеспечения DCV; основной сервис TLS – это основные узлы сервиса, куда подключаются пользователи, можно считать, что за ними стоят защищаемые веб-серверы; диспетчер ACME – для взаимодействия с внешним УЦ, заказа и получения сертификатов.
Сама схема – ниже (по клику – в большем разрешении).
В качестве примера тут зона example.com. ACME-имя _acme-challenge.example.com – делегируется на два специализированных DNS-сервера, которые предназначены для публикации кодов подтверждения в TXT-записях. Данные на эти выделенные серверы передаёт специальный сервис, роль которого состоит в получении свежих данных DCV от диспетчера ACME и в передаче этих данных на публикацию. Почему изолированы NS? Потому что они не должны иметь доступ к основной зоне. При этом, в общем случае, перехват управления этими NS-ами позволяет заказывать и выпускать сертификаты через другой ACME-аккаунт, но только в том случае, если УЦ не поддерживает указания ACME-аккаунта в CAA-записи. Дело в том, что наши специализированные NS для DCV просто не позволяют публиковать CAA-записи (тем более – в зоне уровнем выше). Поэтому применяется CAA из основной зоны, а там, предположим, указан идентификатор аккаунта, которому только разрешено заказывать сертификаты для этого имени.
Блок сервисов, связанный непосредственно с TLS (слева вверху на схеме). Обратите внимание, что здесь все операции, использующие серверный секретный ключ “от сертификата”, вынесены на специальный подписывающий сервер. Речь про секретный ключ, соответствующий открытому ключу в сертификате сервера. Вообще, при установлении TLS-соединения сам этот договременный секретный серверный ключ не требуется, требуется возможность подписывания сессии (значения хеш-функции). Понятно, что для вычисления подписи секретный ключ нужен, но само его значение никакой роли в TLS-соединении не имеет. А цифровая подпись, при установлении TLS-соединения, требуется всего один раз. (Тут речь строго про современную схему TLS 1.3, где использование RSA для передачи сессионного секрета прямо запрещено, и такой секрет должен вычисляться по протоколу Диффи-Хелмана.)
Поэтому операции подписи могут быть прозрачно вынесены на защищённый сервер, где будет доступ к секретному ключу. При такой схеме – веб-сервер не знает секрета от TLS-сертификата. Такой “бесключевой” TLS вполне возможен и используется в решениях с повышенными требованиями безопасности. (Но для ACME это не является обязательным, так что, в принципе, если наладить такой вариант не получается, поскольку он показался слишком сложным, то можно объединить управление ключами с веб-сервером.)
Блок TLS на схеме содержит “микросервис” под названием “Формирователь CSR”. CSR – это файл запроса на сертификат. Этот файл, помимо других параметров, содержит открытый ключ сервера для включения в сертификат и цифровую подпись от этого же ключа. Именно по причине наличия подписи наш формирователь CSR должен иметь доступ к подписывающему серверу: подготовив блок CSR, формирователь запрашивает подпись у этого сервера и присоединяет значение подписи к блоку CSR. Получившийся файл можно использовать в ACME-клиенте для запроса сертификата (после прохождения DCV – см. ниже). Обратите ещё раз внимание: секретного ключа “от сертификата” тут нет ни у формирователя CSR, ни у TLS-узлов – что уж говорить про ACME-клиент.
ACME-клиент в этой схеме взаимодействует только с ACME-сервисом УЦ, где, по команде от программы-диспетчера, исполняемой отдельно, запрашивает DCV и сертификаты. Как описано выше – коды подтверждения передаются через диспетчер на публикацию в контур DNS. При штатной работе, после того, как TXT-записи опубликованы, ACME-клиент запросит проверку на стороне УЦ и DNS-резолвер УЦ обратится к DNS, чтобы получить по независимому каналу значение кода DCV из TXT-записи – это соответствует оранжевой стрелке внизу схемы.
Посмотрим ещё раз на шаги алгоритма выпуска TLS-сертификата, при штатной работе.
***
1.
Диспетчер (см. схему) получает CSR с актуальными данными от формирователя CSR (подпись от защищённого сервера, с актуальным ключом, в CSR – нужное DNS-имя).
2.
Диспетчер отправляет в ACME-клиент запрос на DCV (CSR на этом шаге в ACME не требуется, но будет нужен ниже).
2.1. ACME-клиент инициирует взаимодействие с УЦ через ACME-аккаунт (возможно, используя отдельное хранилище ключа от ACME-аккаунта – см. схему; зачем это может быть нужно – возможно, распишу в отдельной записке; главное – не забывайте, что ACME-аккаунт существует, там есть секретный ключ и он тоже важен).
2.2. ACME-клиент запрашивает прохождение DCV (проверка права управления DNS-именем) на стороне УЦ и получает код подтверждения, который требуется разместить в DNS.
2.3. ACME-клиент передаёт этот код подтверждения (DCV-код) диспетчеру, оджидает публикации кода в TXT-записи.
3.
Диспетчер формирует файлы данных с актуальным кодом подтверждения (DCV-код) и ожидает публикации (у диспетчера нет прямого доступа к сервису подготовки TXT-записей, напротив – тот сервис периодически сам проверяет статусдиспетчера, определяет, не нужно ли разместить новые записи).
4.
Сервис подготовки TXT-записей забирает ткущий код DCV из обменной области диспетчера.
5.
Сервис подготовки TXT-записей направляет команду публикации TXT-записей авториативным серверам специализированной зоны _acme-challenge и получает подтверждение публикации.
6.
Если публикация TXT прошла успешно, сервис подготовки TXT-записей направлет подтверждение диспетчеру.
7.
Диспетчер отправляет команду фактического запуска DCV ACME-клиенту и ожидает получения сертификата (если проверка пройдёт успешно).
8.
ACME-клиент запрашивает фактическую проверку DCV у УЦ (через ACME-API) и начинает периодический опрос статуса заказа на стороне УЦ (ожидание выпуска сертификата – это свойство ACME).
9.
Если DCV завершилась корректно и успешно, то ACME-клиент получает от диспетчера CSR и запрашивает новый сертификат для подтверждённого имени (или для нескольких имён). Обратите внимание: обычно, у ACME УЦ есть некоторый период, в течение которого действует пройденная DCV. Это означает, что запросить новый сертификат можно без DCV, если срок валидности прошлой успешной проверки для этих же имён не закончился. В описании и на схеме этот момент не учитывается – он не имеет принципиального значения.
10.
Если сертификат успешно выпущен, то ACME-клиент скачивает его и возвращает диспетчеру. Диспетчер подготавливает полный набор промежуточных сертификатов, нужный для успешного использования. Промедуточные сертификаты либо можно получить через ACME-клиент, если УЦ это поддерживает, либо скачать по ссылкам в оконечном, серверном сертификате (этот последний метод – гораздо надёжнее). Диспетчер валидирует цепочку сертификатов, перед тем, как передать её дальше.
11.
Диспетчер размещает новый сертификат и цепочку промежуточных в обменной области, откуда их могут забрать либо сами TLS-узлы, либо промежуточный узел, реализующий “деплой” сертификатов. Вариант с таким промежуточным узлом на схеме не показан (тем не менее, я бы сказал, что это предпочтительный вариант).
12.
TLS-узлы забирают новый сертификат из обменной области диспетчера и устанавливают его на TLS-сервер (с дополнительной проверкой валидности по цепочке). Обратите внимание, что секретный ключ уже настроен на стороне подписывающего сервера – TLS-узлам лишь нужно переключиться на новый идентификатор ключа, который они используют при запросе подписи. Секретный ключ уже настроен потому, что он необходим для получения подписи на CSR.
13.
Переход на новый сертификат завершился.
***
Управление расписанием получения новых сертификатов, график замены ключей – остаются за пределами данного описания. Так же, как и процесс отзыва сертификата (возможно, напишу отдельно). Не забывайте, что в ACME не существует таких функций как “перевыпуск” или “продление” TLS-сертификата – это довольно частая терминологическая ошибка. ACME подразумевает, что клиенты всегда обращаются за новым сертификатом.
Комментировать »
В продолжение предыдущей записки, про dns.1d.pw. Вот как серверы данной зоны видны со стороны сервиса проверки – есть DNS over TLS на всех узлах:

Комментировать »
Сделал специальный сервис для DNS – dns.1d.pw. Не торопитесь кликать – там нет A-записи, это именно что DNS-сервис, но он полезен для отладки и поиска причин возникновения проблем. Смысл вот в чём: если спросить в DNS TXT-запись для dns.1d.pw, то в ответ вернётся информация о том, как виден со стороны авторитативного сервера DNS-резолвер, который выполнил DNS-запрос. Вот простейший пример (здесь и далее используется утилита dig из пакета BIND):
$ dig dns.1d.pw -t TXT +short "ns: dns-b" "transport: UDP" "src: [2a04:e4c0:10::145]:63761" "target [id]: dns.1d.pw. [34301]"
Спрашивать нужно именно TXT: с A-записью – не получится. Кроме TXT – поддерживается только минимум: SOA и NS.
Ответ состоит из нескольких TXT-записей. Выясним, – пока кратко, – что в них видно (по порядку сверху вниз, как в примере):
внутренне имя авторитативного сервера, который обработал запрос (dns-b);
транспорт (UDP), по которому сервер получил запрос и ответил резолверу (то есть, не вашему клиенту, а именно резолверу);
IP-адрес узла, приславшего запрос, и номер порта ([2a04:e4c0:10::145]:63761); Здесь IPv6-адрес – сервис, естественно, поддерживает IPv6 тоже;
целевое имя, как его было видно в DNS-запросе, и код ID DNS-сообщения (dns.1d.pw. [34301]); дальше я объясню, почему это важно, хотя, казалось бы, имя и так известно.
И это не все параметры, которые присылает данный сервис.
Подобные сервисы существуют, и достаточно давно. Например, есть “очки” от Google: o-o.myaddr.google.com – показывает адрес резолвера и состав ECS, есть “пробник” от Akamai: whoami.ds.akahelp.net, и другие. Понятно, что у этих сервисов – свои ограничения. Например, я разу добавил поддержку DNS over TLS, поскольку данную технологию можно использовать между резолвером и авторитативными серверами (естественно, поддержка авторитативными серверам – редкость, но тем не менее).
Итак, технический смысл затеи: DNS-зона dns.1d.pw делегирована на специально разработанные NS-серверы, которые собирают данные о запросе, упаковывают их в TXT-записи, и отправляют в ответ. Такой способ позволяет информации пройти по цепочке, через резолвер. То есть, при штатной схеме работы, рекурсивный опрос для клиента выполняет рекурсивный резолвер, и именно это резолвер, в конце DNS-поиска, пришлёт запрос на авторитативный сервер. Например, если воспользоваться Google Public DNS, то мы увидим IP-адрес из пула DNS-сервисов Google (пример для 8.8.8.8):
$ dig @8.8.8.8 dns.1d.pw -t TXT +short "ECS: 185.39.19.0/24/0" "ns: dns-b" "src: 74.114.29.150:43267" "target [id]: dns.1d.Pw. [2909]" "transport: UDP"
Обратите внимание, здесь добавилась информация о подсети источника запроса – ECS: 185.39.19.0/24/0. Это именно источник того запроса, который поступил в систему Google, а сервис DNS-резолвинга Google пронёс эту адресную информацию до авторитативного сервера. То есть, если вы используете сервис 8.8.8.8, то, – при прочих равных, – авторитативные серверы видят номер вашей подсети (обычно, это подсеть интернет-провайдера). Авторитативные серверы DNS – это не серверы Google, а подсеть видна даже в том случае, если прочий трафик завёрнут в VPN.
Кроме сведений о префиксе ECS, этот второй пример содержит другой адрес источника: 74.114.29.150 – IPv4-адрес резолвера Google. Сервис Google может приходить за DNS-данными и по IPv6, и по IPv4.
Приглядитесь к записи целевого имени – dns.1d.pw: при вызове dig имя записано строчными буквами, но в TXT-записи вернулось dns.1d.Pw (заглавная P). Именно так имя увидел авторитативный сервер. Что это? Это называется “рандомизация регистра символов” – один из дополнительных факторов защиты от спуфинга ответов, который применяет Google. Если воспользоваться аналогичным сервисом Cloudflare (1.1.1.1), то “рандомизации регистра” не случится:
$ dig @1.1.1.1 dns.1d.pw -t TXT +short "target [id]: dns.1d.pw. [33389]" "ns: dns-a" "src: [2400:cb00:78:1024::ac44:b97b]:24308" "transport: UDP"
Чтобы наблюдать такие эффекты и требуется возврат исходного имени в TXT-ответе. Дело в том, что изменяет имя резолвер, поэтому, без подобных хитростей, на DNS-клиенте резолвера обнаружить изменения нельзя.
Второй фактор защиты от спуфинга тоже можно видеть на распечатке выше: это номер транзакции (id – 33389). Сервер должен ответить с тем же номером, который отправил DNS-клиент в запросе. Третий типовой фактор – номер порта-источника (особенно актуально в UDP). Запросы в DNS отправляются на номер порта 53 (udp, tcp) и 853 (DNS over TLS), а номер порта-источника, соответственно, рандомизируется (должно быть сложно его угадать).
Сервис можно использовать для того, чтобы увидеть собственный внешний IP и параметры собственных DNS-запросов. Для этого нужно выступить в роли резолвера, направив DNS-запрос непосредственно узлу данного сервиса. Имена можно узнать, запросив список NS:
$ dig @8.8.8.8 dns.1d.pw -t NS +short ns-dns-a.1d.pw. ns-dns-b.1d.pw.
Спрашиваем напрямую ns-dns-a.1d.pw:
$ dig @ns-dns-a.1d.pw dns.1d.pw -t TXT +short "target [id]: dns.1d.pw. [31841]" "ns: dns-a" "src: 185.39.19.199:26283" "transport: UDP"
Получили в “src” IP-адрес, с которого отправлен локальный запрос (точнее: тот адрес, который видит внешний сервис – потому что может быть NAT и тому подобные штуки).
Основной транспорт для DNS – это UDP. Однако необходима и поддержка TCP. Сервис dns.1d.pw умеет отвечать по TCP. Да, контролировать протокол, который использует внешний резолвер, так просто не выйдет, но при локальнй подготовке запроса можно выбрать TCP при помощи флага +tcp утилиты dig. Проверяем:
$ dig @ns-dns-a.1d.pw dns.1d.pw -t TXT +short +tcp "target [id]: dns.1d.pw. [9376]" "ns: dns-a" "src: 185.39.19.199:50169" "transport: TCP"
Теперь указан TCP в качестве транспорта. TLS – не является обязательным. Однако это современная и весьма популярная технология, которая тут тоже поддерживается. Более того, сервис возвращает “расширенную информацию” – данные о версии TLS, о шифронаборах, о выбранном имени узла (SNI). Утилита dig поддерживает TLS (+tls). Проверяем:
$ dig @ns-dns-a.1d.pw dns.1d.pw -t TXT +tls +short "target [id]: dns.1d.pw. [22366]" "ns: dns-a" "src: 185.39.19.199:59527" "transport: TLS (1.3/X25519MLKEM768/TLS_CHACHA20_POLY1305_SHA256)" "SNI: ns-dns-a.1d.pw"
Обратите внимание: здесь в записи имени DNS-узла – ns-dns-a.1d.pw – нельзя указывать крайнюю справа точку (которая превратила бы запись в FQDN, и которая для специалистов в DNS является чем-то само собой разумеющимся). Дело в том, что бэкенд сервиса использует реализацию TLS из типовой библиотеки Go. А типовая, “коробочная”, реализация TLS в Go строго не допускает финальные точки в составе хостнейма внутри расширения SNI – TLS-соединение просто не устанавливается. Такое поведение библиотеки, вообще говоря, вопрос весьма дискуссионный, но к теме этой записки он не относится: просто – не указывайте точку в конце, или используйте IP-адрес узла напрямую (возможно, я как-нибудь этот момент переделаю самостоятельно, ну или разработчики Go одумаются).
Вообще, TLS-сертификаты для авторитативных серверов, используемых в данном проекте, я выпустил через Let’s Encrypt, и это сертификаты для IP-адресов (v4/v6), что неплохо подходит для случая TLS на авторитативном DNS-сервере. А раз это сертификаты для IP-адресов, то для хостнеймов они так и так не валидны, но по умолчанию – dig здесь сертификаты и не проверяет на соответствие имён.
В поведение авторитативного сервера заложены и некоторые другие особенности, так что он не полностью соответствует “лучшим практикам” DNS, и это сделано специально. Например, как отмечено выше, в ответ на запрос A-записи – придёт ответ с флагом REFUSED, а это позволяет посмотреть на расширенные статусы DNS-ошибок, если запросить А-запись через сервис Google.
Комментировать »
Всё чаще попадаются попытки внедрения IPv6-only (только IPv6) веб-узлов. И всё чаще встречается типовая техническая ошибка, этот процесс сопровождающая: для DNS-имени, указывающего на веб-узел, присутствует только AAAA-запись (то есть, только IPv6-адрес), но при этом все авторитативные серверы имён (NS) соответствующей доменной зоны – имеют только A-записи, только v4-адреса. В некотором роде – это удивительное техническое противоречие, граничащее с “карго-культом”: с v4 – доступ к такому сайту получить невозможно, так как нет адресной записи, но и получить v6-доступ, не воспользовавшись v4, тоже невозможно – потому что необходимо обратиться по v4-адресам NS.
IPv6 – не такой уж плохой протокол: многое там сделано даже логичнее практики v4. Но внедрять его “эксклюзивность” нужно аккуратно. Естественное и правильное решение для NS – добавить для авторитативных серверов IPv6-адреса, обеспечить по ним доступность DNS, а уж потом запускать IPv6-эксклюзивный веб-узел под AAAA-записью. Потому что тогда, при верном выборе зоны, все необходимые прикладные процессы смогут работать по IPv6, который уже заслуженно будет в приоритете (в корневой зоне DNS – IPv6 есть). Конечно, при наличии полной поддержки и v6, и v4 на клиенте – запрашивать нужно сразу и A, и AAAA-запись, отдавая приоритет AAAA при соединении. Но если есть только v4, то возникают дополнительные сложности.
Формально, ничего не запрещает не держать в DNS-зоне A-записи, а держать только AAAA, но раздавать эти AAAA исключительно через четвёртую версию протокола. Однако выглядит такая настройка максимально некрасиво, совсем не так, как IPv6-адреса на NS, и только A-запись – для веб-узла.
Более того, ситуация, когда на клиенте нет полноценного IPv6, а в целевой зоне – нет A-записи, и при этом сведения об отсутствии такой записи можно получить только через v4, вполне может трактоваться клиентом как отсутствие IP-доступа к веб-узлу совсем, вне зависимости от версии IP: нет адресной записи и – всё. И такой сигнал отсутствия даже может кешироваться на клиенте, перекрывая повторный доступ после того, как IPv6 на клиенте включился (конечно, в рамках той же сессии прикладного ПО, но такое – вполне возможно, так как сетевой интерфейс с полноценным v6 мог подняться позже, по команде пользователя). Дело в том, что после включения v6 можно было бы спросить AAAA-запись в DNS, но этому мешает флаг “отсутствует адресная запись”, уже установленны прикладным или системным ПО, который флаг, предположим, является универсальным, то есть, не зависит от версий v4/v6.
(Бывают, кстати, и другие “косые” ситуации: в vk.com, например, IPv6-адреса у авторитативных NS есть, но вот только DNS по ним не отвечает.)
Комментарии (2) »
Нужно ли использовать DNSSEC? Хотелось бы просто написать: да. Но, к сожалению, многолетняя история данной технологии уже обставлена особенностями, которые не позволяют написать просто “да”.
Напомню, кратко, что такое DNSSEC: это технология, позволяющая удостоверять адресную информацию в DNS при помощи механизмов цифровой подписи. Основная особенность DNSSEC в том, что она пристраивает к “классической DNS” схему делегирования по криптографическим ключам, которая позволяет транслировать доверие между зонами, по иерархии. То есть, в “классической DNS” используется делегирование по именам авторитативных серверов: зона уровнем выше содержит имена серверов, которые отвечают за зону уровнем ниже. Например, если у нас есть example.com., то в зоне com. указывается перечень имён серверов (NS), которые администрация зоны com. уполномочила отвечать за example.com.
В DNSSEC нет делегирования по серверам имён (делегирующие ответы со списком NS даже не подписываются), но есть делегирование по криптографическим ключам, которые служат для проверки подписей: зона уровнем выше содержит отпечаток ключа для зоны уровнем ниже; в примере с example.com – в зоне .com размещается отпечаток целевого ключа к зоне example.com, при этом сам целевой ключ – находится только на серверах зоны example.com. Такое размещение ключа – важная особенность DNSSEC, которая несколько меняет логическое отношение зон разного уровня. Отпечаток ключа – это DS-запись, находящаяся в зоне уровнем выше, а сам ключ – это DNSKEY-запись, находящаяся в делегируемой зоне. Отпечаток должен сойтись со значением ключа. Связь “DS –> DNSKEY” – это и есть (безопасное) делегирование в DNSSEC. Это делегирование работает параллельно классическому делегированию по именам NS. (Кстати, с DS-записями связаны самые распространённые ошибки настройки DNSSEC в DNS-зонах.)
Нередко приходится слышать, что, мол, “у нас зона не подписана”, и поэтому “нас DNSSEC не касается”. Это не совсем так. В большинстве случаев, DNSSEC – касается “неподписанных” зон. Дело в том, что в DNSSEC подписывается и отсутствие делегирующих DNSSEC-записей – DS-записей. Иначе смысл данной технологии был бы полностью утрачен, так как можно было бы просто удалить из DNS-ответов DNSSEC-данные и – всё выглядело бы как “неподписанная” зона. Поэтому, если у вас зона example.com, но сама она не подписана, то DNSSEC на вашу зону всё равно распространяется, поскольку подписана зона уровнем выше – .com. То есть, в зоне .com криптографически удостоверен факт того, что в вашей зоне – нет доверенной DNSKEY-записи, а поэтому для вашей зоны удостоверен факт отсуствия DS-записи.
Что это означает? Это означает, что если для example.com радикально сломается DNSSEC в зоне com., то и ваша зона example.com окажется недоступна для валидирующих резолверов (“валидирующий” – это DNS-резолвер, проверяющий DNSSEC-записи). Сейчас очень многие используют валидирующие резолверы, поскольку DNSSEC валидируют крупнейшие провайдеры: Google Public DNS, Cloudflare 1.1.1.1 и др. Штатный опрос DNS начинается с корневого домена и обязательно проходит через зоны первого уровня. Поэтому, к сожалению, даже если у вас домен пятого (условно говоря) уровня внутри небезопасной зоны, для которой DNSSEC нет даже в зоне на два уровня выше, рекурсивный опрос всё равно где-то будет касаться зон с DNSSEC. (Пример, как говорится, “на символах”: 5.4.www.example.com – предположим, что DNSSEC тут нет уже в example.com, но это не помогает, если подписи сломались в .com). Поэтому DNSSEC влияет на вашу зону, даже если у вас в зоне нет DNSSEC-подписей, поскольку на каком-то уровне путь к вашей зоне – подписан, как небезопасный. Естественно, это не распространяется на невалидирующие резолверы: вот им – всё равно.
К сожалению, практическая “ломкость” DNSSEC, регулярно приводящая к авариям больших зон первого уровня, привела и к тому, что складывается нехорошая практика отключения DNSSEC на стороне валидирующих резолверов, если обнаружилась какая-то масштабная проблема. Есть соответствующий документ RFC 7646, который прямо предписывает так делать (кто бы мог подумать? представьте, что для TLS была бы спецификация, предписывающая “всё равно продолжить”, если ошибка “ожидаемая”; да; зато вот в DNSSEC – есть). Формально, речь там идёт о том, что оператор DNS-резолвера должен убедиться, что “эта нога – у кого надо нога!” (то есть, что сломалось там, где положено ломаться), и только потом отключать валидацию для конкретного поддерева (подмножества) DNS-зон. И, судя по сообщениям Cloudflare, именно так этот провайдер и поступил, когда поломались подписи в зоне первого уровня .de (крупнейший национальный домен).
Проблема тут в том, что практика типа “сигнализация опять зашумела – просто отключи”, поднятая на уровень спецификаций, не очень-то помогает развитию и внедрению криптографических технологий. Представьте, что через сервис Cloudflare домены большой популярной зоны резолвятся, а через небольшой корпоративный резолвер – нет, не резолвятся. Почему? Потому что Cloudflare смогли переговорить с большим оператором большой популярной зоны по своим каналам, и отключили DNSSEC у себя, решив, что “это не атака” (почему? как? нет ответа). А администратор небольшого корпоративного резолвера – не имеет возможности проверить все детали. Собственно, на следующем шаге и администратор небольшого резолвера просто отключает DNSSEC совсем, для всего, чтобы “не морочить голову себе и пользователям”. Ну и кому такая криптография нужна? Риторический вопрос. Тем более, когда есть TLS.
Что касается TLS и DNSSEC. Да, эти технологии задают совсем разные поверхности атаки: если DNSSEC работает, и работает верно, то, при обнаружении подмены адресной информации, до применения TLS даже не дойдёт дело. Но это только если DNSSEC работает. А если эту технологию отключают крупнейшие провайдеры, чтобы “пользователи могли заходить на сайты” в сломанной зоне, то, как бы, рассуждать про поверхности атаки становится сильно сложнее. Заметьте, что при этом нет спецификаций, предписывающих “отключать валидацию TLS-сертификатов по команде с сервера обновлений браузера”, если вдруг у крупного удостоверяющего центра “сломались ключи”. Естественно, у TLS другая архитектура и поломка “корневого оператора” пока что не может так повлиять на доступность, как в случае с DNS. Хотя, тут слова “пока что” я использовал неспроста: как только глобальная инфраструктура TLS для HTTPS перейдёт на сертификаты с хеш-деревьями, без подписей, то сразу возникнет похожая на DNS ситуация с раздачей промежуточных “аретфактов доверия”. Пойдёт ли тогда та же корпорация Google, как поставщик наиболее распространённых веб-браузеров, по схеме под условным названием “исправленному верить”? Не факт, но, как говорится, посмотрим: времена сейчас новые, так что всякое может приключиться, поди как и аутентификацию узлов в TLS избирательно отключат.
Вернёмся к DNSSEC в доменной зоне. Распространено ещё такое мнение, что наличие DNSSEC ухудшает работу электронной почты, если домен является почтовым. В отличие от мнения про “независимость от DNSSEC”, это мнение гораздо более обосновано и граздо ближе к реальности. Действительно, такое возможно. Это, буквально, ещё один “неожиданный эффект” DNS. Может показаться, что хотя бы при отправке почты DNSSEC не влияет: ну, какая разница, что там в DNS-зоне, если при отправке почты наш почтовик идёт на внешний сервер напрямую? А имена и адреса внешнего сервера – они в другой зоне. Это так, но вот только сейчас принимающий сервер, в подавляющем большинстве случаев, будет запрашивать записи из зоны отправителя. Например, SPF-записи, или TXT-записи с ключами DKIM, или ещё что-то. Если в зоне DNSSEC не работает, а принимающий почту сервер валидирует DNS-ответы, то он не сможет все эти записи получить. Ну а с доставкой почты в подписанный домен – должно быть очевидно: уже извлечение MX-записи затрагивает DNSSEC. Так что, да, на почту DNSSEC влияет. И в качестве бонуса тут идёт описанный выше момент: от DNSSEC всё равно не отделаться полностью, а отсутствие DNSSEC в собственной зоне лишь уменьшает шансы эту DNSSEC собственноручно же сломать, и “почётная” обязанность отламывания подписей – передаётся выше, по делегированию.
Тем не менее, DNSSEC сейчас поддерживается распространённым ПО “из коробки”. Внедрить DNSSEC в собственной зоне для тестирования можно без автоматического размещения DS-записей, это означает, что ключи и подписи в зоне будут, можно проверить их “сходимость”, но без привязки в глобальную цепочку. Главное – не перепутать шаги: DS-записи вообще нельзя размещать в вышестоящей зоне до того, как целевая зона корректно подписана. Ну и если, после неудачного опыта, отказались от DNSSEC в DNS-зоне, то нужно не забыть корректно почистить DS-записи. Как и раньше, забытые DS-записи – самая распространённая ошибка.
Итак, нужно ли использовать DNSSEC? Нужно. Однако прежде необходимо определить – можно ли.
Комментировать »
Хроники разваливающихся интернетов. Я, в силу ряда причин, использую DNS-резолвер, который установлен за пределами Рунета. С некоторых пор я заметил, что ряд вспомогательных сервисов для аккаунта Google – недоступны из браузера, из моей локальной сети. А я всё ещё использую для ряда задач почту Google – так исторически сложилось, тем более, что, в отличие от того же “Яндекса”, Google мне пока что эту историческую почту и кучу прочих сервисов под моим доменом (из Рунета, заметьте) предоставляет бесплатно, как ни странно; не знаю, долго ли ещё так будет, но пока что – так; недостатки там тоже есть, кто бы сомневался, но это другая история: а сервис, как минимум, никто за эти десятилетия у меня не отобрал – очень существенный плюс Google, по нынешним временам-то.
Вернёмся, впрочем, к доступности.
Итак, я заметил, что какие-то сервисы через HTTPS недоступны, а они необходимы для нормальной работы веб-интерфейса (там всё управление – через веб). Логичное предположение: так как мой резолвер приходит на авторитативные серверы Google из “иностранной сети”, ему DNS Google отдаёт другие IP-адреса, а именно – адреса, предназначенные для соответствующего региона; и узлы под этими IP-адресами – недоступны из российских сетей. Почему это влияет? Потому что браузером-то я подключаюсь из российской IP-сети. Где именно соответствующий трафик забанен – я уже не стал разбираться: сейчас подобное разбирательство – легко превращается в длительное исследование, так как понять, “что-как-где-почему”, довольно сложно: сети окончательно стали мутными на прикладном уровне. Да, я делал бы ставку на то, что забанено на российском транзите; но, к сожалению, тут нельзя полностью исключать и сторону CDN Google – вообще говоря, агрессивная геобалансировка на стороне крупнейших провайдеров была известна и раньше, иногда, скажем, такая блокировка может быть побочным эффектом маршрутизации для anycast-адресов (отдельная история).
В общем, я просто добавил на сторне своего DNS-резолвера функцию отправки подсети-источника DNS-запроса в ECS, но только для доменов внутри зоны google.com, чтобы авторитативные DNS-серверы на той стороне видели целевой IP-префикс запроса. В Unbound (весьма рекомендую, кстати) избирательная поддержка ECS легко включается. После того, как в запросы добавились ECS – IP-адреса в ответных A-записях стали приходить другие, а сервис Google – тут же заработал из локальной сети. Да, откровенно говоря, не могу исключить, что это совпадение, но посмотрим: в других, – более прозрачных, но аналогичных, – случаях, с которыми я сталкивался, подход с перенастройкой резолвера срабатывал эффективно.
Комментировать »
DNSSEC строится на механизмах цифровой подписи и на иерархии криптографических ключей. Открытые ключи публикуются в DNSKEY-записях. Подписи вычисляются для адресной информации, опубликованной в зоне. Значения подписей публикуются в RRSIG-записях. Ключей и, соответственно, DNSKEY-записей в DNS-зоне может быть несколько. Чтобы доверенным образом проверить подпись, резолвер должен выбрать подходящий ключ. Чтобы упростить поиск подходящего ключа – в RRSIG-записях указывается 16-битный тег, соответствующий ключу. Это и есть тег ключа DNSSEC. (Тег ключа используется также в DS-записи, которая обеспечивает другой важнейший аспект: делегирование в DNSSEC, но ниже речь пойдёт только про RRSIG.)
Значение тега представляет собой простейшую “контрольную сумму” – то есть, сумму октетов DNSKEY-записи, выполненную в определённом порядке (чётные/нечетные и т.д.). Очевидно, что используемый алгоритм вычисления тега тут вообще не имеет особого значения – в теге всего 16 битов, а в ключе, как минимум, 256 битов: коллизии тут всегда будут достигаться легко.
Практический смысл добавления некоего “алгоритма суммирования” несколько тёмен. Понятно, что сумма позволяет побороть варианты, когда в каких-то криптосистемах некоторые части в записи ключей принципиально одинаковые. Но это, обычно, не так. Поэтому можно было бы с почти тем же успехом, например, брать два байта на нечётных средних позициях записи непосредственно ключа (примерно так и было сделано для тегов алгоритма подписи RSA/MD5); да, ещё нужно учитывать флаги ключа, но и это не сильно влияет на практику. В общем, как бы там ни было, но DNSSEC сейчас использует теги, вычисляемые как сумма.
Если теги разных ключей в зоне не совпадают (обычно, в добропорядочной зоне, это так и есть, но см. ниже), а в RRSIG – указано верное значение, то, конечно, это ускоряет процесс выбора ключа и проверки подписи. Проблема в том, что вычислительные затраты на проверку подписи по “пробному ключу” сильно меньше, чем затраты на обработку специально неверно сконфигурированной зоны с совпадающими тегами ключей. И ещё хуже, что неверная интерпретация свойств тегов регулярно приводит к масштабным сбоям в практике DNSSEC – отламываются целые большие TLD (это было в зоне .RU, это же теперь было и в .DE, которая в несколько раз больше).
Вообще говоря, выбор ключа при валидации записей, в имеющейся конфигурации DNS, так или иначе, но проводится при помощи “пробных операций проверки подписи”: дело в том, что RRSIG-запись считается доверенной только в том случае, если в зоне нашёлся хотя бы один доверенный ключ, которым удалось успешно проверить подпись. Если ключей не нашлось, то вообще не важно, какие были значения у тегов и RRSIG – доверенной информация в DNS-зоне быть уже не может.
Естественно, штатный способ выбора ключа состоит в сравнении тегов: если в зоне единственный ключ с совпавшим значением тега, и этот ключ не даёт доверенной подписи для заданной RRSIG-записи, то, понятно, другие ключи можно не проверять. Почему? Потому что спецификация требует, чтобы тег, указанный в RRSIG, совпадал с тегом ключа. Заметьте, что нигде не сказано, что соответствие должно быть один к одному – тег-ключ. Но даже в случае такого совпадения, это всё равно будет пробная проверка подписи – просто, в штатной конфигурации, используется единственная итерация. Всё потому, что тег не обязательно соответствует одному ключу.
Из обратной ситуации, то есть, из того, что ключи должны соответствовать тегам, но разные ключи могут иметь одинаковый тег, и выводится DoS-атака: в зоне может быть несколько ключей с одинаковыми значениями тега и резолвер должен перебирать эти ключи для проверки RRSIG, которая теперь ссылается единственным тегом на множество ключей. При этом, RRSIG-записей может быть много. И криптосистем тоже может быть несколько. Это известная DoS-атака под названием KeyTrap (CVE-2023-50387).
А из обобщения принципа, что теги недопустимо использовать в качестве идентификаторов ключей при вычислении подписи (а лишь как первый шаг, сужающий набор для перебора, при проверке подписи) и публикации ключей в DNS-зоне, выводится угроза штатной подмены ключа в процессе подписывания зоны: из-за того, что схему ломает единственное совпадение пары значений тегов, вероятность совпадения для разных ключей, результатом которого будет сбой – очень и очень велика. То есть, в схеме подписи, для её вычисления, использовался один ключ, но где-то рядом сохранился второй ключ, с совпавшим тегом, и в зоне будет опубликован этот второй, неподходящий ключ. Но неподходящий он – по значению подписи, не по значению тега – значение тега-то, как раз, подходит под RRSIG, а поэтому простая проверка на соответствие тегов, на уровне, что в зоне есть ключи с тегами из RRSIG, успешно пройдёт. К сожалению, из-за особенностей DNSSEC, такая проверка имеет весьма небольшую пользу: ключи должны строго и по тегу сходиться, и по подписи.
Комментировать »
В DENIC опубликовали некие сведения о причинах недавней поломки DNSSEC в зоне .DE (DENIC – оператор). Как ни странно, но, похоже, причина именно в некорректном использовании тегов ключей. Я как раз в прошлой записке по этой теме такое и предположил: “возможно, тоже перепутали ключ из-за совпадающих тегов”. Выходит, что снова использовали теги для индексирования ключей в процессе подписи. Теги – могут запросто совпадать у разных ключей. К сожалению, как это нередко бывает, в опубликованном пояснении формулировка расплывчатая:
Consequently, for the same “key tag” (33834), three different key pairs were generated instead of a single one, of which only the public key of a single pair was stored in the DNSKEY RR, meaning that only about a third of the RRSIG RRs could be validated. (В результате, для одинакового “тега ключа” (33834) были сгенерированы три разных ключевых пары вместо одной, из которых только открытый ключ единственной пары был размещён в DNSKEY-записи, что привело к тому, что только треть из RRSIG-записей могли быть валидированы.)
Ну, то есть, можно предположить, что раз только треть валидировалась, значит – остальное подписывалось другими секретными ключами, из пар, имевших один и тот же тег открытого ключа, а ПО ссылалось на ключи по значению тега (чего делать при подписывании нельзя категорически). Тут может возникнуть сомнение: как же тогда так получилось, что для трёх разных ключей совпал тег? Да, чтобы тег заведомо совпал для ключей, сгенерированных на небольшом интервале времени, ключи нужно специально перебирать (но и это нетрудно – там всего-то 16 битов в теге). Но дело в том, что ключи подписи зоны постоянно заменяются при штатной работе, так что эти пары с совпавшими тегами скорее всего были старыми ключами, сгенерированными ранее, и не удалёнными из системы. Теги же совпадут с большой вероятностью, так или иначе, если просто генерировать ключи штатным образом – только будет несколько дольше по времени: вероятность там много больше, чем 1/65535, как продолжают думать, – ведь это типовое воплощение парадокса дней рождения.
Собственно, в недавней записке об аварии DNSSEC в .DE я поэтому и упомянул конфликты тегов ключей DNSSEC, которые теги используют не по назначению. Цитата:
В DNSSEC выбрана неудачная система тегирования ключей при помощи 16-битных номеров, которые, понятно, то и дело совпадают для разных ключей; данные теги нельзя использовать в качестве индекса при выборе ключей для подписи, об этом написано в RFC, об этом много писал и говорил я, и не только я, но теги всё равно регулярно используют с такой целью; однако насчёт данного случая с DE – не факт, что в этом была проблема.
Оказалось – в этом и была проблема. Что тут ещё сказать? Бывает, конечно: ведь с пониманием сложных процессов – сейчас трудности везде.
Комментировать »
В домене .DE на некоторое время сломались подписи DNSSEC. Сейчас уже пишут, что починили. Возможно, тоже перепутали ключ из-за совпадающих тегов. (Лирическое отступление: в DNSSEC выбрана неудачная система тегирования ключей при помощи 16-битных номеров, которые, понятно, то и дело совпадают для разных ключей; данные теги нельзя использовать в качестве индекса при выборе ключей для подписи, об этом написано в RFC, об этом много писал и говорил я, и не только я, но теги всё равно регулярно используют с такой целью; однако насчёт данного случая с DE – не факт, что в этом была проблема.)
Интересна тут реакция Cloudflare, как оператора одного из самых распространённых в этих интернетах сервиса DNS-резолвинга – 1.1.1.1: в Cloudflare, после локализации ошибки на стороне DE, валидацию DNSSEC для этой зоны просто отключили. Ну, то есть, очередной пример реальной ценности DNSSEC в современой глобальной DNS: если что не так, то систему валидации принято отключать; но, конечно, не просто так отключать, а информированно отключать.
Есть даже RFC 7646, который, кто бы мог подумать, прямо предписывает так делать. Естественно, речь тут идёт об операторах DNS-сервисов, которые могут убедиться, что, мол, “это не атака подмены”, а это DNSSEC сломали сами администраторы ключей, очередной раз. Хотя, строго говоря, достоверно определить, что подписи стали расходиться не из-за атаки, а из-за ошибки – весьма и весьма сложно: атака могла быть на уровне оператора реестра, например. Может ли тут что-то с уверенностью – и, главное, быстро, – сказать внешний наблюдатель, даже если он оператор резолвера? Ну, это вряд ли. Остаётся полагаться на ответы оператора реестра и, что называется, кликать виртуальную универсальную кнопку “Всё равно продолжить” для всех пользователей своего “валидирующего” резолвера. Такая вот нынче стала на практике эта технология – DNSSEC. Ничего не поделать.
Комментировать »

Новый