
Отдельно хочу заметить, что DLZ поддерживает не только mysql, список поддерживаемых хранилищ также под хабракатом.
Начну со списка хранилищ, которые поддерживает DLZ:
- Файловая система — все данные хранятся в именах файлов и каталогов, определенном образом структурированных
- Berkeley DB
- PostgreSQL
- MySQL
- ODBC (Firebird, Oracle, DB2, Sybase, SAPDB, MS SQL Server, и т.п.)
- LDAP
Для работы с DLZ bind должен быть собран с поддержкой DLZ и соответствующими драйверами хранилища. Как этого добиться — смотрите руководство к Вашей ОС.
Конкретно mysql драйвер не работает с BIND, скомпилированным с поддержкой потоков (threads), на некоторых ОС, в том числе на linux. Список ОС, в которых mysql драйвер может использоваться в многотопоточном BIND, есть в описании mysql драйвера на официальном сайте DLZ.
В gentoo включаем следующие USE для BIND со следующими USE=dlz mysql -threads (остальное на Ваш выбор).
Создаем БД, например, «dns», в ней таблицу, например, «records» и пользователя, который имеет право на SELECT из этой БД. Вообще dlz поддерживает любой вариант структуры, так как в конфиге BIND мы будет указывать конкретные sql-запросы на получение данных. Здесь я привожу то, что взято из официальной документации и доработано до текущих реалий (BIND 9.7.4_p1).
Мой вариант структуры таблицы records:
CREATE TABLE IF NOT EXISTS `records` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `zone` varchar(255) NOT NULL, `ttl` int(11) NOT NULL DEFAULT '86400', `type` varchar(255) NOT NULL, `host` varchar(255) NOT NULL DEFAULT '@', `mx_priority` int(11) DEFAULT NULL, `data` text, `resp_person` varchar(255) DEFAULT NULL, `serial` bigint(20) DEFAULT NULL, `refresh` int(11) DEFAULT NULL, `retry` int(11) DEFAULT NULL, `expire` int(11) DEFAULT NULL, `minimum` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `type` (`type`), KEY `host` (`host`), KEY `zone` (`zone`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
Пример данных о зоне:
INSERT INTO `records` (`id`, `zone`, `ttl`, `type`, `host`, `mx_priority`, `data`, `resp_person`, `serial`, `refresh`, `retry`, `expire`, `minimum`) VALUES
(1, 'example.com', 86400, 'SOA', '@', NULL, 'ns1.example.com.', 'admin.example.com.', 2011013101, 10800, 7200, 604800, 86400),
(2, 'example.com', 86400, 'NS', '@', NULL, 'ns1.example.com.', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'example.com', 86400, 'NS', '@', NULL, 'ns2.example.com.', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'example.com', 86400, 'A', '@', NULL, '192.168.0.35', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'example.com', 86400, 'A', 'ns1', NULL, '192.168.0.36', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'example.com', 86400, 'A', 'ns2', NULL, '192.168.0.37', NULL, NULL, NULL, NULL, NULL, NULL);
В named.conf прописываем:
dlz "Mysql zone" { database "mysql {dbname=dns user=username pass=password socket=/var/run/mysqld/mysqld.sock} {select zone from records where zone = '$zone$'} {select ttl, type, mx_priority, case when lower(type)='txt' then concat('\"', data, '\"') else data end from records where zone = '$zone$' and host = '$record$' and not (type = 'SOA' or type = 'NS')} {select ttl, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum from records where (type = 'SOA' or type='NS') and zone = '$zone$'}"; };
«Mysql zone» — просто название куска конфига, к имени самой зоны отношения не имеет.
$zone$ и $record$ прописываем именно так, это переменные на место которых DLZ сам будет подставлять имя зоны и записи при запросе.
В третье строчке можно прописывать следующие параметры:
dbname=
port=
host=
user=
pass=
socket=
compress=
ssl=
space=
Названия говорят вроде бы сами за себя. Ну, может быть, кроме «space=», но что это — я не знаю. В документации кроме того, что это булевый параметр, ничего про него не сказано.
Запросы опишу вкратце. В документации они описаны подробнее.
- select zone from records where zone = '$zone$' — запрос, с помощью которого BIND понимает поддерживает ли он вообще эту зону.
- select ttl, type, mx_priority, case when lower(type)='txt' then concat('\"', data, '\"')
else data end from records where zone = '$zone$' and host = '$record$'
and not (type = 'SOA' or type = 'NS')} — запрос получения записи о конкретном хосте в зоне. - select ttl, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum
from records where (type = 'SOA' or type='NS') and zone = '$zone$' как видно из запроса — тут мы получаем все авторитарные (authority) записи о зоне.
Самая неприятная и непонятная проблема, с которой я столкнулся, ориентируясь на имеющиеся в интернете документы, это постоянное появление в логах записей типа:
Jun 22 19:51:10.142 dns_rdata_fromtext: buffer-0xbfffe390:1: near eof: unexpected end of input Jun 22 19:51:10.143 dns_sdlz_putrr returned error. Error code was: unexpected end of input Jun 22 19:51:10.146 dns_rdata_fromtext: buffer-0xbfffe0d0:1: near eof: unexpected end of input Jun 22 19:51:10.147 dns_sdlz_putrr returned error. Error code was: unexpected end of inputи неработающей зоной.
Обозначают эти строчки то, что DLZ получает данные не в том формате или порядке, как ожидает. A и NS записи должны иметь ttl, type и data, именно в таком порядке и только их (остальные поля — NULL). MX — все вышеперечисленное + mx_priority, SOA — ttl, type, data, responsible_person, refresh, retry, expire, minimum. (Информация в этом абзаце выкопана из почтового архива).
Есть еще два варианта запроса, связанных с переносом (xfer) зон, я их не использовал, так что отсылаю к официальной документации.
Очень помогает для отладки, как ни странно, отладочный режим BIND (-d 9). В gentoo прописываем OPTIONS="-d 9" в /etc/conf.d/named.
Я буду очень рад, если в комментариях, пользователи хабра поделятся своим опытом и конфигами для работы с BIND DLZ. Я пока только на начальном этапе настройки, мне предстоит очень многое. Например, обратные зоны.