Страница 1 из 2

Не BIND'ом единым жив DNS

Добавлено: 15 дек 2011, 16:56
Raven
Думаю каждый системный администратор хотя бы раз в своей жизни настраивал сервер DNS. Я более чем уверен что в 99% DNS-серверов под *nix это был BIND. Однако, не смотря на то, что бинд был и остается пока стандартом де-факто в мире DNS-серверов, все же и у него есть и недостатки - слишком уж часто выявляются все новые и новые бреши в безопасности, аппетиты его оставляют желать лучшего и... нового железа. Не спорю - BIND хорош в качестве авторитарного сервера, но вот в качестве кэширующего рекурсивного DNS-сервера он реально страшен. К тому же по заявлениям разработчиков, 10-я версия BIND будет совмещена с сервером DHCP (кому спрашивается нужен такой монстр). Поэтому я давно начал задумываться о переходе на что-нибудь более легкое и шустрое, поэтому задумал поставить на новый хостинг настраиваемый мной PowerDNS, а затем случилось страшное - на мастер-сервере (bind) обнаружилась проблема с кэшем - он упорно не хотел выдавать ответы из кэша. Очень долго промучавшись я выяснил только одно - что мои подозрения по его поводу оправдались и надо что-то с этим делать... Итак, рассмотрим несколько вариантов легких DNS-серверов в качестве альтернативы старичку.

Параметры машины:
KVM-guest, 1000MHz CPU, 2Gb RAM, 8Gb Hdd, 2 сетевухи (1 смотрит в локалку, 2-я в сеть). ОС - FreeBSD 7.4-amd64

Unbound

Unbound - это кеширующий DNS сервер который обслуживает исключительно рекурсивные запросы. Во время работы сервера кеш целиком распологается в памяти, а его размер ограничен указанным объемом. Unbound поддерживает расширения DNSSEC и может работать как "validator" . В качестве плюсов Unbound по сравнению с BIND надо отметить все те же скромные размеры и скорость.
Решено - ставлю!

Надеюсь не нужно рассказывать о необходимости обновления портов :)

Код: Выделить всё

cd /usr/ports/dns/unbound
make install clean

Код: Выделить всё

┌────────────────────────────────────────────────────────────────────┐
│                    Options for unbound 1.4.13                       │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ [X] LIBEVENT  is useful when using many (10000) outgoing ports   │ │
│ │ [X] THREADS   build with threads support                        │ │
│ │ [ ] PYTHON    build python bindings                             │ │
│ │ [ ] GOST      build GOST support (requires OpenSSL from ports)   │ │
│ │                                                                │ │
├─└────────────────────────────────────────────────────────────────┘─┤
│                       [  OK  ]       Cancel                        │
└────────────────────────────────────────────────────────────────────┘
Описывать детально основные опции не буду, ибо лучше чем это сделал terminus я все равно не смогу:
terminus писал(а):При проведении разрешения имен которых еще нет в кеше сервера, а значит при необходимости обращаться к внешним авторитарным DNS серверам, Unbound отсылает исходящие запросы используя множество UDP портов из разрешенного диапазона. Это сделано для обеспечения дополнительной безопасности чтобы было труднее угадать с какого порта был отправлен запрос и затруднить возможность атак с целью отравления записей в кеше. Позже, в примере файла конфигурации это будет отражено - опция outgoing-range: 512 указывает, сколько UDP портов для этой цели разрешено использовать одному потоку (thread) сервера.

Каждый открытый сервером UDP или TCP порт, потребляет один файловый дескриптор. Серверу Unbound необходимо иметь возможность работать со всеми открытыми дескрипторами. Сам Unbound содержит в себе некий builtinmini-event обработчик, который и используется для этого. Встроенный обработчик способен обслуживать максимум 1024 открытых файловый дескрипторов на один процесс сервера.

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

Если же отказаться от опции THREADS, то сервер будет собран без потоков (фактически с одним потоком на процесс) и будет происходить форканье процессов, что есть практически параллельный запуск нового сервера со своим собственным кешем. Минус такого подхода - это увеличение требований к памяти. Плюс этого метода работы - увеличение скорости на 10-20 %.

Таким образом, если наш сервер будет собран с поддержкой потоков THREADS, и мы захотим использовать восемь потоков (опция конфигурации num-threads: 8), то при установленных outgoing-range: 512, в сумме это даст 512*8=4096 одновременно открытых файловых дескрипторов, что превышает возможности встроенного обработчика. Unbound не захочет стартовать и выведет сообщение об ошибке. Проблема. (Кривое решение проблемы - это снизить значение outgoing-range, но делать этого не стоит так как это уменьшает секюрность). Для правильного решения этой проблемы, разработчики Unbound предлагают использовать специальные сторонние обработчики, такие как например libevent или libev. Выбор опции LIBEVENT приведет к установке дополнительного порта libevent 1.4.8 и линковке с ним Unbound.

Если же мы откажемся от использования потоков и соберем Unbound без THREADS, и без ненужного теперь LIBEVENT, то при использовании той же опции конфигурации num-threads: 8, мы получим восемь процессов Unbound каждый из которых будет иметь свой кеш и использовать только 512 файловых дескрипторов управляемых встроенным обработчиком.
Едем дальше - сервер собран, ничто не мешает нам его настроить.

