Практическое применение DNSSEC

img4f45033e7eef1 - Практическое применение DNSSEC

В статье описываются недостатки существующей структуры DNS, полный процесс внедрения DNSSEC на примере доменов .com и .org, процедура создания валидного самоподписанного SSL-сертификата подписанного с помощью DNSSEC.

Система DNS в нынешнем виде была разработана более 20 лет назад, когда о защите информации не особенно задумывались. Она имеет несколько фундаментальных уязвимостей.

Достоверность ответа DNS-сервера никак не проверяется. Это позволяет отправить пользователя, обратившегося к доменному имени, на произвольный IP-адрес, подменив ответ сервера. На практике подобная атака может выглядеть так .

Также уязвимы кеширующие DNS-серверы провайдеров, выступающие как резолверы для клиентов: Атака Каминского .

Сегодня существуют технологии, предусматривающие хранение открытых ключей в DNS-записях, например, DKIM-подписи в электронной почте, SSH-ключей в записях SSHFP и т.д. Все эти технологии требуют защиты от подделки DNS.

DNSSEC — технология, позволяющая однозначно удостовериться в подлинности DNS информации при помощи криптографической подписи.

Популярно о DNSSEC можно прочитать здесь: dxdt.ru/2009/03/04/2163/

Более подробно здесь: habrahabr.ru/blogs/sysadm/120620/

Перед продолжением настоятельно рекомендуется внимательно прочитать вышеприведенные ссылки, так как на первый взгляд процедура подписания зоны кажется довольно запутанной.

Максимально упрощенно это выглядит примерно так: есть корневая зона «.», которая содержит в себе информацию о всех доменах первого уровня. Условно говоря, это текстовый файл с некоторым множеством строк, который изменяется не очень часто. Создается пара открытый/закрытый ключ и каждая строка в этом файле подписывается (по типу «clear sign» в PGP/GPG, которая используется в электронной почте для открытого подписания текста и начинается с «BEGIN PGP SIGNATURE»).

Теперь, имея открытый ключ от этой пары, можно удостовериться в подлинности каждой записи в этом списке. Например, проверить, что за зону «ru.» действительно отвечают серверы ripn.net:

dig -t any +dnssec @k.root-servers.net ru.

В ответе можно увидеть запись RRSIG содержащую хеш-подпись.

Но этого недостаточно, так как в резолве участвуют нижестоящие серверы, ответы которых тоже нужно верифицировать. Тогда владельцы домена верхнего уровня, например «com.», создают такую же пару ключей и подписывают все записи в своей зоне, и после этого добавляют слепок своего открытого ключа в корневую зону. В результате доверяя открытому ключу корневой зоны можно проверить подлинность ключа зоны «com.» и, соответственно, доверять ему:

dig -t any +dnssec @k.root-servers.net com.

В ответе запись DS содержит слепок ключа, которым подписывается зона «com.»

Важно понимать, что после каждого изменения в зоне подписание происходит заново. Но, так как корневая зона подписывает только открытый ключ зоны «com.», то нет необходимости перехешировать записи в корневой зоне при каждом изменении в зоне «com.»

Теперь можно установить подлинность ответов от серверов, ответственных за домен «com.»:

dig +dnssec -t any @a.gtld-servers.net verisign.com.

Видно, что запись о домене verisign.com. подписана, но на этом этапе возможно установить только подлинность адресов NS-серверов, ответственных за домен verisign.com. Для резолва IP-aдреса необходимо получить ответ от них, поэтому владельцы этих NS-серверов имеют свою пару ключей, которыми подписывают зону и помещают слепок открытого ключа в DS-запись.

Запрашиваем A-запись для домена verisign.com.:

В результате, для проверки подлинности факта, что А-запись verisign.com содержит значение 192.5.6.31 выстраивается такая цепочка доверия:

нам заранее известен открытый ключ корневой зоны «.» и мы ему доверяем. В корневой зоне существует DS-запись о том, что все записи зоны «com.» подписаны указанным в ней ключом и сама запись, соответственно, подписана ключом корневой зоны. Проверив подлинность этой записи, мы доверяем всем записям в зоне «com.», подписанным этим ключом. На серверах, ответственных за зону «com.» содержится DS-запись с открытым ключом verisign.com, подписанная ключом зоны «com.», что позволяет проверить подлинность подписи в ответе NS-сервера, ответственного за verisign.com.

Схематически это выглядит так:img4f45033ea7506 - Практическое применение DNSSEC

Приведенное выше описание достаточно примитивно и нелепо. Оно написано с целью объяснить принцип работы «на пальцах». Вероятно, оно нисколько не упростит понимание, а только еще больше запутает.

На текущий момент подписаны только некоторые доменные зоны верхнего уровня, в частности: .net, .com, .org.

