Рубрика:
Администрирование /
Хранение данных
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
Сергей Алаев
Интеграция BIND + PostgreSQL
Многие провайдеры используют BIND в качестве DNS-сервера. Но иногда возникают проблемы с добавлением зон и записей в них, и это приводит к перезапуску сервера, что крайне нежелательно из-за возможных ошибок при обработке клиентских DNS-запросов. Чтобы предотвратить перезапуск DNS-сервера BIND, целесообразно использовать внешние хранилища (MySQL, OpenLDAP, PostgreSQL и т. д.).
Прелюдия
Сегодня подробно рассматрим хранение зон BIND в PostgreSQL. Этот метод хранения зон позволяет динамически добавлять зоны и записи в них, а также обновлять содержимое зон.
В качестве внешнего хранилища можно также использовать MySQL, OpenLDAP, BerkeleyDB, ODBC, который предоставляет хранить зоны в любой СУБД, и т. д.
Основными достоинствами методов хранения являются:
- Возможность обновлять содержимое зон без перезапуска.
- Экономия оперативной памяти (при запуске named считывает все зоны из файлов, при большом количестве зон и записей в них это занимает достаточно много оперативной памяти и времени).
- Более высокое быстродействие по сравнению с хранением зон в файлах (результаты тестов можно посмотреть на http://bind-dlz.sourceforge.net/perf_tests.html).
Существует две реализации драйверов для хранения зон во внешних хранилищах – DLZ и SDB.
DLZ-драйверы не входят в стандартный набор исходных текстов BIND. Они более гибкие в настройке и поддерживают широкий набор внешних хранилищ. Техническую документацию по настройке DLZ-драйверов вы можете найти на http://bind-dlz.sourceforge.net.
SDB-драйверы входят в стандартный набор исходных текстов BIND и содержат инструменты для автоматизированной интеграции зон из файлов в базу данных. К недостаткам такого способа хранения зон можно отнести поддержку только master-зон.
Рассмотрим обе реализации. В Fedora Core Linux есть rpm-пакет bind-sdb с поддержкой необходимых драйверов SDB. Сначала рассмотрим метод интеграции с помощью драйвера SDB. К сожалению, во FreeBSD нет интегрированного порта BIND с поддержкой SDB PostgreSQL, поэтому устанавливать будем из исходных текстов.
Установка PostgreSQL
Итак, приступим.
Собираем PostgreSQL из портов:
# cd /usr/ports/databases/postgresql80-server
# make && make install
Создадим каталог для размещения баз данных с правами на pgsql:
# cd /var/db
# mkdir pgsql
# chmod 700 pgsql && chown pgsql:pgsql pgsql
Зададим параметры запуска PostgreSQL в rc.conf, которые будут использоваться при инициализации кластера баз данных:
# mcedit /etc/rc.conf
postgresql_enable=”YES”
postgresql_user=”pgsql”
postgresql_data=”/var/db/pgsql”
Инициализируем кластер баз данных:
# /usr/local/etc/rc.d/010.pgsql.sh initdb
Далее правим главный конфигурационный файл, где указываем IP, на котором будет работать сервер:
# mcedit /var/db/pgsql/postgresql.conf
listen_addresses=’localhost’
Для версии 7.x необходимо указать:
tcpip_socket = true
virtual_host = ‘127.0.0.1’
Для запуска PostgreSQL выполните команду:
# /usr/local/etc/rc.d/010.pgsql.sh start
Установка и настройка BIND на использование SDB-драйвера
Приступаем к установке BIND. Устанавливаем порты gettext и libiconv из раздела devel общего дерева портов, которые необходимы для нормальной компиляции BIND.
Закачиваем и распаковываем исходные тексты:
# mkdir /usr/local/src
# cd /usr/local/src/
# fetch ftp://ftp.isc.org/isc/bind9/9.3.2/bind-9.3.2.tar.gz
# cd bind-9.3.2
Драйвер SDB находится в contrib/sdb/pgsql. Для успешной компиляции BIND с поддержкой этого драйвера необходимо включить его исходный код в исходный код сервера named.
Для компиляции драйвера также будут необходимы библиотеки и файлы заголовков PostgreSQL, поэтому надо будет уточнить в pgsqldb.c их точное месторасположение относительно общих путей расположения библиотек и заголовков(/usr/local/lib, /usr/local/include). Общие пути расположения задаются позже с помощью патча.
Правим pgsqldb.c:
# mcedit contrib/sdb/pgsql/pgsqldb.c
// Заменяем строку «# include <pgsql/libpq-fe.h>» на
#include <libpq-fe.h>
// Заменяем строку «# include “pgsqldb.h”» на
# include “named/pgsqldb.h”
Для добавления драйвера скачиваем скрипт и патч в корневое дерево исходных текстов и выполняем его с помощью скрипта (патч и скрипт смотрите в разделе «Исходный код» на сайте журнала http://www.samag.ru):
# ./add_pgsqldb.sh
Приступаем к компиляции и установке сервера:
# ./configure --prefix=/usr/local && make && make install
Приступаем к настройке сервера.
Рассмотрим простую конфигурацию сервера:
# mcedit /etc/namedb/named.conf
options {
directory "/etc/namedb";
pid-file "/var/run/named/pid";
};
key rndc-key {
algorithm hmac-md5;
secret "X4JdLjgWj2acEqQ2gyKhPw==";
};
controls {
inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { rndc-key; };
};
zone "example.net" {
type master;
database "pgsql bind zone_example_net 127.0.0.1 bind 123456";
allow-transfer {
192.168.7.2;
};
};
zone "7.168.192.in-addr.arpa" {
type master;
database "pgsql bind zone_192_168_7 127.0.0.1 bind 123456";
allow-transfer {
192.168.7.2;
};
};
Разрешаем передачу зон для 192.168.7.2, т.к. с этого адреса будем тестировать наш DNS-сервер.
Строка «database “pgsql bind zone_192_168_7 127.0.0.1 bind 123456”;» определяет параметры хранения зоны в PostgreSQL в следующем порядке:
- bind – имя базы данных;
- zone_192_168_7 – имя таблицы, где хранится содержимое зоны;
- 127.0.0.1 – IP-адрес, на котором слушает сервер PostgreSQL;
- bind – имя пользователя для соединения к серверу PostgreSQL;
- 123456 – пароль для пользователя BIND.
Приступаем к созданию баз данных:
# psql –h 192.168.7.1 -d template1 -U pgsql
Cоздаём пользователя bind:
template1=# CREATE USER bind WITH SYSID 100 PASSWORD '123456'
NOCREATEDB NOCREATEUSER;
|
Cоздадим базу данных для хранения зон:
template1=# CREATE DATABASE bind WITH OWNER = bind;
Скомпилируем утилиту для автоматического добавления зоны из файла в базу:
# cd /usr/local/src/bind-9.3.2/contrib/sdb/pgsql
# gcc -g `isc-config.sh --cflags isc dns` -c zonetodb.c
# gcc -g -o zonetodb zonetodb.o `isc-config.sh --libs isc dns` -lpq
# cp zonetodb /usr/local/bin/zonetodb
Допустим, у нас имеется файл зоны example.net следующего содержания:
# mcedit /etc/namedb/example.net.hosts
$ttl 38400
example.net. IN SOA freebsd.example.net. bsdadmin3.mail.ru (
1161450241
10800
3600
604800
38400 )
example.net. IN NS freebsd.example.net.
example.net. IN A 192.168.7.1
freebsd.example.net. IN A 192.168.7.1
boss.example.net. IN A 192.168.7.2
semen.example.net. IN A 192.168.7.3
ignat.example.net. IN A 192.168.7.4
www.example.net. IN CNAME freebsd.example.net.
example.net. IN MX 50 freebsd.example.net.
example.net. IN MX 100 boss.example.net.
Для добавления воспользуемся утилитой zonetodb. Для соединения с базой данных она использует в качестве значений имени пользователя, хоста значения переменных PGHOST, PGUSER. Название таблицы и базы данных указывается при использовании утилиты.
Пароль указывать в этом случае необязательно, т.к. настройка PostgreSQL по умолчанию разрешает из консоли соединяться с базой данных на правах суперпользователя без указания пароля.
Задаём имена хоста и пользователя:
# export PGHOST=127.0.0.1
# export PGUSER=bind
# /usr/local/bin/zonetodb example.net. example.net.hosts bind zone_example_net
где первый параметр – это название зоны (заканчивается обязательно точкой), второй – имя файла содержимого зоны, третий – база данных, четвёртый – имя таблицы, где хранится содержимое зоны.
Утилита сама создаст таблицу и добавит содержимое зоны автоматически (см. рис. 1).
Рисунок 1. Добавление зоны из файла в базу данных
Добавим зону обратного просмотра.
root@localhost# mcedit 192.168.7.rev
$ttl 38400
7.168.192.in-addr.arpa. IN SOA freebsd.example.net. bsdadmin3.mail.ru (
1161450262
10800
3600
604800
38400 )
7.168.192.in-addr.arpa. IN NS freebsd.example.net.
1.7.168.192.in-addr.arpa. IN PTR freebsd.example.net.
2.7.168.192.in-addr.arpa. IN PTR boss.example.net.
3.7.168.192.in-addr.arpa. IN PTR semen.example.net.
4.7.168.192.in-addr.arpa. IN PTR ignat.example.net.
root@localhost# /usr/local/bin/zonetodb 7.168.192.in-addr.arpa. 192.168.7.rev bind zone_192_168_7
Настраиваем параметры запуска BIND:
# mcedit /etc/rc.conf
named_enable=”YES”
named_program=”/usr/local/sbin/named”
named_chroot_dir=”/var/named”
named_flags=”-u bind –c /etc/namedb/named.conf”
Также необходимо настроить приоритеты загрузки, т.к. по умолчанию во время загрузки системы BIND запускается до PostgreSQL, что приведёт к ошибке, т.к. при запуске он будет устанавливать соединения к PostgreSQL. Правим стартовый скрипт PostgreSQL:
# mcedit /usr/local/etc/rc.d/010.pgsql.sh
# PROVIDE: postgresql
# REQUIRE: NETWORKING SERVERS
# KEYWORD: FreeBSD shutdown
# BEFORE:
Данные комментарии используются для определения порядка запуска стартовых скриптов во время загрузки системы. Рассмотрим назначение данных ключевых слов:
- # PROVIDE: – задает имя сервиса, предоставляемого этим файлом.
- # REQUIRE: – список сервисов, необходимых этому сервису. Этот файл будет запущен после указанных сервисов.
- # BEFORE: – список сервисов, зависящих от этого сервиса. Этот файл будет запущен до указанных сервисов.
- # KEYWORD: – FreeBSD или NetBSD. Используется для функций, зависящих от версии *BSD.
За более подробной информацией обращайтесь к справочному руководству FreeBSD. Запускаем BIND:
# /etc/rc.d/named start
Тестируем наш сервер с помощью утилиты nslookup (см. рис. 2).
Рисунок 2. Тестирование SBD-драйвера
Установка и настройка BIND на использование DLZ-драйвера
Рассмотрим использование драйвера DLZ.
Собираем BIND из портов:
# cd /usr/ports/dns/bind9-dlz
# make clean && make && make install
В окне конфигурации отмечаем нужный нам PostgreSQL (см. рис. 3).
Рисунок 3. Конфигурация DLZ-драйвера
Приступаем к конфигурированию BIND.
# mcedit /etc/namedb/named.conf
options {
directory "/etc/namedb";
pid-file "/var/run/named.pid";
listen-on {
192.168.7.1;
};
};
key rndc-key {
algorithm hmac-md5;
secret "3lyE4327kU/qr6C/THQflg==";
};
controls {
inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { rndc-key; };
};
dlz "postgres zone" {
database "postgres 1
// Определяем параметры подключения к базе данных
{host=192.168.7.1 port=5432 dbname=bind ?
user=bind password=123456}
// Определяем запрос для поиска зоны в таблице dns_records. Все зоны будут храниться в этой таблице.
// Вместо переменной %zone% во время обработки DNS-запроса подставляется название требуемой зоны
{select zone from dns_records where zone = '%zone%'}
// Определяем запрос для поиска записи в таблице. Данный запрос используется, например, для обработки
// запросов на получение имени по IP-адресу и наоборот. Вместо переменной %record% вставляется название записи
// (DNS имя или IP адрес).
{select ttl, type, mx_priority, case ?
when lower(type)='txt' then '\"' || data || '\"' when lower(type)='soa' then data || ' ' || resp_person || ' ' || serial || ' ' || refresh || ' ' || retry || ' ' || expire || ' ' || minimum else data end from dns_records where zone = '%zone%' and host = '%record%'}
{}
// Определяем запрос для получения содержимого всей зоны
{select ttl, type, host, mx_priority, case when lower(type)='txt' then '\"' || data || '\"' else data end, resp_person, serial, refresh, retry, expire, minimum from dns_records where zone = '%zone%'}
// Формируем запрос для получения адресов клиентов, которым разрешено получать содержимое зоны
{select zone from xfr_table where zone = '%zone%' and client = '%client%'}";
};
Обратите внимание, при создании конфигурационного файла в настройках DLZ-драйвера очень важен порядок строк, т.к. сервер считывает SQL-запросы в специальном порядке и в этом же порядке определяет, какой SQL-запрос использовать при обработке клиентских DNS-запросов.
Создадим базу данных и таблицу для хранения зон:
# psql –h 192.168.7.1 -d template1 -U pgsql
Создаём пользователя bind:
template1=# CREATE USER bind WITH SYSID 100 PASSWORD '123456'
NOCREATEDB NOCREATEUSER;
|
Создаём базу данных для хранения зон:
template1=# CREATE DATABASE bind WITH OWNER = bind;
Создаём таблицу:
template1=# \c bind
bind =# CREATE TABLE dns_records (
"zone" text,
host text
ttl int8,
"type" text,
mx_priority text,
data text,
resp_person text,
serial int8,
refresh int8,
retry int8,
expire int8,
minimum int8
) WITH OIDS;
Создадим индексы для поиска по полям host, type, zone:
bind =# CREATE INDEX host_index
ON dns_records
USING btree
(host);
bind =# CREATE INDEX type_index
ON dns_records
USING btree
("type");
bind =# CREATE INDEX zone_index
ON dns_records
USING btree
("zone");
Создадим таблицу для хранения разрешений на получение содержимого зоны:
bind =# CREATE TABLE xfr_table
(
"zone" text,
client text
)
WITH OIDS;
Приступаем к добавлению зон. В качестве примера будем использовать те же зоны, что и при описании SDB-драйвера.
Рассмотрим зону прямого просмотра.
Добавим SOA-запись:
bind =# INSERT INTO dns_records("zone", host, ttl, "type", data, resp_person, serial, refresh, retry, expire, minimum) VALUES ('example.net', '@',38400, 'SOA','freebsd.example.net.','bsdadmin3.mail.ru.', 1161450241,10800,3600,604800,38400);
Добавим NS-запись:
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('example.net', '@','NS','freebsd.example.net.')
Добавим A-записи:
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('example.net', '@','A','192.168.7.1');
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('example.net', 'freebsd','A','192.168.7.1');
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('example.net', 'boss','A','192.168.7.2');
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('example.net', 'semen','A','192.168.7.3');
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('example.net', 'ignat','A','192.168.7.4');
Добавим CNAME-запись:
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('example.net', 'www','CNAME','freebsd.example.net.');
Добавим MX-записи:
bind =# INSERT INTO dns_records("zone", host, "type", mx_priority, data) VALUES ('example.net', 'example.net','MX',50,'freebsd.example.net.');
bind =# INSERT INTO dns_records("zone", host, "type", mx_priority, data) VALUES ('example.net', 'example.net','MX',100,'boss.example.net.');
Рассмотрим зону обратного просмотра.
Добавим SOA-запись:
bind =# INSERT INTO dns_records("zone", host, ttl, "type", data, resp_person, serial, refresh, retry, expire, minimum) VALUES ('7.168.192.in-addr.arpa', '@',38400, 'SOA','freebsd.example.net.','bsdadmin3.mail.ru.', 1161450262,10800,3600,604800,38400);
Добавим NS-запись:
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('7.168.192.in-addr.arpa', '@','NS', 'freebsd.example.net.');
Добавим PTR-записи:
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('7.168.192.in-addr.arpa ', '1','PTR','freebsd.example.net.');
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('7.168.192.in-addr.arpa ', '2','PTR','boss.example.net.');
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('7.168.192.in-addr.arpa ', '3','PTR','semen.example.net.');
bind =# INSERT INTO dns_records("zone", host, "type", data) VALUES ('7.168.192.in-addr.arpa ', '4','PTR','ignat.example.net.');
Разрешим клиенту 192.168.7.2 (с него мы будем тестировать сервер) получать содержимое данных зон:
bind =# INSERT INTO xfr_table VALUES ('example.net', '192.168.7.2');
bind =# INSERT INTO xfr_table VALUES ('7.168.192.in-addr.arpa', '192.168.7.2');
Параметры запуска и приоритеты загрузки задаём аналогично первому примеру.
Приступаем к тестированию BIND. Запускаем BIND:
# /etc/rc.d/named start
Тестируем наш сервер с помощью утилиты nslookup (см. рис. 4).
Рисунок 4. Тестирование DLZ-драйвера
На этом всё. Удачи.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|