Создаем кластер BIND9

По причине своей профессиональной лени, много лет подряд я активно использовал DNS Selectel для размещения своих доменов и доменов клиентов, и все было отлично. Но спустя много лет без проблем, он активно заглючил, чем рубил всю инфраструктуру на часы.

Уже изрядно достало видеть в http://status.selectel.info вот такие портянки.

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

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

Поскольку инфраструктура у меня не большая и запросов к DNS-кам немного, то для каждого сервера кластера я выделил по одной виртуалки 2vCPU, 1GB RAM, 5GB HDD.

Если с установкой проблем не возникает, обычно, поскольку любая адекватная ось умеет делать apt install bind9 laugh То вот с настройкой некоторые путаются, ща разжуем!

Master DNS – хранитель и великий управлятель всея зон diablo

# cat named.conf.options
acl "my_ip" {
    85.21.***.***/32;
    116.202.***.***/32;
    185.91.***.***/32;
    95.213.***.***/29;
    77.244.***.***/28;
    95.213.***.***/28;
    95.213.***.***/28;
    localhost;
    localnets;
};

statistics-channels {
 inet 127.0.0.1 port 8253 allow { 127.0.0.1; }; //расширенная статистика для снятия метрик Zabbix'ом
};

options {
 directory "/var/cache/bind";
 dnssec-validation auto;

 allow-query { any; }; // любой может сделать запрос к локально размещенным зонам
 allow-transfer { 116.202.***.***; 95.213.***.***; }; // разрешено трансферить зоны на слейвы
 allow-update { none; }; // запрещено получать апдейт зон от кого угодно, ибо только мастер рулит зонами
 recursion yes; // В целом, рекурсия нам нужна
 allow-recursion { my_ip; };// Но разрешена рекурсия только со своих подсетей
 allow-query-cache { my_ip; };
 max-cache-size 10M; // Ограничить кеш 10МБ памяти
 max-cache-ttl 4000; // хранить записи в кеше максимум 4 тыс. секунд

 rate-limit { // Защищаем от DoS
  window 5; // Окно вычисления
  responses-per-second 40; // Лимит ответов на /24-ю подсеть
  errors-per-second 5; // рубить после 5 ошибок, ибо нефиг спрашивать всякую чепуху
  nxdomains-per-second 5; // не слишком много давать возможностей запрашивать nxdomains
  slip 2; // Уровень магии обрезания UDP
  exempt-clients { my_ip; }; // Не накладываем ограничения на свои сети 
  ipv4-prefix-length 24; // Сюрприз! лимитить подсетями /24 эффективнее
 };
 notify yes; // Высылать нотифи при изменении зоны
 listen-on-v6 { none; }; // Нафаршировать IPv6 по вкусу :)
 version "My cloud DNS"; // На версию бинда навешиваем завесу тайны
};

На двух рабов мастера ой… чо-то меня понесло в терминологию BDSM На два Slave DNS размещаем следующий конфиг:

# cat named.conf.options
acl "my_ip" {
    85.21.***.***/32;
    116.202.***.***/32;
    185.91.***.***/32;
    95.213.***.***/29;
    77.244.***.***/28;
    95.213.***.***/28;
    95.213.***.***/28;
    localhost;
    localnets;
};

statistics-channels {
 inet 127.0.0.1 port 8253 allow { 127.0.0.1; }; //расширенная статистика для снятия метрик Zabbix'ом
};