Для начала нужен chroot - запускать DNS-серверы в основной среде вообще признак дурного тона. Я для себя выбрал директорию /srv/unbound (у меня в /usr/local заканчивается место)

Код: Выделить всё

mkdir /srv
mkdir /srv/unbound
mv /usr/local/etc/unbound/unbound.conf.sample /srv/unbound/unbound.conf
ln -sf /srv/unbound/unbound.conf /usr/local/etc/unbound/unbound.conf #Симлинк назад, ибо лень мне править стартовые скрипты
mkdir /srv/unbound/dev
Теперь нужно примонтировать /dev в /srv/unbound/dev, но как вы наверное все понимаете это не самый безопасный выход - из чрута будут доступны все файлы устройств, а это ой как небезопасно! По рекомендации все того же terminus'a пришлось прибегнуть к частичному монтированию /dev посредством devfs. Вписываем в /etc/devfs.rules правила для нашего chroot-ового /dev

Код: Выделить всё

[unbound_ruleset=20]
add hide
add path null unhide
add path zero unhide
add path crypto unhide
add path random unhide
add path urandom unhide
Добавим строчку в /etc/fstab

Код: Выделить всё

devfs  /srv/unbound/dev        devfs   rw      0       0
И внесем параметры запуска в /etc/rc.conf

Код: Выделить всё

devfs_set_rulesets="/srv/unbound/dev=unbound_ruleset"
Монтируем папку и перезапускаем сервис:

Код: Выделить всё

mount /srv/unbound/dev
/etc/rc.d/devfs restart
И проверим результаты:

Код: Выделить всё

ls -la /srv/unbound/dev
total 0
crw-rw-rw-  1 root  wheel    0,  19 15 дек 16:33 null
crw-rw-rw-  1 root  wheel    0,  23 15 дек 10:39 random
lrwxr-xr-x  1 root  wheel         6 15 дек 16:43 urandom -> random
crw-rw-rw-  1 root  wheel    0,  20 15 дек 10:39 zero
Скачиваем корневую зону в папку к unbound

Код: Выделить всё

cd /srv/unbound
fetch -o root.zone ftp://FTP.INTERNIC.NET/domain/named.cache
Cенерируем ключи для работы unbound-control:

Код: Выделить всё

unbound-control-setup -d /srv/unbound
setup in directory /srv/unbound
generating unbound_server.key
Generating RSA private key, 1536 bit long modulus
............++++
............................++++
e is 65537 (0x10001)
generating unbound_control.key
Generating RSA private key, 1536 bit long modulus
...................................................................++++
.................++++
e is 65537 (0x10001)
create unbound_server.pem (self signed certificate)
create unbound_control.pem (signed client certificate)
Signature ok
subject=/CN=unbound-control
Getting CA Private Key
Setup success. Certificates created. Enable in unbound.conf file to use
Меняем права на ключи.

Код: Выделить всё

chown unbound:wheel ./unbound_*
chmod 440 ./unbound_*
Ну а теперь правим конфиг:

Код: Выделить всё

cat unbound.conf 
server:          
         verbosity: 2 # Степень вывода логов (1-4, при уровне 4 в логи будет попадать вся отладочная информация, при уровне 1 - только сообщения об ошибках)
         statistics-interval: 0 # Я не собираю статистику, поэтому эти 3 строки мне в принципе не нужны
         statistics-cumulative: no
         extended-statistics: no  
         num-threads: 1 # Количество потоков. Рекомендуется ставить равным числу ядер процессора
         interface: 192.168.50.32 # Интерфейс на котором будем слушать
         interface-automatic: no  # Определять интерфейсы автоматически мне не нужно
         port: 53  
         outgoing-interface: <внешний_IP> # Интерфейс для связи с внешним миром
         outgoing-range: 8192 # Диапазон портов для связи с миром. При использовании libevent рекомендуется использовать данное значение.
         outgoing-port-permit: 32768     
         outgoing-port-avoid: "3200-3208"
         outgoing-num-tcp: 10            
         incoming-num-tcp: 10            
         so-rcvbuf: 4m  # Зарезервированный обьем буфра для приема UDP пакетов (рекомендованное стартовое значение)
         so-sndbuf: 4m  # Зарезервированный обьем буфера для отправки UDP пакетов (рекомендованное стартовое значение)
         edns-buffer-size: 4096          
         msg-buffer-size: 65552          
         msg-cache-size: 32m             
         msg-cache-slabs: 4              
         num-queries-per-thread: 4096    
         rrset-cache-size: 64m           
         rrset-cache-slabs: 4            
         cache-min-ttl: 86400            
         cache-max-ttl: 864000           
         infra-host-ttl: 900             
         infra-lame-ttl: 900             
         infra-cache-slabs: 4            
         infra-cache-numhosts: 10000     
         infra-cache-lame-size: 10k      
         do-ip4: yes                     
         do-ip6: no                      
         do-udp: yes                     
         do-tcp: yes                     
         do-daemonize: yes               
         access-control: 0.0.0.0/0 allow 
         access-control: ::0/0 refuse         
         access-control: ::1 allow            
         access-control: ::ffff:127.0.0.1 allow
         chroot: "/srv/unbound"                
         username: "unbound"                   
         directory: "/srv/unbound"             
         logfile: "/srv/unbound/log/unbound.log"
         use-syslog: no                         
         log-time-ascii: no                     
         log-queries: yes                       
         pidfile: "/srv/unbound/unbound.pid"    
         root-hints: "/srv/unbound/named.cache" 
         hide-identity: yes                     
         hide-version: yes                      
         identity: "MySuper-Puper DNS"          
         version: "100.500"                         
         harden-glue: yes                       
         do-not-query-address: 127.0.0.1/8
         do-not-query-address: ::1
         do-not-query-localhost: yes
         module-config: "iterator"