Зона .ru до сих пор не подписана, зона .ua подписана в режиме тестирования, зона .su официально подписана, но до сих пор ни один регистратор не поддерживает добавление DS-записей.

Для подписания своей зоны эта возможность должна поддерживаться регистратором домена. На текущий момент мне неизвестны отечественные регистраторы поддерживающие DNSSEC. Регистратор R01 и сайт dnssec.ru, которые рекламирует делегирование доменов .ru с поддержкой DNSSEC абсурдны, потому что сама зона .ru не подписана и, в таком случае, отправной точкой для построения цепочки доверия становится сервер R01.

Из поддерживающих можно выделить наиболее крупных:

Неполный список можно посмотреть здесь .

Кроме регистратора, необходимы NS-серверы с поддержкой DNSSEC. Некоторые регистраторы предоставляют такие услуги. Самый дешевый вариант у Godaddy называется Premium DNS 35$/год. Самый дорогой у dyn.com называется DynECT Lite 30$/месяц. В этой статье будет показан пример настройки собственного master DNS-сервера на базе BIND 9.7.3.

Далее предполагается, что у нас уже есть домен, делегированный на собственные, полностью настроенные DNS, и готовый файл зоны.

Для включения поддержки DNSSEC в named.conf в секцию options нужно добавить:

options { … dnssec-enable yes; … };

Инструменты для генерации ключей и подписания зон входят в пакет BIND последних версий.

На этом этапе предполагается, что читателю уже известно что такое ZSK (Zone Sign Key) и KSK (Key Sign Key).

Все приведенные ниже операции необходимо проводить в отдельно созданной папке.

Генерация ключа ZSK:

Генерация ключа KSK:

где my-domain.com — домен для которого генерируются ключи. В результате выполнения этих команд будут созданы две пары ключей.

Далее необходимо скопировать файл зоны в текущую папку и выполнить подписание:

где my-domain.com — текстовый файл зоны. Важно выполнять команду, находясь в одной папке с ключами и файлом зоны; имя файла указывать без пути.

В результате будут созданы два файла:

dsset-my-domain.com — файл содержащий две DS-записи

Исходный файл зоны останется без изменений. Далее в конфиге BIND необходимо заменить файл на подписанный:

zone «my-domain.com» { type master; file «my-domain.com.signed»; allow-query { any; }; allow-transfer { ….; }; };

Развернутые примеры файлов зон можно посмотреть на nox.su .

Чтобы повысить отказоустойчивость своих DNS, рекомендуется использоваться secondary серверы. Cуществует несколько бесплатных сервисов предлагающих slave-серверы с поддержкой DNSSEC. Вот неполный список http://www.frankb.us/dns/ . Я использую rollernet.us, поэтому разрешаю трансфер с адресов 208.79.240.3 и 208.79.241.3. При использовании secondary-серверов, записи о них должны присутствовать в файле зоны еще до подписания. Я рекомендую активировать трансфер уже после того как на master-сервере будет находиться подписанная зона.

Далее предполагается, что подписанная зона уже размещена на авторитарном NS-сервере и доступна снаружи:

dig +dnssec -t any @super.vip.my.dns.com my-domain.com

Команда должна вернуть подписанную зону.

На этом этапе можно активировать secondary сервера и синхронизировать зону по AXFR.

Далее необходимо добавить DS-записи в панели регистратора домена. Они были сгенерированы при выполнении dnssec-signzone и находятся в файле dsset-my-domain в таком виде:

Так выглядит форма добавления DS-записей в панели GoDaddy:

img4f45033ebf344 - Практическое применение DNSSEC

Необходимо переключиться в «Advanced mode» и скопировать обе строки, предварительно отредактировав. Нужно добавить значение TTL и удалить пробел во второй строке в отпечатке ключа, иначе форма вернет ошибку. В результате копируемые строки должны выглядеть так:

Записи будут добавлены только в случае если зона на master-сервере доступна и подписана правильно.

Значения полей в DS-записи:

В приведенном выше примере при генерации ключей был использован алгоритм RSA-SHA1, поэтому запись имеет номер пять.

Таблица номеров алгоритмов:

Digest Type в приведенном примере у первой записи равен 1, во второй 2.

Таблица номеров Digest Type:

У некоторых регистраторов, например Dyn.com, форма добавления DS-записи не предусматривает копирование строк, а требует заполнения всех полей отдельно:

img4f45033ed53d5 - Практическое применение DNSSEC

Из-за того, что у Dyn.com список алгоритмов расположен не по порядку и не отмечен номерами, это вызывает некоторую путаницу. При добавлении через эту форму так же нужно удалить пробел в отпечатке второго ключа.

После добавление DS-записей можно проверить их появление на серверах, ответственных за домен верхнего уровня. Для домена «com.» это выглядит так:

dig +dnssec -t DS @a.gtld-servers.net my-domain.com

