illumium.org

Главная › Блоги › Блог kayo

Dynamic DNS Server своими руками

kayo — Вс, 19/12/2010 - 02:57

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

На сервере работает bind9, и для него, разумеется, существует решение, позволяющие динамически обновлять доменные записи с удалённых клиентов. Однако сводится оно к использованию продвинутого метода nsupdate, который не поддерживается средненьким сетевым оборудованием не промышленного уровня, а в частности моим домашним маршрутизатором. Поэтому лучшим решением, на мой взгляд, было иметь сервер, протокольно совместимый с ddclient, который есть почти во всех ныне существующих сетевых устройствах.

Кое-какие вводные слова

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

Идея первая. Менять записи напрямую было бы относительно сложно и небезопасно, гораздо лучше использовать для этого nsupdate, который по сути принимает на вход файл изменений и последовательно применяет имеющиеся в нём команды. При этом нет необходимости передёргивать сам bind, чтобы изменения вступили в силу.

Идея вторая. Мне не очень хотелось реализовывать авторизацию пользователей, было решено воспользоваться помощью WEB-сервера. Пользователи хранятся в файле htpasswd, используемом обычно для базовой авторизации по HTTP.

Идея третья. Для обеспечения безопасности сервис должен работать под своим пользователем в роли FastCGI backend-а, на который будет ссылаться WEB-сервер при появлении ожидаемого запроса. Сервису будут доступны ключи авторизации пользователей для запуска nsupdate, которые не будут доступны другим.

Идея четвёртая. Для администрирования пользователей в этой реализации решено было написать небольшой скрипт, который автоматически генерирует ключи, а также обновляет базу пользователей и список ключей bind.

Динамически обновляемые зоны в bind9

Перед тем, как перейти к описанию установки и настройки сервиса, хотелось бы рассказать, как работает nsupdate и bind.

Создаём ключи

Итак, первое, что нам потребуется сделать, настроить зоны, которые мы бы хотели обновлять динамически. Утилита nsupdate взаимодействует с bind используя ключи, поэтому сейчас мы должны генерировать ключ примерно таким образом:

dnssec-keygen -a HMAC-MD5 -b 512 -n HOST ddserver

Здесь мы указали тип ключа (hmac-md5), длину (512, можно в принципе использовать любую для этого типа ключа от 1 до 512) и пользователя (ddserver).

По завершении у нас будет пара ключей: публичный и приватный, у меня получились такие:

Kddserver.+157+47946.key
Kddserver.+157+47946.private

Далее нам потребуется хеш (всё, что находится после числа 157 в файле .key) из публичного ключа для добавления его в конфигурацию сервера.

Создадим файл /etc/bind/ddserver.conf со следующим содержимым:

key ddserver {       
  algorithm hmac-md5;
  secret "<ваш ключ>";
};

Далее включим его в /etc/bind/named.conf.local (Кайо добавил строку перед описанием доменных зон):

include "/etc/bind/ddserver.conf";

Теперь передёргиваем bind9:

sudo invoke-rc.d bind9 reload

Настраиваем доступ

Почти всё, однако мы ещё не дали разрешения на динамическое обновление конкретных зон, поэтому делаем следующее: находим описание нужной зоны, и добавляем в неё разрешение на обновление соответствующему ключу:

zone "illumium.org" {
  type master;
  file "illumium.org";
  allow-update {
    key ddserver;
  };
};

Этого в общем-то будет достаточно, но так мы дали слишком много возможностей клиенту с ключом ddserver. Можно определиться более конкретно, какие обновления позволено делать, например добавив следующую директиву вместо блока allow-update:

update-policy {
  grant ddserver name kayo-home.illumium.org. A;
};

Тем самым мы позволили обновлять лишь A запись только для поддомена kayo-home.illumium.org.

Чтобы излишне не загромождать статью, Кайо не рассматривает здесь обновление обратных зон, однако суть практически та же.

Тестируем обновление зоны

Итак, воспользуемся nsupdate для обновления нашего поддомена. Чтобы обновить некоторую A-запись, нужно сперва удалить её, затем добавить снова уже с нужным IP-адресом. Создадим файл update.ns с таким содержимым:

zone illumium.org
update delete kayo-home.illumium.org. A
update add kayo-home.illumium.org. 60 IN A 1.2.3.4
send