remote-control:
         control-enable: yes
         control-interface: 127.0.0.1
         control-port: 8953
         server-key-file: "/srv/unbound/unbound_server.key"
         server-cert-file: "/srv/unbound/unbound_server.pem"
         control-key-file: "/srv/unbound/unbound_control.key"
         control-cert-file: "/srv/unbound/unbound_control.pem"
Проверим параметры ядра:

Код: Выделить всё

sysctl -a | grep kern.maxfiles
sysctl -a | grep kern.ipc.maxsockets
sysctl -a | kern.ipc.maxsockbuf
У меня их значения такие:

Код: Выделить всё

kern.maxfiles: 90000
kern.maxfilesperproc: 230400
kern.ipc.maxsockets: 204800
kern.ipc.maxsockbuf: 16777216
Исправляем их на лету, вносим их в /etc/sysctl.conf и прописываем в /etc/rc.conf:

Код: Выделить всё

unbound_enable="YES"
Можно стартовать

Код: Выделить всё

/usr/local/etc/rc.d/unbound start
И проверять:

Код: Выделить всё

nslookup mail.ru 192.168.50.32
Server:         192.168.50.32
Address:        192.168.50.32#53

Non-authoritative answer:
Name:   mail.ru
Address: 94.100.191.203
Name:   mail.ru
Address: 94.100.191.204
Name:   mail.ru
Address: 94.100.191.201
Name:   mail.ru
Address: 94.100.191.202
На данный момент сервер отработал 1 сутки с нагрузкой около 10к запросов с секунду - полет нормальный)))

Re: Не BIND'ом единым жив DNS

Добавлено: 16 мар 2012, 18:12
Raven
Издавна мною было замечено, что bind на моих подопечных много-много кушает, причем лично для меня это святотатство - отдавать 850M оперы на поток - жаба душит. Нагрузка на проц в пределах 250-350% сильно ощутима даже на шестнадцатиядерниках. В общем надоел он мне, решил я напнуть его нафиг!

Но возник вопрос - чем заменить? Все мало-мальски толковые авторитарные сервера почему-то сделаны ЧИСТО авторитарными!!! Т.е. резольвера у них либо нет вообще, либо ставится и настраивается отдельно. По скорости и минимализму лидеры тут безусловно NSD и PowerDNS, но ни тот, ни другой не умеют самостоятельно слать рекурсивные запросы. У PowerDNS есть в комплекте резольвер - рекурсивный dns-сервер PowerDNS-recursor, у NSD и того нету, зато у него есть весьма скоростной брат - Unbound, описаный постом выше. С PDNS-recursor'ом я как-то уже сталкивался, чегой-то он мне дюже не понравился - вместо обещаного прироста скорости я стал ощущать "висяки" - сервер "проседал" (хотя тут могут быть виновны мои кривые руки :) ), поэтому вариант использования его на продакшне был отвергнут сразу же во избежание рецидивов (да и не так давно в одной из староватых версий его была найдена серьезная дырень способствующая заражению кэша).

В итоге созрел сл. план:
  • Вариант 1: PowerDNS+Unbound с бэкендом в MySQL
    Вариант 2: NSD+Unbound с хранением зон в виде файлов (вариант особо уважаемый среди сторонников "православного" bind'a)
Итак, исходим из следующей конфиги:
2 ядра по 2.24 GHz, 2 Gb RAM, свежеуствновленая FreeBSD 9.0, с пересобраным миром и ядром, а также свежеобновленной коллекцией поротов.

Начнем, пожалуй, со 2-го варианта.
Ставим софт:

Код: Выделить всё

# make -C /usr/ports/dns/unbound install clean && make -C /usr/ports/dns/nsd install clean
Опции для сборки Unbound используем те же что и в предыдущем посте, для NSD мной были выбраны следующие:
  • LARGEFILE Enable support for large files
  • BIND8_STATS Enable BIND8 like NSTATS & XSTATS
  • NSEC3 Enable NSEC3 support
  • MINRESPSIZE Enable minimized response size
  • NSEC3PREHASH Enable full NSEC3 prehashing
  • MAXIPS Raise max-ips from 8 to 512
Наливаем кофе пока все это собирается)))
Далее проделываем с конфигом Unbound то же самое, что и в предыдущем посте, я правда не стал заморачиваться с chroot - работать это все будет в KVM-госте, так что чрутить смысла не вижу.
В итоге у меня получился конфиг следующего содержания:

Код: Выделить всё