В момент, когда это произойдет, можно проверить правильность подписания зоны с помощью DNSSEC Debugger от Verisign и визуализатора цепочки подписания .

Напомню, что после каждого изменения в записях зоны, необходимо выполнять подписание повторно. DS-записи при этом обновлять не нужно.

Если всё правильно, можно переходить к настройке клиентской части.

Для проверки подписей на стороне клиента, эту функцию должен поддерживать системный DNS, через который происходит резолв адресов. Публичный DNS от Google 8.8.8.8 поддерживает передачу DNSSEC записей, но не производит их верификацию. Подробнее написано в FAQ .

Наиболее простой вариант — плагин для Firefox и Chrome .

img4f45033ee9e9d - Практическое применение DNSSEC

Плагин позволяет производить резолв в обход системных DNS, имеет свои предустановленные серверы с поддержкой валидации DNSSEC. По умолчанию плагин использует системные DNS, изменить это можно в настройках плагина: выбрать CZ.NIC’s или 217.31.57.6

Для того, чтобы научить утилиту dig проверять подпись, необходимо создать отправную точку в цепочке доверия, создав файл с ключом корневой зоны:

dig +nocomments +nostats +nocmd +noquestion -t dnskey . > trusted-key.key

Теперь можно проверять подлинность подписей с помощью dig:

Как настроить рекурсивный резолвер с функцией проверки подписей можно прочитать здесь

Не смотря на то, что стандарт DNSSEC до сих пор находится в разработке, уже возможно извлекать из него пользу.

При первом подключении к серверу SSH клиент просит самостоятельно проверить отпечаток публичного ключа сервера и ввести yes, после чего публичный ключ сервера сохраняется в файле known_hosts.

С появлением DNSSEC публичный ключ может быть помещен в DNS-запись типа SSHFP и, при первом подключении к серверу, проверяться автоматически без запроса. Для активирования этой функции нужно добавить опцию VerifyHostKeyDNS=yes в конфиг SSH-клиента, также необходимо чтобы системный резолвер поддерживал верификацию DNSSEC.

С помощью DNSSEC можно самостоятельно подписать SSL-сертификат который будет «валидным» в браузере.

Эта экспериментальная функция на данный момент находится в активной разробтке и пока поддерживается только браузером Google Chrome/Chromium.

Черновой вариант стандарта: tools.ietf.org/html/draft-agl-dane-serializechain-01

Технология разрабатывается сотрудником Google по имени Адам Лэнгли (Adam Langley), он ведет очень интересный блог http://www.imperialviolet.org/ .

Пост об этой технологии.

Далее предполагается, что домен для которого генерируется сертификат, может быть подписан DNSSEC.

Скачиваем dnssec-tls-tools:

git clone git://github.com/agl/dnssec-tls-tools.git

И компилируем:

Генерация RSA-ключей:

openssl genrsa 1024 > privkey.pem openssl rsa -pubout -in privkey.pem > pubkey.pem

Создание отпечатка ключа:

где gencaa.py файл из пакета dnssec-tls-tools.

Команда вернет строку вида:

Это DNS-запись, которую необходимо добавить в свой файл зоны, заменив EXAMPLE.COM. своим значением. Если зона еще не подписана, это нужно сделать. Если запись добавляется к уже подписанной зоне, нужно, соответственно, выполнить подписание заново.

Проверяем правильность ключа в DNS:

Команда должна вернуть DNSSEC validation is ok: SUCCESS

После того как запись type27 доступна и подписана, можно сгенерировать цепочку доверия DNSSEC:

И сам сертификат:

Подключение сертификата в Nginx выглядит так:

server { … ssl on; ssl_certificate cert.pem; ssl_certificate_key privkey.pem; … }

Из-за того, что цепочка подписания DNSSEC может изменяться, создание цепочки и генерацию сертификата (последние две команды) необходимо добавить в крон и выполнять, например, раз в сутки.

Результат должен выглядеть так: https://dnssec.zhovner.com

Из-за того, что вся цепочка DNSSEC помещена в сертификат, браузеру нет необходимости производить полную проверку цепочки, так что сертификат будет «валидным» даже в случае если системный резолвер не поддерживает проверку DNSSEC.

P.S. В статье не рассмотрены сроки действия ключей DNSSEC, не рассказано об альтернативной цепочке доверия DLV (DNSSEC Look-aside Validation). Я буду признателен тем, кто разберется в этих вопросах и опишет их.

P.P.S. Мне известно негативное влияние подобных пошаговых HOWTO, которые приводят к бездумному копированию команд без понимания сути. Но, из-за того, что информации по данному вопросу мало и местами она противоречива, я надеюсь, кому-то эта статья поможет избежать путаницы с которой пришлось столкнуться мне. Спасибо Александру Венедюхину за консультации и его статьи .

Источник: http://habrahabr.ru

Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий

Вы должны быть авторизованы, чтобы разместить комментарий.