options {
 directory "/var/cache/bind";
 dnssec-validation auto;

 allow-query { any; }; // любой может сделать запрос к локально размещенным зонам
 allow-transfer { none; }; // Слейвы ничего никуда не трансферят, они рабы!
 allow-update { 77.244.***.***; }; // Разрешено получать апдейт с мастера
 recursion yes; // В целом, рекурсия нам нужна
 allow-recursion { my_ip; };// Но разрешена рекурсия только со своих подсетей
 allow-query-cache { my_ip; };
 max-cache-size 10M; // Ограничить кеш 10МБ памяти
 max-cache-ttl 4000; // хранить записи в кеше максимум 4 тыс. секунд

 rate-limit { // Защищаем от DoS
  window 5; // Окно вычисления
  responses-per-second 40; // Лимит ответов на /24-ю подсеть
  errors-per-second 5;  // рубить после 5 ошибок, ибо нефиг спрашивать всякую чепуху
  nxdomains-per-second 5; // не слишком много давать возможностей запрашивать nxdomains
  slip 2; // Уровень магии обрезания UDP 
  exempt-clients { my_ip; }; // Не накладываем ограничения на свои сети
  ipv4-prefix-length 24; // Сюрприз! лимитить подсетями /24 эффективнее
 };
 notify no; // Не высылать нотифи при изменении зоны, мы не мастер
 listen-on-v6 { none; }; // Нафаршировать IPv6 по вкусу :)
 version "My cloud DNS"; // На версию бинда навешиваем завесу тайны

};

Обязательно надо на картинке показать что дает RRL(Response Rate Limiting) которому посвящена большая часть конфига. laugh

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

В целом это все, настройка закончена, далее начинается проработка нюансов. Я не буду вдаваться в форматы файлов зон и их написание, благо в сети очень много информации на эту тему, т.к. бинд9 – default dns blush А вот вопросы реплики зон каждый прорабатывает по своему, встречаются и отчаенные кто пихает зоны в мускул, костылит бинд на поддержку мускула и раскидывает реплики… оно прикольно, безусловно, но! в принципе не надо еще одну потенциальную точку отказа!

Я реализовал так:

На мастере был размещен скрипт:

# cat refresh_zones.sh
#!/bin/sh

echo >named.conf.zones
echo >named.conf.zones.transfer_to_slaves

ls master_zones | while read line ; do

echo "zone \""$line"\" { type master; file \"/etc/bind/master_zones/"$line"\"; };" >>named.conf.zones
echo "zone \""$line"\" { type slave; masters { 77.244.***.***; }; allow-notify { 77.244.***.***; }; file \"/etc/bind/slave_zones/"$line"\"; };" >>named.conf.zones.transfer_to_slaves

done

ls master_zones | while read line ; do

named-checkconf /etc/bind/named.conf
if [ $? -ne 0 ] ; then echo "Something wrong!" ; exit 1; fi

named-compilezone -o /etc/bind/master_zones/$line $line /etc/bind/master_zones/$line
if [ $? -ne 0 ] ; then echo "Something wrong!" ; exit 1; fi

named-checkzone $line /etc/bind/master_zones/$line
if [ $? -ne 0 ] ; then echo "Something wrong!" ; exit 1; fi

done
if [ $? -ne 0 ] ; then exit 1; fi

scp named.conf.zones.transfer_to_slaves ns2.****.cloud:/etc/bind/named.conf.zones
scp named.conf.zones.transfer_to_slaves ns3.****.cloud:/etc/bind/named.conf.zones

rndc reload
ssh ns2.****.cloud rndc reload
ssh ns3.****.cloud rndc reload

Его суть проста как 2 копейки!

  • Сканируем папку зон master_zones
  • При нахождении файлов зон принимаем имя файла за имя зоны.
  • Проверяем файлы зон на ошибки и приводим их формат к установленному по дефолту.
  • Генерируем конфиг мастера и конфиг слейва.
  • Загружаем на слейвы конфиги.
  • Перезагружаем конфигурации.

Не забываем конечно-же заинклюдить в конфигах наш автогенерируемый конфиг файл:

include "/etc/bind/named.conf.zones";
А поскольку мы с вами уже взрослые дяди и ходим на сервера по ключам, то никаких проблем с работой со слейвами у данного скрипта нет, он туда заходит в гости и делает все что ему надо.

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

Для мониторинга загрузки DNS-ок можно взять к примеру этот заббикс-шаблон https://github.com/vv-sm/Zabbix-Bind9-Statistics-Collection

Собственно вот и все! Просто и со вкусом автоматизации! drinks

Добавить комментарий