server:                                             
         verbosity: 2                               
         statistics-interval: 0                     
         statistics-cumulative: no                  
         extended-statistics: no                    
         num-threads: 2                             
         interface: xxx.xxx.xxx.xxx         
         interface-automatic: no                    
         port: 53                                   
         outgoing-interface: xxx.xxx.xxx.xxx 
         outgoing-range: 1024                       
         outgoing-port-permit: 32768-65000          
         outgoing-port-avoid: "3200-3208"           
         outgoing-num-tcp: 10                       
         incoming-num-tcp: 10                       
         so-rcvbuf: 8m                              
         so-sndbuf: 8m                              
         edns-buffer-size: 4096                     
         msg-buffer-size: 65552                     
         msg-cache-size: 32m                        
         msg-cache-slabs: 8                         
         num-queries-per-thread: 4096
         rrset-cache-size: 64m
         rrset-cache-slabs: 8
         cache-min-ttl: 86400
         cache-max-ttl: 864000
         infra-host-ttl: 60
         infra-lame-ttl: 120
         infra-cache-slabs: 4
         infra-cache-numhosts: 10000
         infra-cache-lame-size: 10k
         do-ip4: yes
         do-ip6: no
         do-udp: yes
         do-tcp: yes
         do-daemonize: yes
         access-control: 0.0.0.0/0 allow
         access-control: ::0/0 allow
         access-control: ::1 allow
         access-control: ::ffff:127.0.0.1 allow
         username: "unbound"
         directory: "/usr/local/etc/unbound"
         logfile: "/var/log/unbound.log"
         use-syslog: yes
         log-time-ascii: no
         log-queries: yes
         pidfile: "/var/run/unbound.pid"
         root-hints: "/usr/local/etc/unbound/root.zone"
         hide-identity: yes
         hide-version: yes
         identity: "Unbound"
         version: "1.1.2"
         harden-glue: yes
         do-not-query-address: 127.0.0.1/8
         do-not-query-address: ::1
         do-not-query-localhost: yes
         module-config: "iterator"

remote-control:
         control-enable: yes
         control-interface: 127.0.0.1
         control-port: 8953
         server-key-file: "/usr/local/etc/unbound/unbound_server.key"
         server-cert-file: "/usr/local/etc/unbound/unbound_server.pem"
         control-key-file: "/usr/local/etc/unbound/unbound_control.key"
         control-cert-file: "/usr/local/etc/unbound/unbound_control.pem"
Как вы можете заметить особых различий в конфигах практически нет, если исключить пути и мелкий тюнинг. Главное отличие - 2 последние строки подключающие 2 файла. Но о них позже, давайте займемся настройкой NSD. В виду того, что данные эксперименты проводятся в виртуальной машине я не стал использовать chroot - контейнер VM сам по себе идеальный chroot.

Код: Выделить всё

server:
        ip-address: 192.168.50.102 # Вешаем на серый ип
        port: 53
        ip4-only: yes
        identity: "unidentified server"
        hide-version: yes
        database: "/var/db/nsd/nsd.db"
        logfile: "/var/log/nsd.log"
        server-count: 2
        pidfile: "/var/run/nsd.pid"
        zonesdir: "/usr/local/etc/nsd/zones"
        difffile: "/var/db/ndb/ixfr.db"
        xfrdfile: "/var/db/ndb/xfrd.state"
        tcp-timeout: 120
        ipv4-edns-size: 4096
        tcp-query-count: 0
        tcp-count: 10
        username: unbound
zone:
        name: "example.com"
        zonefile: "./zones/example.com"
        notify: 192.168.50.202  NOKEY
        provide-xfr: 192.168.50.202  NOKEY
        notify-retry: 5
        outgoing-interface: 192.168.50.102
zone:
        name: "50.168.192.in-addr.arpa"
        zonefile: "./zones/50.168.192.in-addr.arpa"
        notify: 192.168.50.202  NOKEY
        notify-retry: 5
        outgoing-interface: 192.168.50.102
        provide-xfr: 192.168.50.202  NOKEY
Файлы зон - стандартные, такие же как и у bind'a:

Код: Выделить всё

$TTL 1800 ;minimum ttl
example.com.	IN	SOA	ns1.example.com. admin.example.com. (
			2012031601	;serial
			3600	 	;refresh
			9600		;retry
			180000	 	;expire
			600		;negative ttl
			)

		NS		ns1.domain.su.
		NS		ns2.domain.su.
		MX	10	mail
		A		192.168.50.1

ns1		A		192.168.50.102
ns2		A		192.168.50.202
www		A		192.168.50.1
ftp		A		192.168.50.2
mail		A		192.168.50.3

Зона обратного просмотра тоже в принципе стандартна:

Код: Выделить всё

$TTL 1800 ;minimum ttl
50.168.192.in-addr.arpa. IN      SOA     ns1.example.com. admin.example.com. (
                                2012031601      ;serial
                                3600            ;refresh
                                9600            ;retry
                                180000          ;expire
                                600             ;negative ttl
                                )

                NS              ns1.example.com.
                NS              ns2.example.com.

102               PTR             ns1.example.com.
202               PTR             ns2.example.com.
1               PTR             example.com.
1               PTR             ftp.example.com.
3               PTR             mail.example.com.

Дописываем nsd_enable="YES" в /etc/rc.conf и стартуем демон:

Код: Выделить всё

# service nsd start
Если все запустилось нормально - проверяем (если нет - тогда в логи!):

Код: Выделить всё