Добавляем запись A-типа kayo-home.illumium.org с IP 1.2.3.4 и TTL 60 секунд. Время жизни TTL указывать необходимо, чем оно больше, тем дольше запись будет оставаться в кешах DNS серверов. К примеру, если указать 600 (10 минут), запись в течении 10 минут не будет запрашиваться снова, и если в течении этого времени IP обновится, об этом станет известно только спустя указанный интервал.

Теперь собственно пробуем обновить (делать это можно с любого хоста, где есть nsupdate и доступен созданный нами ранее приватный ключ):

nsupdate -k Kddserver.+157+47946.private -v update.ns

Смотрим syslog на сервере в момент запуска команды, должны появиться записи вида:

updating zone 'illumium.org/IN': deleting rrset at 'kayo-home.illumium.org' A
updating zone 'illumium.org/IN': adding an RR at 'kayo-home.illumium.org' A

При этом по завершении nsupdate не должен ничего выдать на stdout и stderr. Если вы не верно определили привилегии, утилита скажет, что обновление не удалось. Так что теперь чтобы убедиться, что мы не может таким образом обновлять другие записи, пробуем изменить имя в update.ns и заново вызвать nsupdate, если всё настроено, как описано у меня, получаем следующее:

update failed: REFUSED

А в syslog на сервере bind скажет вот что:

updating zone 'illumium.org/IN': update failed: rejected by secure update (REFUSED)

DynDNS Server совместимый с протоколом dyndns2

Кайо разработал ddserver как FastCGI backend. Софт написан на C и запускается как демон под непривилегированным пользователем, которому позволено находить ключи пользователей и запускать nsupdate. Проект разместил на SF.Net. Там же лежат готовые пакеты для Debian. В общем, хотелось проще, получилось как всегда ^_~

Краткое описание протокола

Обновление доменных записей dyndns2 происходит посредством HTTP GET запроса. Сперва клиент определяет свой текущий IP адрес. Это он может делать разными способами: например запросить у ADSL модема или через WEB (http://checkip.dyndns.com и подобные). В случае, если текущий IP клиента изменился, он должен сделать запрос на обновление записей, который в простейшем случае выглядит следующим образом:

http://<пользователь>:<пароль>@dyndns-server.dom/nic/update?hostname=<домен>&myip=<IP>

 Доменные имена должны быть представлены в полном формате, но без завершающей точки. В случае, если доменных имён несколько, они должны быть перечислены через запятую.

Управление пользователями

Для администрирования пользователей был написан скрипт ddserver-admin, делает он следующее:

  • ddserver-admin user-list - выводит список существующих пользователей
  • ddserver-admin user-add <username> - добавляет нового пользователя или обновляет существующего
  • ddserver-admin user-del <username> - удаляет существующего пользователя

При добавлении и обновлении пользователя потребуется ввести пароль для доступа через WEB. Скрипт автоматически генерирует нужные ключи и обновляет htpasswd файл соответствующей утилитой из apache. Имя пользователя будет названием ключа для bind.

В директории /etc/ddserver у нас будут два файла:

  • named.conf - содержит ключи, потребуется включить в конфиг bind-а директивой include с указанием полного пути
  • htpasswd - потребуется указать WEB-серверу для обеспечения авторизации пользователей

Разграничение доступа

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

zone "site1.dom" {
  type master;
  file "site1.dom";
  allow-update {
    key user1; // user1 может обновлять любые записи в зоне site1.dom
  };
};
zone "site2.dom" {
  type master;
  file "site2.dom";
  update-policy {
    grant user2 name user2.site2.dom. A; // user2 может обновлять только A запись поддомен user2.site2.dom в зоне site2.dom
    grant user3 subdomain site2.dom. A; // user3 может обновлять любые A записи поддомены  site2.dom
    grant user4 wildcard *u4.site2.dom.; // user4 может обновлять записи, соответствующие шаблону *u4.site2.dom
  };
};

Важно иметь ввиду также значения TTL в файлах описания зон, чтобы снизить время нахождения динамических записей в кешах серверов имён.

Настройка обновления через WEB в Nginx

Поскольку Кайо использует Nginx, здесь будет рассказано, как настроить работу сервиса в качестве FastCGI backend-а к нему. Перейдём сразу к примеру конфигурации, который довольно прост и практически не требует пояснений:

# DDServer server config..
server {
  listen 80;
  server_name ddns.yourdomain.dom; // Указываем по какому адресу будет доступен сервис
  location /nic/update {
    auth_basic "badauth"; // Требуем базовую авторизацию
    auth_basic_user_file /etc/ddserver/htpasswd; // Указываем файл пользователей
    access_log off; // Запрещаем логи
    fastcgi_pass 127.0.0.1:7111; // Определяем способ связи с backend-ом
    fastcgi_param REMOTE_USER $remote_user; // Заботимся об отправке имени пользователя в качестве переменной среды REMOTE_USER
    include fastcgi_params; // Включаем другие параметры
  }
}

Статус проекта

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

В данный момент поддерживается:

  • обновление A-записей
  • обновление нескольких имён за раз (с одинаковым IP)

Не поддерживается:

  • обновление MX записей
  • автообновление обратных зон
  • Системное администрирование
  • dns
  • dyndns
  • Бортовой журнал Иллюмиума

ddserever 0.0.2a имеет

Гость (не проверено) — Пт, 28/01/2011 - 09:53

ddserever 0.0.2a имеет зависимость от libfcgi0ldbl и папки /etc/ddserver/keys, поэтому перед установкой:

mkdir /etc/ddserver/keys
aptitude install libfcgi0ldbl
dpkg -i ddserver_0.0.2a_amd64.deb

  • ответить

Спасибо за верное замечание

kayo — Сб, 05/02/2011 - 15:22
Спасибо за верное замечание про /etc/ddserver/keys, добавляю создание каталога в postinst скрипт.Зависимость от libfcgi итак имеется в пакете. 
We used to be in Love…
  • ответить

еще в

Гость (не проверено) — Пт, 28/01/2011 - 10:06
еще в /etc/apparmor.d/usr.sbin.named нужно добавить "/etc/ddserver/** r," и перегрузить apparmor
  • ответить

С доступом туда со стороны

kayo — Сб, 05/02/2011 - 15:29
С доступом туда со стороны bind-а проблем вроде бы не наблюдал, странно.
We used to be in Love…
  • ответить

Пожалуй единственный

Гость (не проверено) — Вс, 06/01/2013 - 00:45

Пожалуй единственный вменяемый проект такого типа! Спасибо большое! Планируете развивать далее, добавить функционал?

Написал ebuild для gentoo - http://portage.org.ua/portage/net-dns/ddserver/

  • ответить

Конечно, если появятся

kayo — Пнд, 01/04/2013 - 14:45
Конечно, если появятся хотелки :-]
We used to be in Love…
  • ответить

