Система DNS очень важна для работы Интернета в целом, поэтому стоит посвятить достаточное количество времени на изучение принципов работы системы и на настройку сервера имен. Сегодня я расскажу о настройке bind для хранения информации о зонах в базе данных LDAP.
Очень часто в локальных сетях, будь то большие сети крупных организаций или же небольшие «домашние» сети, устанавливается и настраивается локальный DNS-сервер. Ставят его для удобства работы или для кэширования запросов к DNS-серверам провайдера. Для UNIX-систем стандартом среди DNS-серверов является bind. По умолчанию bind хранит все записи о зонах в простых текстовых файлах, с которыми не всегда удобно работать. Например, если у вас есть несколько DNS-серверов на разных машинах, то править файлы зон через шелл не очень удобно, так как придется выполнить большое число однообразных действий, начиная от ввода логина, заканчивая перезагрузкой DNS-сервера. Если у вас в сети настроен LDAP-сервер, то разумнее всего хранить прямые и обратные зоны DNS-сервера в LDAP. Разумнее, потому что тогда получается централизованное хранилище данных, с которым легко можно работать из различных ОС, да и программ для работы с LDAP-сервером очень много, как для UNIX, так и для Windows. Еще один довод для хранения информации в LDAP – динамическое обновление зон. DHCP может не посылать запросы DNS-серверу на обновление зоны, тем самым нагружая DNS-сервер, а может сам обновить запись на LDAP-сервере. Надеюсь, вы задумались о LDAP как о хранилище данных DNS-сервера. Теперь приступим к практической реализации. Сразу хочу описать сеть, для которой мы будем настраивать DNS-сервер:
Адрес сети: 192.168.1.0/24.
Домен: teachers.
IP-адрес DNS-сервера: 192.168.1.254 (hostname: dns).
IP-адрес LDAP-сервера: 192.168.1.250 (hostname: spider).
Итак, приступаем к настройке:
Система: FreeBSD-6.1-p6 (и на LDAP- и на DNS-сервере).
Корень LDAP-сервера: dc=l1523,dc=ru.
Если у вас не настроен LDAP-сервер, то можете почитать о его настройке на сайте: http://www.fr33man.ru/index.php?newsid=5б.
Настройка LDAP
Сначала необходимо подключить две схемы к нашему серверу: dnsZone.schema и dhcp.schema. Схема dnsZone поставляется по умолчанию с сервером slapd, а вот схема dhcp появляется после установки DHCP-сервера. Забирайте dhcp.schema отсюда: http://fr33man.ru/files/dhcp.schema.
Редактируем slapd.conf, добавляем:
include /usr/local/etc/openldap/schema/dnszone.schema
include /usr/local/etc/openldap/schema/dhcp.schema
После этого перезапускаем slapd:
spider@/root/> /usr/local/etc/rc.d/slapd.sh restart
Stopping slapd.
Starting slapd.
Все, теперь можно добавить необходимые записи в LDAP. Я предоставляю ldif-файл с комментариями:
Dns.ldif
# Добавляем контейнер, где будут храниться все зоны нашего DNS-севера
dn: ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: organizationalUnit
ou: dns
description: domain zones
# Добавляем прямую зону teachers
dn: zoneName=teachers,ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: dNSZone
zoneName: teachers
relativeDomainName: teachers
# SOA-запись для зоны teachers
dn: relativeDomainName=@,zoneName=teachers,ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: dNSZone
zoneName: teachers
relativeDomainName: @
nSRecord: ns.teachers.
sOARecord: ns.teachers. root.ns.teachers. 1 8H 2H 1W 1D
# Добавляем запись вида:
# ns IN A 192.168.1.254
dn: relativeDomainName=ns,zoneName=teachers,ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: dNSZone
zoneName: teachers
relativeDomainName: ns
dNSClass: IN
aRecord: 192.168.1.254
# Добавляем запись вида:
# spider IN A 192.168.1.250
dn: relativeDomainName=spider,zoneName=teachers,ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: dNSZone
zoneName: teachers
relativeDomainName: spider
dNSClass: IN
aRecord: 192.168.1.250
# Добавляем новую обратную зону 1.168.192.in-addr.arpa
dn: zoneName=1.168.192.in-addr.arpa,ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: dNSZone
zoneName: 1.168.192.in-addr.arpa
relativeDomainName: 1.168.192.in-addr.arpa
# SOA-запись для зоны 1.168.192.in-addr.arpa
dn: relativeDomainName=@,zoneName=1.168.192.in-addr.arpa,ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: dNSZone
relativeDomainName: @
nSRecord: ns.teachers.
sOARecord: ns.teachers. root.ns.teachers. 1 8H 2H 1W 1D
zoneName: 1.168.192.in-addr.arpa
# Добавляем запись вида:
# 254 PTR ns.teachers.
dn: relativeDomainName=254,zoneName=1.168.192.in-addr.arpa,ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: dNSZone
zoneName: 1.168.192.in-addr.arpa
relativeDomainName: 254
pTRRecord: ns.teachers.
# Добавляем запись вида:
# 250 PTR spider.teachers.
dn: relativeDomainName=250,zoneName=1.168.192.in-addr.arpa,ou=dns,dc=l1523,dc=ru
objectClass: top
objectClass: dNSZone
zoneName: 1.168.192.in-addr.arpa
relativeDomainName: 250
pTRRecord: spider.teachers.
Может показаться, что добавлять записи в файлы зон намного удобнее, чем в LDAP-сервер, но кто вас заставляет составлять ldif-файлы и добавлять их через shell? Можете использовать программы для работы с LDAP-сервером, например ldapadmin: http://ldapadmin.sourceforge.net. Я давно пользуюсь этой программой и ни разу не испытывал неудобств.
Вернемся к добавлению записей в LDAP. Составленный нами ldif-файл нужно добавить в директории LDAP:
Enter password:
Первоначальная настройка LDAP-сервера закончена.
Настройка DNS-сервера
Первым делом необходимо установить bind. По умолчанию bind уже установлен во FreeBSD, но он не поддерживает работу с LDAP-сервером, поэтому необходимо установить другую версию bind, которая поддерживает работу с LDAP (bind9-sdb-ldap):
dns@/usr/ports/dns/bind9-sdb-ldap> make install clean
Проверим, что установился нужный нам bind.
bind9-sdb-ldap-9.3.2 The well known Bind9, patched for use of an LDAP based back
dns@/> /usr/local/sbin/named -v
BIND 9.3.2
Bind-sdb-ldap установился. Теперь создадим конфигурационный файл named.conf и подготовим сервис к запуску:
Named.conf
# Описание списков доступа к bind
acl lan { 192.168.1.0/24; };
acl transfers { 127.0.0.1; };
# Конфигурация rndc-ключа. Сгенерировать ключ можно командой
# rndc-confgen, вывод которой нужно вставить в named.conf
key "rndc-key" {
algorithm hmac-md5;
secret "V0spN5Z3OWgkGG2Bt0SdKQ==";
};
controls {
inet 127.0.0.1 port 953
allow { 127.0.0.1; } keys { "rndc-key"; };
};
# Опции демона named
options {
directory "/etc/namedb";
pid-file "/var/run/named/pid";
dump-file "/var/dump/named_dump.db";
statistics-file "/var/stats/named.stats";
# IP-адреса, на которых named будет слушать запросы
listen-on { 127.0.0.1; 192.168.1.254; }
# Если named не найдет адрес, запрашиваемый клиентом,
# в локальных базах или кэше, то запрос перенаправится
# DNS-серверам провайдера
forward only;
# DNS-сервера провайдеров
forwarders { 192.168.49.100; 172.16.0.3; };
# Разрешение запросов
allow-query { lan; trusted; };
allow-recursion { trusted; lan; };
};
# Описание зоны teachers
zone "teachers." {
# Наш сервер является первичным для этой зоны
type master;
# Где располагается зона.
# Формат записи: database «ldap протокол:
# //IP_адрес_LDAP_сервер/_путь_к_нужной_зоне_ ttl»
# Указанный ttl будет использован по умолчанию, если не будет указан другой ttl
database "ldap ldap://192.168.1.250/zoneName=teachers,ou=dns,dc=l1523,dc=ru 178600";
# Права доступа
allow-query { lan; trusted; };
allow-transfer { transfers;};
};
# Описание обратной зоны: 1.168.192.in-addr.arpa
zone "1.168.192.IN-ADDR.ARPA." {
# Наш сервер primary
type master;
# Где хранится зона
database "ldap ldap://192.168.1.250/zoneName=1.168.192.in-addr.arpa,ou=dns,dc=l1523,dc=ru 178600";
# Права доступа
allow-query { lan; trusted; };
allow-transfer { transfers; };
};
Все, конфигурационный файл составлен, подготавливаем named к запуску. Разрешаем запуск named:
Меняем путь к программе DNS-сервера. Это нужно для того, чтобы не запустился стандартный bind, который не умеет работать с LDAP. Стандартный bind лежит в /usr/sbin/named:
Теперь выставляем необходимые права на /var/named:
dns@/root/> chown –R bind:bind /var/named/var/
Теперь можно запускать DNS-сервер:
Stating named.
dns@/root/> ps ax | grep named
275 ?? Ss 0:01,64 /usr/sbin/syslogd -l /var/run/log -l /var/named/var/r
464 ?? Is 0:31,00 /usr/local/sbin/named -u bind -t /var/named
Bind запустился. Давайте проверим его на работоспособность. Проверяем работу утилитой rndc:
number of zones: 2
debug level: 0
xfers running: 0
xfers deferred: 0
soa queries in progress: 0
query logging is OFF
recursive clients: 0/1000
tcp clients: 0/100
server is up and running
dns@/root> dig @127.0.0.1 teachers. axfr
; <<>> DiG 9.3.2 <<>> @127.0.0.1 teachers. axfr
; (1 server found)
;; global options: printcmd
teachers. 178600 IN SOA ns.teachers. root.ns.teachers. 1 28800 7200 604800 86400
teachers. 178600 IN NS ns.teachers.
spider.teachers. 178600 IN A 192.168.1.250
ns.teachers. 178600 IN A 192.168.1.254
;; Query time: 26 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jan 11 22:27:24 2007
;; XFR size: 17 records (messages 1)
dns@/root> dig @127.0.0.1 1.168.192.in-addr.arpa axfr
; <<>> DiG 9.3.2 <<>> @127.0.0.1 1.168.192.in-addr.arpa axfr
; (1 server found)
;; global options: printcmd
1.168.192.in-addr.arpa. 178600 IN SOA ns.teachers. root.ns.teachers. 1 28800 7200 604800 86400
1.168.192.in-addr.arpa. 178600 IN NS ns.teachers.
250.1.168.192.in-addr.arpa. 178600 IN PTR spider.teachers.
254.1.168.192.in-addr.arpa. 178600 IN PTR ns.teachers.
;; Query time: 7 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jan 11 22:28:28 2007
;; XFR size: 12 records (messages 1)
Как видите, все работает. Единственное замечание: я запрашивал полный трансфер зоны с DNS-сервера, в моем конфигурационном файле выставлены права доступа, которые разрешают трансфер зон только IP-адресу 127.0.0.1, поэтому не пытайтесь скачать зону с другого компьютера. Все, теперь можно переходить к настройке DHCP-сервера.
Настройка DHCP-сервера
Сначала необходимо установить DHCP-сервер:
spider@/usr/ports/net/isc-dhcp3-server> make install clean
Сервер установлен. Теперь переходим к его настройке:
/root/dhcpd.conf
# Время, на которое выдается IP
default-lease-time 14400;
# Время, через которое клиент обязан вернуть IP
max-lease-time 28800;
log-facility local7;
authoritative;
# Не проводить обновление зон
ddns-update-style none;
# Описание сети 192.168.1.0/24
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.10 192.168.1.200;
ignore client-updates;
option domain-name "teachers";
option domain-name-servers 192.168.1.254;
option routers 192.168.1.254;
option default-ip-ttl 64;
option default-tcp-ttl 64;
}
Вот такой конфигурационный файл получился. Теперь его необходимо перевести в ldif-формат и добавить в LDAP. В поставку isc-dhcp-server входит perl-скрипт dhcpd-conf-to-ldap.pl. Давайте откроем его и отредактируем параметры в самом начале:
# Этот параметр можно не менять, будет использован результат, который вернет функция hostdomain()
my $domain = hostdomain();
# Корень сервера ldap
my $basedn = "dc=l1523,dc=ru";
# В этой строке скрипт заменяет все «.», указанные в $basedn на «,dc=»
$basedn =~ s/\./,dc=/g;
# Параметр можно не изменять, будет использован результат вызова функции hostname(),
# где будут храниться настройки DHCP
my $server = hostname();
my $dhcpcn = 'dhcp'; # CN of DHCP config tree
my $dhcpdn = "cn=$dhcpcn, $basedn"; # DHCP config tree DN
my $second = ''; # secondary server DN / hostname
my $i_conf = ''; # dhcp.conf file to read or stdin
my $o_ldif = ''; # output ldif file name or stdout
my @use = (); # extended flags (failover)
Все, теперь можно запускать:
Creating LDAP Configuration with the following options:
Base DN: dc=l1523,dc=ru
DHCP DN: cn=dhcp, dc=l1523,dc=ru
Server DN: cn=spider, dc=l1523,dc=ru
dn: cn=spider, dc=l1523,dc=ru
cn: spider
objectClass: top
objectClass: dhcpServer
dhcpServiceDN: cn=dhcp, dc=l1523,dc=ru
dn: cn=dhcp, dc=l1523,dc=ru
cn: dhcp
objectClass: top
objectClass: dhcpService
dhcpPrimaryDN: cn=spider, dc=l1523,dc=ru
dhcpStatements: default-lease-time 14400
dhcpStatements: max-lease-time 28800
dhcpStatements: log-facility local7
dhcpStatements: authoritative
dhcpStatements: ddns-update-style none
dn: cn=192.168.1.0, cn=dhcp, dc=l1523,dc=ru
cn: 192.168.1.0
objectClass: top
objectClass: dhcpSubnet
objectClass: dhcpOptions
dhcpNetMask: 24
dhcpRange: 192.168.1.10 192.168.1.200
dhcpStatements: ignore client-updates
dhcpOption: domain-name "teachers"
dhcpOption: domain-name-servers 192.168.1.254
dhcpOption: routers 192.168.1.254
dhcpOption: default-ip-ttl 64
dhcpOption: default-tcp-ttl 64
Done.
Скопируем вывод скрипта в файл dhcp.ldif и добавим его командой:
Теперь составим конфигурационный файл DHCP-сервера, в котором укажем параметры подключения к LDAP-серверу.
/usr/local/etc/dhcpd.conf
# IP-адрес или hostname LDAP-сервера
ldap-server "spider.teachers";
# Порт, который слушает LDAP
ldap-port 389;
# Учетная запись, под которой будет происходить подключение к LDAP-серверу.
ldap-username "cn=root,dc=l1523,dc=ru";
# Пароль учетной записи
ldap-password "123456";
# Корень LDAP-сервера
ldap-base-dn "dc=l1523,dc=ru";
ldap-method dynamic;
Теперь запускаем DHCP-сервер:
spider@/root/> /usr/local/etc/rc.d/isc-dhcpd.sh start
Starting dhcpd.
Internet Systems Consortium DHCP Server V3.0.5rc2
Copyright 2004-2006 Internet Systems Consortium.
All rights reserved.
For info, please visit http://www.isc.org/sw/dhcp/
TLS session successfully started to spider.teachers
Wrote 17 leases to leases file.
Listening on BPF/xl0/00:0a:5e:42:b8:01/192.168.1/24
Sending on BPF/xl0/00:0a:5e:42:b8:01/192.168.1/24
Sending on Socket/fallback/fallback-net
Отлично! Сервер запустился. Осталось настроить динамическое обновление DNS-зон. К сожалению, пакет bind-sdb-ldap не умеет сам обновлять записи в LDAP, так же как и DHCP. Поэтому придется использовать скрипт, написанный Travis Groth. Подробнее об этом можете почитать на странице: http://www.venaas.no/ldap/bind-sdb. Давайте скачаем и настроим скрипт:
spider@/root/> cd dhcp
spider@/root/dhcp/> fetch http://www.venaas.no/ldap/bind-sdb/dhcp2ldapd-1.1.gz
dhcp2ldapd-1.1.gz 100% of 2185 B 1279 Bps
spider@/root/dhcp/> gunzip dhcp2ldapd-1.1.gz
spider@/root/dhcp/> ll
total 10
drwxr-xr-x 2 root wheel 512B 11 янв 23:18 .
drwxr-xr-x 8 root wheel 1,5K 11 янв 23:18 ..
-rw-r–r– 1 root wheel 5,3K 3 май 2005 dhcp2ldapd-1.1
Теперь отредактируем скрипт. В самом начале:
Dhcp2ldapd-1.1
#!/usr/bin/perl
# Файл, где хранится информация о выданных адресах DHCP-сервером
$LEASES = "/var/db/dhcpd/dhcpd.leases";
# Домен
$DOMAIN = "teachers";
# Обратная зона
$REVERSE = "1.168.192.in-addr.arpa";
# Где в LDAP хранятся зоны прямого и обратного преобразования
$FORWARD_BASE = "zoneName=teachers,ou=dns,dc=l1523,dc=ru";
$REVERSE_BASE = "zoneName=1.168.192.in-addr.arpa, ?
ou=dns,dc=l1523,dc=ru";
# Пользователь для подключения к LDAP-серверу
$USER = 'cn=root,dc=l1523,dc=ru';
# Пароль пользователя
$PASSWORD = "9vpIj9";
# Хост, на котором работает LDAP-сервер
$LDAP_HOST = 'localhost'
# Время проверки файла в секундах
$UPDATE_TIME = 30;
# Автопроверка
$AUTO_VERIFY = 0;
Еще необходимо подправить две строчки в скрипте, потому что у меня сеть с маской 24, а скрипт добавляет записи для маски 16. Поэтому правим строку 172 и 174, меняем там $fourth.$third на $fourth. Все, после этого можно запускать наш скрипт, но сначала составим скрипт запуска:
#!/bin/sh
case "$1" in
start)
if [ -f /var/run/dhcpd2ldap.pid ]
then
echo "Скрипт dhcpd2ldap уже запущен!"
else
daemon -f -p /var/run/dhcpd2ldap.pid /root/dhcp2ldapd-1.1
echo "Скрипт dhcpd2ldap запущен!"
fi
;;
stop)
if [ -f /var/run/dhcpd2ldap.pid ]
then
kill -TERM `cat /var/run/dhcpd2ldap.pid`
rm -f /var/run/dhcpd2ldap.pid
echo "Скрипт dhcpd2ldap остановлен!"
else
echo "Скрипт dhcpd2ldap не запущен!"
fi
;;
*)
echo "Использование: ${0##*/}: { start | stop }" >&2
exit 64
;;
esac
Такой скрипт кладем в /usr/local/etc/rc.d/ и выставляем нормальные права:
spider@/usr/local/etc/rc.d/> chown root:wheel dhcpd2ldap.sh
spider@/usr/local/etc/rc.d/> ll dhcpd2ldap.sh
-rwxr-xr-x 1 root wheel 586B 19 янв 12:19 dhcpd2ldap.sh
Теперь пробуем запустить:
483 ?? Is 0:01,56 /usr/local/sbin/dhcpd -cf /usr/local/etc/dhcpd.conf -
54964 p0 R+ 0:00,00 grep dhcp
spider@/usr/local/etc/rc.d/> ./dhcpd2ldap.sh start
Скрипт dhcpd2ldap запущен!
483 ?? Is 0:01,56 /usr/local/sbin/dhcpd -cf /usr/local/etc/dhcpd.conf -
54967 ?? Ss 0:00,40 /usr/bin/perl /root/dhcp2ldapd-1.1 (perl5.8.8)
54969 p0 R+ 0:00,00 grep dhcp
Как видите, скрипт запустился успешно. Переходим к тестированию нашей связки.
Тестирование
Давайте для начала посмотрим pid DNS-сервера, для того чтобы далее можно было проконтролировать, что named не перезапускался:
264 ?? Ss 0:00,50 /usr/sbin/syslogd -l /var/run/log -l /var/named/var/r
448 ?? Ss 1:17,13 /usr/local/sbin/named -u bind -t /var/named
22315 p0 R+ 0:00,00 grep named
Pid named – 448. Теперь проверим, резолвится ли адрес машины, которую мы вскоре добавим в нашу сеть. Имя машины – fr33man:
Host fr33man not found: 3(NXDOMAIN)
shield@/root> ldapsearch -LLL -x -b ‘dc=l1523,dc=ru’ -H ldap://spider/ ‘relativeDomainName=fr33man’
Адрес не резолвится, в LDAP также нет записей об этом адресе. Теперь подключим машину к сети и настроим на получение IP-адреса от DHCP-сервера. После этого проверим, резолвится ли адрес:
fr33man.teachers has address 192.168.1.199
shield@/root> host 192.168.1.199
shield@/root> host 192.168.1.199
shield@/root> ldapsearch -LLL -x -b ‘dc=l1523,dc=ru’ -H ldap://spider/ ‘relativeDomainName=fr33man’
dn: relativeDomainName=fr33man,zoneName=teachers,ou=dns,dc=l1523,dc=ru
relativeDomainName: fr33man
objectClass: top
objectClass: dNSZone
dNSTTL: 7200
zoneName: teachers
aRecord: 192.168.1.199
shield@/root> ldapsearch -LLL -x -b ‘dc=l1523,dc=ru’ -H ldap://spider/ ‘relativeDomainName=199′
dn: relativeDomainName=199,zoneName=1.168.192.in-addr.arpa,ou=dns,dc=l1523,dc=ru
relativeDomainName: 199
objectClass: top
objectClass: dNSZone
dNSTTL: 7200
zoneName: 1.168.192.in-addr.arpa
pTRRecord: fr33man.teachers.
Как видите, адрес резолвится, и в LDAP появились записи о нашем адресе. И под конец проверим pid named:
264 ?? Ss 0:00,50 /usr/sbin/syslogd -l /var/run/log -l /var/named/var/r
448 ?? Is 1:17,41 /usr/local/sbin/named -u bind -t /var/named
Pid не изменился, следовательно, DNS-сервер не перезапускался и изменения «подхватились» автоматически.
За и против
Мы получили работающую связку, удобную в управлении. Для того чтобы обновить зоны или конфигурацию DHCP, достаточно изменить записи в LDAP, а для этого можно использовать программы для работы с LDAP-сервером. Еще одним плюсом является то, что при изменении информации на LDAP-сервере изменения вступят в силу без перезагрузки зоны. Централизованное хранение данных для крупных компаний выгоднее по нескольким причинам:
Все данные хранятся в одной базе. Если с этой базой что-то случится, то восстанавливать придется только ее, а не бегать по всем серверам и восстанавливать по отдельности каждый сервис.
Управлять базой можно из любой ОС, так как стандарт работы LDAP один.
Из минусов можно отметить, что управление немного усложняется, но результат того стоит. Использовать централизованную базу лучше только в сетях со сложной структурой, а для маленьких сетей централизованное хранение данных не так выгодно.
Василий Озеров
Журнал “Системный администратор”