# nslookup example.com 192.168.50.102
Server:         192.168.50.102
Address:        192.168.50.102#53

Name:   example.com
Address: 192.168.50.1
Отлично! Вяжем голубчеГоф!

Открываем /usr/local/etc/unbound/unbound.conf и добавляем в конец файла:

Код: Выделить всё

forward-zone:
        name: "example.com"
        forward-addr: 192.168.50.102
forward-zone:
        name: "50.168.192.in-addr.arpa"
        forward-addr: 192.168.50.102
Добавим unbound_enable="YES" в /etc/rc.conf и сттартуем демон

Код: Выделить всё

service unbound start
Если все правильно - nslookup example.com xxx.xxx.xxx.xxx должен отдать тот же ип что и та же команда по серому ипу.

Итак, схема работы следующая:

Запрос на внешнем интерфейсе ловит Unbound и если он соответствует форвардинговой зоне перенаправляет его на поклон NSD, если же нет - опросит корневые сервера. В итоге система показала минимум загрузки при максимуме скорости. Но есть одно неудобства - приходится прописывать 1 зону в 2-х серверах! Имхо жутко неудобно, поэтому я буду тестировать вторую связку. Результаты будут позже)

Не BIND'ом единым жив DNS

Добавлено: 16 мар 2012, 21:55
Vano
Спасибо, очень полезный ман! надо будет опробовать эту связку *BEER*

Re: Не BIND'ом единым жив DNS

Добавлено: 16 мар 2012, 23:38
Infernal Flame
Vano
это актуально в продакшне при 10к+ пользователях... в остальном - и бинда не скопытится в принципе... при правильном продходе.

Re: Не BIND'ом единым жив DNS

Добавлено: 17 мар 2012, 08:07
Vano
Infernal Flame
Ога, понимаю. Хочу поставить на виртуалку, для обучения. :-[

Re: Не BIND'ом единым жив DNS

Добавлено: 19 мар 2012, 14:14
Raven
Итак, продолжаем. Решил значит я опробовать 1 вариант - PDNS+Unbound. Основная загвоздка - pdns работает с БД, а отдавать львиную долю ресурсов под MySQL не особо хочется, а postgresql хоть и может заводиться даже на мобильнике, но к сожалению не все толковые панели управения powerdns изьявляют желание работать с ней, а раз уж будем юзать базу, то зачем отказываться от возможности поднять морду? Немного покумекав принимаю решение - была не была! Ставим! Черт с ней с ресой - в случае чего БД можно вынести и на другой хост. Исходя из аппетитов InnoDB и ненадежности MyISAM будем ставить MariaDB - почему-то я ей больше доверяю... Хотя быть может это чисто ИМХОвый пунктик.

Код: Выделить всё

# make -C /usr/ports/databases/mariadb-server install clean
Отключаем все лишние хранилища вроде archive, ndb, xtradb, innodb - будем использовать форк MyISAM - Aria.

Устанавливаем powerdns:

Код: Выделить всё

# make -C /usr/ports/dns/powerdns install clean
Из параметров я выбрал только поддержку mysql - все остальное мне ни к чему.

Тюним машку - правим my.cnf:

Код: Выделить всё

[mysqld]
local-infile=0
max_connections = 512
datadir=/var/db/mysql
character-set-server = utf8
skip-external-locking

port = 3306
socket = /tmp/mysql.sock
key_buffer = 16K
max_allowed_packet = 1M
table_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K
query_cache_limit=256K

log-slow-queries

[mysql]
no-auto-rehash
port = 3306
socket = /tmp/mysql.sock
default-character-set = utf8

[isamchk]
key_buffer = 8M
sort_buffer_size = 8M

[myisamchk]
key_buffer = 8M
sort_buffer_size = 8M

[mysqlhotcopy]
interactive-timeout
Дописываем в /etc/rc.conf

Код: Выделить всё

mysql_enable="YES"
и запускаем:

Код: Выделить всё

# service mysql-server start
Задаем пароль, создаем базу:

Код: Выделить всё

# mysqladmin password <новый_пароль>
# mysql -uroot -p<пароль>
MariaDB [(none)]> CREATE DATABASE powerdns;
MariaDB [(none)]> GRANT ALL ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'mypass';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]>\q
Создаем файлик db.sql следующего содержания:

Код: Выделить всё

SET SESSION sql_mode='ANSI';

CREATE TABLE "domains" (
 "id" INTEGER NOT NULL AUTO_INCREMENT,
 "name" VARCHAR(255) NOT NULL,
 "type" VARCHAR(6) NOT NULL,
 "master" VARCHAR(40) NOT NULL DEFAULT '',
 "account" VARCHAR(40) NOT NULL DEFAULT '',
 "last_check" INTEGER DEFAULT NULL,
 "notified_serial" INTEGER DEFAULT NULL,
 "auto_serial" INTEGER NOT NULL DEFAULT 0,
 "status" CHAR(1) NOT NULL DEFAULT 'A',
CONSTRAINT "pdns_pk_domains_id"
 PRIMARY KEY ("id"),
CONSTRAINT "pdns_unq_domains_name"
 UNIQUE ("name")
) type=Aria;

CREATE INDEX "pdns_idx_domains_status_type" ON "domains" ("status","type");