На Апаче разве нельзя

Artem (не проверено) — Чт, 23/07/2015 - 01:55
На Апаче разве нельзя сделать?
  • ответить

Можно, то можно. Только

kayo — Ср, 12/08/2015 - 22:15
Можно, то можно. Только зачем?
We used to be in Love…
  • ответить

А не подскажите, на чем лучше

Round (не проверено) — Вс, 22/04/2018 - 21:19

А не подскажите, на чем лучше сделать свой сервер днс чтобы для всех доменных зон? Кэширующий и высокопроизводительный. 20000-50000 запросов в секунду, причем разных доменов. Но кэш все равно необходимо собирать и складировать - в идеале - в бд (понимаю что там будут миллионы строк).  Ну... и при таком объеме полагаю понадобится база днсок, и софт, соответственно должен использовать их случайно.

Под ubuntu ту же...

Благодарю!

  • ответить

Ну вообще на Rust есть

kayo — Вс, 22/04/2018 - 21:32

Ну вообще на Rust есть полностью асинхронный высокопроизводительный сервер из проекта trust-dns: trust-dns-server.

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

We used to be in Love…
  • ответить

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

Содержимое этого поля является приватным и не будет отображаться публично.
  • Доступные HTML теги: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".

Подробнее о форматировании

CAPTCHA
Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.
    _               ____     _           _   _ 
(_) __ __ / ___| (_) __ _ | \ | |
| | \ \ /\ / / | | _ | | / _` | | \| |
| | \ V V / | |_| | | | | (_| | | |\ |
_/ | \_/\_/ \____| _/ | \__, | |_| \_|
|__/ |__/ |___/
Введите код, изображенный в стиле ASCII-арт.
RSS-материал

Навигация

  • Подшивки
  • Фотоальбомы

«Иллюмиум» на якоре.

Работает на Drupal, система с открытым исходным кодом.

(L) 2010, Illumium.Org. All rights reversed ^_~