CREATE TABLE "records" (
 "id" INTEGER NOT NULL AUTO_INCREMENT,
 "domain_id" INTEGER NOT NULL,
 "name" VARCHAR(255) NOT NULL,
 "type" VARCHAR(6) NOT NULL,
 "content" VARCHAR(255) NOT NULL,
 "ttl" INTEGER DEFAULT NULL,
 "prio" INTEGER DEFAULT NULL,
 "change_date" INTEGER(11) DEFAULT NULL,
CONSTRAINT "pdns_pk_records_id"
 PRIMARY KEY ("id"),
CONSTRAINT "pdns_fk_records_domainid"
 FOREIGN KEY ("domain_id")
 REFERENCES "domains" ("id")
 ON UPDATE CASCADE
 ON DELETE CASCADE
) type=Aria;


 

CREATE INDEX "pdns_idx_records_name_type" ON "records" ("name","type");
CREATE INDEX "pdns_idx_records_type" ON "records" ("type");



CREATE TABLE "supermasters" (
 "ip" VARCHAR(40) NOT NULL,
 "nameserver" VARCHAR(255) NOT NULL,
 "account" VARCHAR(40) NOT NULL DEFAULT ''
);

CREATE INDEX "pdns_idx_smaster_ip_ns" ON "supermasters" ("ip","nameserver");



GRANT SELECT ON "supermasters" TO "powerdns";
GRANT ALL ON "domains" TO "powerdns";
GRANT ALL ON "records" TO "powerdns";



DELIMITER :

CREATE TRIGGER "pdns_trig_records_insert"
AFTER INSERT ON "records"
FOR EACH ROW BEGIN
 UPDATE "domains" d SET d."auto_serial" = d."auto_serial" + 1
 WHERE d."id" = NEW."domain_id";
END;:

CREATE TRIGGER "pdns_trig_records_update"
AFTER UPDATE ON "records"
FOR EACH ROW BEGIN
 UPDATE "domains" d SET d."auto_serial" = d."auto_serial" + 1
 WHERE d."id" = NEW."domain_id";
END;:

CREATE TRIGGER "pdns_trig_records_delete"
AFTER DELETE ON "records"
FOR EACH ROW BEGIN
 UPDATE "domains" d SET d."auto_serial" = d."auto_serial" + 1
 WHERE d."id" = OLD."domain_id";
END;:

DELIMITER ;
и загоняем его в базу:

Код: Выделить всё

# mysql -uroot -p<пароль> powerdns < db.sql
Теперь нужнео перегнать зоны в базу. В этом нам поможет утилитка zone2sql идущая вместе с powerdns. Надеюсь вы не успели порушить пути в named.conf (я успел и пришлось все вертать назад %) ). Перегоняем:

Код: Выделить всё

# zone2sql --qmysql --named-conf=/etc/namedb/named.conf --verbose > zones.sql
# mysql -uroot -p<пароль> powerdns < zones.sql
Перестраиваем Unbound - закоментируем все записи касающиеся зон и сменим интерфейсы:

Код: Выделить всё

#forward-zone:
#        name: "example.com"
#        forward-addr: 192.168.50.102
#forward-zone:
#        name: "50.168.192.in-addr.arpa"
#        forward-addr: 192.168.50.102

Код: Выделить всё

         interface: 192.168.0.102 # Вешаем его на внутренний интерфейс
Тушим NSD и перезапускаем unbound

Код: Выделить всё

# service nsd stop
# service unbound restart
Конфигурим powerdns:

Код: Выделить всё

# cat /usr/local/etc/pdns/pdns.conf
allow-axfr-ips=192.168.0.202
allow-recursion=0.0.0.0/0
cache-ttl=20
config-dir=/usr/local/etc/pdns
control-console=no
daemon=yes
default-soa-name=ns.example.com
default-ttl=3600
disable-tcp=no
guardian=yes
launch=gmysql
gmysql-host=localhost
gmysql-port=3306
gmysql-user=powerdns
gmysql-dbname=powerdns
gmysql-password=mypass
gmysql-socket=/tmp/mysql.sock
local-address=xxx.xxx.xxx.xxx
local-port=53
log-dns-details=/var/log/dns/pdns-details.log
log-failed-updates=/var/log/dns/pdns-fail.log
logfile=/var/log/dns/pdns.log
loglevel=9
query-logging=yes
#use-logfile=yes
#master=yes
max-queue-length=5000
max-tcp-connections=10
queue-limit=1500
recursive-cache-ttl=10
recursor=192.168.50.102 # Отправляем все что не нашли у себя в unbound
setgid=wheel
setuid=unbound
# slave=no
# slave-cycle-interval=60
soa-expire-default=604800
soa-minimum-ttl=3600
soa-refresh-default=10800
soa-retry-default=3600
socket-dir=/var/run
version-string=anonymous
webserver=yes # Иногда надо и статистику глянуть. Врубаем веб-сервер (естесно в секурной зоне)
webserver-address=192.168.0.102
webserver-password=<пароль к веб-серверу>
webserver-port=8081
webserver-print-arguments=yes
Заводимсо:

Код: Выделить всё

# service pdns onestart
Если все норм - резолвим, если нет - смотрим логи. У меня все завелось отлично, так что прорезольвив пару-тройку сайтеГов был очень удивлен скоростью работы. Решил я значит оставить эту связку на ПМЖ. Для этого необходимо внести кое-какие правки в /etc/rc.conf

Код: Выделить всё

nsd_enable="NO"
pdns_enable="YES"
lighttpd_enable="YES"
А зачем же lighttpd спросите вы? А как же фкусняшко о которой говорилось в самом начале этого поста - вебмордо? Ставим лайтеГ и пых!

Код: Выделить всё

# make -C /usr/ports/lang/php5 install clean && make -C /usr/ports/lang/php5-extensions install clean && make -C /usr/ports/www/lighttpd install clean
И приводим его конфиг к такому виду:

Код: Выделить всё

server.document-root = "/usr/local/wwwdata"                                               
server.port = 80                                                                            
server.username = "www"                                                                     
server.groupname = "www"                                                                    
server.tag ="lighttpd"                                                      
server.event-handler = "libev" # Если включена поддержка libev  при сборке                                                          
server.max-worker=1                                                                         
server.max-keep-alive-requests=250                                                          
server.max-keep-alive-idle=120                                                              
server.max-read-idle =120                                                                   
server.protocol-http11 ="enable"                                                            
server.errorlog = "/var/log/lighttpd/error.log"                                             
accesslog.filename = "/var/log/lighttpd/access.log"                                         

server.modules = (
        "mod_rewrite",
        "mod_alias",  
        "mod_access", 
        "mod_auth",   
        "mod_fastcgi",
        "mod_redirect",
        "mod_compress",
        "mod_accesslog"
)                      


mimetype.assign = (
         ".pdf" => "application/pdf",
         ".sig" => "application/pgp-signature",
         ".spl" => "application/futuresplash", 
         ".class" => "application/octet-stream",
         ".ps" => "application/postscript",     
         ".torrent" => "application/x-bittorrent",
         ".dvi" => "application/x-dvi",           
         ".gz" => "application/x-gzip",           
         ".pac" => "application/x-ns-proxy-autoconfig",
         ".swf" => "application/x-shockwave-flash",    
         ".tar.gz" => "application/x-tgz",             
         ".tgz" => "application/x-tgz",                
         ".tar" => "application/x-tar",                
         ".zip" => "application/zip",                  
         ".mp3" => "audio/mpeg",                       
         ".m3u" => "audio/x-mpegurl",                  
         ".wma" => "audio/x-ms-wma",                   
         ".wax" => "audio/x-ms-wax",                   
         ".ogg" => "audio/x-wav",                      
         ".wav" => "audio/x-wav",                      
         ".gif" => "image/gif",                        
         ".jpg" => "image/jpeg",                       
         ".jpeg" => "image/jpeg",                      
         ".png" => "image/png",                        
         ".xbm" => "image/x-xbitmap",                  
         ".xpm" => "image/x-xpixmap",                  
         ".xwd" => "image/x-xwindowdump",              
         ".css" => "text/css",                         
         ".html" => "text/html",                       
         ".htm" => "text/html",                        
         ".js" => "text/javascript",                   
         ".asc" => "text/plain",                       
         ".c" => "text/plain",                         
         ".conf" => "text/plain",                      
         ".text" => "text/plain",                      
         ".txt" => "text/plain",                       
         ".dtd" => "text/xml",                         
         ".xml" => "text/xml",                         
         ".mpeg" => "video/mpeg",                      
         ".mpg" => "video/mpeg",                       
         ".mov" => "video/quicktime",                  
         ".qt" => "video/quicktime",                   
         ".avi" => "video/x-msvideo",                  
         ".asf" => "video/x-ms-asf",                   
         ".asx" => "video/x-ms-asf",                   
         ".wmv" => "video/x-ms-wmv",                   
         ".bz2" => "application/x-bzip",               
         ".tbz" => "application/x-bzip-compressed-tar",
         ".tar.bz2" => "application/x-bzip-compressed-tar"
 )                                                        

index-file.names = ( "index.html", "index.php" )

$SERVER["socket"] == ":80" {
$HTTP["host"] =~ "(^|\.)ns\.example\.com$" {
        url.redirect = ( "^/(.*)" => "http://mega.kg" )
       $HTTP["url"] =~ "(.*)/poweradmin" { url.redirect = ( "^/(.*)" => "https://ns.example.com/" ) }
        server.name = "ns.example.com"
}
}

$SERVER["socket"] == ":443" {
protocol = "https://"
ssl.engine = "enable"
ssl.pemfile = "/etc/ssl/server.pem"
server.name = "ns.example.com"
compress.cache-dir = "/var/tmp"
server.document-root = "/usr/local/www/poweradmin"
server.kbytes-per-second = 10240
dir-listing.activate = "disable"
server.errorlog = "/var/log/lighttpd/ns.error.log"
accesslog.filename = "/var/log/lighttpd/ns.access.log"
server.error-handler-404 = "/e404.php"

fastcgi.server = ( ".php" =>
 ((
                       "socket" => "/tmp/fastcgi.sock",
                       "bin-path" => "/usr/local/bin/php-cgi",
                       "bin-environment" => (
                         "PHP_FCGI_CHILDREN" => "8",
                         "PHP_FCGI_MAX_REQUESTS" => "10000",
                       ),
                       "bin-copy-environment" => (
                         "PATH", "SHELL", "USER" ),
                       "max-procs" => 2,
                       "broken-scriptfilename" => "enable",
    )
  )
)

auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/usr/local/etc/lighttpd/htdigest"

auth.require = ( "" =>
        (
                "method" => "basic",
                "realm" => "Hello Evil Hacker!!!",
                "require" => "valid-user"
        )
)

}
С помощью утилитки htpasswd от apache создаем файлик /usr/local/etc/lighttpd/htdigest с паролями для доступа к морде.
Ставим poweradmin

Код: Выделить всё

# make -C /usr/ports/dns/poweradmin install clean
отмечаем ему в конфиге что юзаем муську, после установки правим его конфиг:

Код: Выделить всё

<?php
// See <https://www.poweradmin.org/trac/wiki/Documentation/ConfigurationFile> for help.

$db_host        = "localhost";
$db_user        = "powerdns";
$db_pass        = "mypass";
$db_name        = "powerdns";
$db_type        = "mysql";

$iface_lang        = "en_EN";
$iface_style        = "example";
$iface_rowamount    = "50";
$iface_expire        = "1800";
$iface_zonelist_serial    = "1";

$dns_hostmaster        = "admin.example.com";
$dns_ns1        = "ns.example.com";
$dns_ns2        = "ns2.example.com";
$dns_ttl        = "3600";
$dns_fancy        = "false";
$dns_strict_tld_check    = "1";

?>
Вуаля! Что мы получили в итоге? В итоге мы получили легкий DNS-сервер, отьедающий вдвое меньше ресурсов нежели bind, + имеющий зачотную морду для настройки. Сервер отработал 3 суток и что же мы видим в топе?

Код: Выделить всё

last pid: 11339;  load averages:  2.51,  2.16,  2.21                                                                                                                                         up 2+20:39:00  14:23:46
45 processes:  1 running, 44 sleeping
CPU 0: 12.9% user,  0.0% nice, 12.9% system, 20.0% interrupt, 54.1% idle
CPU 1: 22.4% user,  0.0% nice, 21.2% system,  5.5% interrupt, 51.0% idle
Mem: 298M Active, 569M Inact, 285M Wired, 568K Cache, 213M Buf, 821M Free
Swap: 5120M Total, 5120M Free

  PID USERNAME  THR PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
10451 unbound    11  21    0   148M 89132K usem    0 123:05 32.08% pdns_server
 1133 mysql      13  20    0   230M 35468K sbwait  0 777:24 26.76% mysqld
 8379 unbound     2  25    0   265M   235M kqread  1  90:00 14.55% unbound
 8294 root        1  22    0 12160K  1632K select  1  24:05  3.66% syslogd
 1181 www         1  20    0 56060K  6620K kqread  1   0:26  0.00% lighttpd
За это время bind обычно отжирал уже всю оперу и половину свопа. Что же касается сравнения с предыдущей связкой - честно говоря та связка потребляет гораздо меньше ресурсов но в отличии от нее в этой связке устранено одно неудобство - не нужно дважды прописывать зоны. Достаточно вбить зону в базу.

В общем я остановился на второй связке. Желаете сделать что-то подобное - вам выбирать в конце-концов)

Re: Не BIND'ом единым жив DNS

Добавлено: 19 мар 2012, 14:53
Gen1us2k
херасе букаф

Re: Не BIND'ом единым жив DNS

Добавлено: 19 мар 2012, 14:56
Raven
Gen1us2k
Эт у мну еще мозГа не варила красиво все это расписывать %)

Re: Не BIND'ом единым жив DNS

Добавлено: 26 мар 2012, 09:35
Vano
Raven Спасибо!
Пашет все как часы атомные. По сравнению с DNS от мокрого софта, прирост заметен глазу

Код: Выделить всё

Uptime: 3.01 days Queries/second, 1, 5, 10 minute averages: 0.199, 0.267, 0.29. Max queries/second: 21.7
Cache hitrate, 1, 5, 10 minute averages: 1.8%, 11.7%, 12.4%
Backend query cache hitrate, 1, 5, 10 minute averages: 53.0%, 56.5%, 58.2%
Backend query load, 1, 5, 10 minute averages: 0.34, 0.387, 0.408. Max queries/second: 8.04
Total queries: 395791. Question/answer latency: 0ms

Код: Выделить всё

last pid: 18925;  load averages:  0.06,  0.05,  0.01                                                                                                                                                                 up 3+00:18:37  09:51:40
57 processes:  1 running, 56 sleeping
CPU:  0.1% user,  0.0% nice,  0.0% system,  0.0% interrupt, 99.9% idle
Mem: 760M Active, 2233M Inact, 624M Wired, 468K Cache, 818M Buf, 4213M Free
Swap: 1600M Total, 1600M Free

Re: Не BIND'ом единым жив DNS

Добавлено: 10 фев 2014, 11:08
bammbr
Сообщение http://sysadmins.ws/viewtopic.php?f=52&t=1400#p9087
Листинг конфига lighttpd.conf
Строка

Код: Выделить всё

server.document-root = "/usr/local/wwwdata" 
Не опечатка ли это?
Сравниваю с "умолчальным" значением
server.document-root = "/usr/local/www/data"