DNS сервер Bind на Ubuntu 24.04.1 LTS

DNS сервер Bind на Ubuntu 24.04.1 LTS
Photo by Stefan Cosma / Unsplash

Предисловие

Это вторая из цикла заметок по настройке домашнего сетевого шлюза на базе Ubuntu 24.04.1.

Предыдущий материал:

Сетевой шлюз на базе Ubuntu 24.04 (Gateway)
Предисловие После очередного успешного теста на хоть и домашнем, но PRODe Ubuntu 20.04 - он лег далеко и надолго. Бэкапа и точек отката не было, вручную сняв с сервера все данные с жестких дисков и все данные баз данных было решено собрать на том же железе обновленный сервер на

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

sudo apt install bind9 bind9utils bind9-doc bind9-host dnsutils

Настраиваем

Создаем acl-лист (список доступа), в котором прописываем имена сетей и их диапазоны.

sudo nano /etc/bind/named.conf.acl 

Добавляем сети, на текущий момент добавляю одну - локальной сети:

acl acl_local {
        192.168.1.0/24;
};

Редактируем файл /etc/bind/named.conf, добавляем строку подключения списков доступа, содержание получается примерно следующим:

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.acl";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";

Редактируем файл /etc/bind/named.conf.options до следующего вида:

options {
        directory "/var/cache/bind";

        // If there is a firewall between you and nameservers you want
        // to talk to, you may need to fix the firewall to allow multiple
        // ports to talk.  See http://www.kb.cert.org/vuls/id/800113

        // If your ISP provided one or more IP addresses for stable
        // nameservers, you probably want to use them as forwarders.
        // Uncomment the following block, and insert the addresses replacing
        // the all-0's placeholder.

        forwarders {
                77.88.8.8;      // Yandex
                77.88.8.1;      // Yandex
                8.8.8.8;        // Google
                8.8.4.4;        // Google
                1.1.1.1;        // Cloudflare
                1.0.0.1;        // Cloudflare
        };

        listen-on port 53 { 127.0.0.1; 192.168.1.1; };

        dnssec-validation auto;

        listen-on-v6 { none; };

        // Отключение проверки валидности имен и возможность использовать кирилицу
        check-names master ignore;

        // hide version number from clients for security reasons.
        version "not currently available";

        // optional - BIND default behavior is recursion
        recursion yes;

        // network range you allow to recieve queries from hosts
        allow-query { localhost; acl_local; };

        // provide recursion service to trusted clients only
        allow-recursion { localhost; acl_local; };

        allow-query-cache { localhost; acl_local; };

        allow-transfer { none; };

        // enable the query log
        querylog yes;
};

Это базовая настройка, её должно быть достаточно для работы Bind9 на системе и клиентов локальной сети по адресам 192.168.1.0/24. После сохранения выполняем проверку конфигурации командой sudo named-checkconf.

Управление локальной доменной зоной

Опционально. Настройки для управления своей локальной доменной зоной. Редактируем файл /etc/bind/named.conf.local, добавляем зоны для прямого и обратного просмотра:

zone "savenkoff.local" IN {
        type master;
        file "/var/lib/bind/db.savenkoff.local";
        // allow-update { none; };
};

zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "/var/lib/bind/db.1.168.192";
        // allow-update { none; };
};

Для зоны прямого просмотра создаем файл /var/lib/bind/db.savenkoff.local со следующим содержимым:

;
$ORIGIN savenkoff.local.
$TTL    604800
@       IN      SOA     ns.savenkoff.local. nobody.savenkoff.com. (
                              2         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns.
@       IN      A       192.186.1.1
home    IN      A       192.168.1.1
ns      IN      A       192.168.1.1

Для зоны обратного просмотра создаём файл /var/lib/bind/db.1.168.192 со следующим содержимым:

;
$ORIGIN 1.168.192.IN-ADDR.ARPA.
$TTL    604800
@       IN      SOA     ns.savenkoff.local. nobody.savenkoff.com. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns.savenkoff.local.
1       IN      PTR     ns.savenkoff.local.

Переопределение ответов сервера и использование RPZ

Возможность творить чудеса с ответами сервера на разного рода запросы.

Для начала редактируем файл /etc/bind/named.conf.options, в секцию options добавляем директиву для включения RPZ (зона может называться как угодно, мое именование обосновано тем, что там будут переопределения для домена блога):

response-policy { zone "rpz.savenkoff.com"; };

Редактируем файл /etc/bind/named.conf.local, вносим в него данные зоны:

zone "rpz.savenkoff.com" IN {
        type master;
        file "/var/lib/bind/db.rpz.savenkoff.com";
        allow-update { none; };
};

Создаём файл зоны /var/lib/bind/db.rpz.savenkoff.com со следующим содержимым:

;RPZ
$TTL    60
@       IN      SOA     ns.savenkoff.local. nobody.savenkoff.com. (
                              1         ; Serial
                           3600         ; Refresh
                            300         ; Retry
                          86400         ; Expire
                             60 )       ; Negative Cache TTL
;
@       IN      NS      ns.savenkoff.local.
; Modified
savenkoff.com           A       192.168.1.1
www.savenkoff.com       A       192.168.1.1

Записи SOA и NS не используются, существуют для совместимости. 2 записи ниже переопределяют IP адрес доменных имен savenkoff.com и www.savenkoff.com для запросов к серверу.

Проверяем конфигурацию сервера командой sudo named-checkconf. Если ошибок нет - перезапускаем и проверяем работу. Проверяем запросом к серверу:

В ответ получаем именно то, что планировали.

Настройка логирования

Как оказалось, искать информацию в общем файле лога /var/log/syslog приятного мало, поэтому выносим логи в отдельный файл. Создаем директорию хранения логов и выдаём на неё права:

sudo mkdir /var/log/named
sudo chown -R bind:bind /var/log/named/

Создаём файл /etc/bind/named.conf.logging, добавляем туда блок с настройками логирования (базовая конфигурация взята из статьи BIND Logging - some basic recommendations и отредактирована под себя):

logging {
     channel default_log {
          file "/var/log/named/default.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
     channel auth_servers_log {
          file "/var/log/named/auth_servers.log" versions 100 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
     channel dnssec_log {
          file "/var/log/named/dnssec.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
     channel zone_transfers_log {
          file "/var/log/named/zone_transfers.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
     channel ddns_log {
          file "/var/log/named/ddns.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
     channel client_security_log {
          file "/var/log/named/client_security.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
     channel rate_limiting_log {
          file "/var/log/named/rate_limiting.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
     channel rpz_log {
          file "/var/log/named/rpz.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
     channel dnstap_log {
          file "/var/log/named/dnstap.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
//
// If you have the category ‘queries’ defined, and you don’t want query logging
// by default, make sure you add option ‘querylog no;’ - then you can toggle
// query logging on (and off again) using command ‘rndc querylog’
//
     channel queries_log {
          file "/var/log/named/queries.log" versions 600 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };
//
// This channel is dynamic so that when the debug level is increased using
// rndc while the server is running, extra information will be logged about
// failing queries.  Other debug information for other categories will be
// sent to the channel default_debug (which is also dynamic), but without
// affecting the regular logging.
//
     channel query-errors_log {
          file "/var/log/named/query-errors.log" versions 5 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
     };
//
// This is the default syslog channel, defined here for clarity.  You don’t
// have to use it if you prefer to log to your own channels.
// It sends to syslog’s daemon facility, and sends only logged messages
// of priority info and higher.
// (The options to print time, category and severity are non-default.)
//
     channel default_syslog {
          print-time yes;
          print-category yes;
          print-severity yes;
          syslog daemon;
          severity info;
     };
//
// This is the default debug output channel, defined here for clarity.  You
// might want to redefine the output destination if it doesn’t fit with your
// local system administration plans for logging.  It is also a special
// channel that only produces output if the debug level is non-zero.
//
     channel default_debug {
          print-time yes;
          print-category yes;
          print-severity yes;
          file "/var/log/named/named.run";
          severity dynamic;
     };
//
// Log routine stuff to syslog and default log:
//
     category default { default_syslog; default_debug; default_log; };
     category config { default_syslog; default_debug; default_log; };
     category dispatch { default_syslog; default_debug; default_log; };
     category network { default_syslog; default_debug; default_log; };
     category general { default_syslog; default_debug; default_log; };
//
// From BIND 9.12 and newer, you can direct zone load logging to another
// channel with the new zoneload logging category.  If this would be useful
// then firstly, configure the new channel, and then edit the line below
// to direct the category there instead of to syslog and default log:
//
     category zoneload { default_syslog; default_debug; default_log; };
//
// Log messages relating to what we got back from authoritative servers during
// recursion (if lame-servers and edns-disabled are obscuring other messages
// they can be sent to their own channel or to null).  Sometimes these log
// messages will be useful to research why some domains don’t resolve or
// don’t resolve reliably
//
     category resolver { auth_servers_log; default_debug; };
     category cname { auth_servers_log; default_debug; };
     category delegation-only { auth_servers_log; default_debug; };
     category lame-servers { auth_servers_log; default_debug; };
     category edns-disabled { auth_servers_log; default_debug; };
//
// Log problems with DNSSEC:
//
     category dnssec { dnssec_log; default_debug; };
//
// Log together all messages relating to authoritative zone propagation
//
     category notify { zone_transfers_log; default_debug; };
     category xfer-in { zone_transfers_log; default_debug; };
     category xfer-out { zone_transfers_log; default_debug; };
//
// Log together all messages relating to dynamic updates to DNS zone data:
//
     category update{ ddns_log; default_debug; };
     category update-security { ddns_log; default_debug; };
//
// Log together all messages relating to client access and security.
// (There is an additional category ‘unmatched’ that is by default sent to
// null but which can be added here if you want more than the one-line
// summary that is logged for failures to match a view).
//
     category client{ client_security_log; default_debug; };
     category security { client_security_log; default_debug; };
//
// Log together all messages that are likely to be related to rate-limiting.
// This includes RRL (Response Rate Limiting) - usually deployed on authoritative
// servers and fetches-per-server|zone.  Note that it does not include
// logging of changes for clients-per-query (which are logged in category
// resolver).  Also note that there may on occasions be other log messages
// emitted by the database category that don’t relate to rate-limiting
// behaviour by named.
//
     category rate-limit { rate_limiting_log; default_debug; };
     category spill { rate_limiting_log; default_debug; };
     category database { rate_limiting_log; default_debug; };
//
// Log DNS-RPZ (Response Policy Zone) messages (if you are not using DNS-RPZ
// then you may want to comment out this category and associated channel)
//
     category rpz { rpz_log; default_debug; };
//
// Log messages relating to the "dnstap" DNS traffic capture system  (if you
// are not using dnstap, then you may want to comment out this category and
// associated channel).
//
     category dnstap { dnstap_log; default_debug; };
//
// If you are running a server (for example one of the Internet root
// nameservers) that is providing RFC 5011 trust anchor updates, then you
// may be interested in logging trust anchor telemetry reports that your
// server receives to analyze anchor propagation rates during a key rollover.
// If this would be useful then firstly, configure the new channel, and then
// un-comment and the line below to direct the category there instead of to
// syslog and default log:
//
//
     category trust-anchor-telemetry { default_syslog; default_debug; default_log; };
//
// If you have the category ‘queries’ defined, and you don’t want query logging
// by default, make sure you add option ‘querylog no;’ - then you can toggle
// query logging on (and off again) using command ‘rndc querylog’
//
     category queries { queries_log; };
//
// This logging category will only emit messages at debug levels of 1 or
// higher - it can be useful to troubleshoot problems where queries are
// resulting in a SERVFAIL response.
//
     category query-errors {query-errors_log; };
};

Редактируем файл /etc/bind/named.conf, добавляем строку подключения настроек логирования, с учетом выше сделанных манипуляций должно получиться следующее:

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.acl";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
include "/etc/bind/named.conf.logging";

Перезапускаем командой sudo systemctl restart bind9. Проверяем состояние командой sudo systemctl status bind9.

Ротация логов

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

Создаем файл настроек ротации логов:

sudo nano /etc/logrotate.d/bind9

со следующим содержимым:

/var/log/named/*.log {
  compress
  create 0644 bind bind
  daily
  dateext
  missingok
  notifempty
  rotate 30
  sharedscripts
  postrotate
    /usr/sbin/rndc reconfig > /dev/null 2>/dev/null || true
  endscript
}

Коротко, что будет: compress - сжимаем, create 0644 bind bind - создаем новый файл лога после перемещения старого с указанными правами, daily - обрабатываем файлы ежедневно, dateext - перед заголовком старого лога добавляется дата ротации, missingok - не выдаем ошибки об отсутствии файла лога, notifempty - не ротируем пустой файл, rotate 30 - храним 30 файлов лога, sharedscripts - команда postrotate/endscript выполняется 1 раз после обработки всех файлов, postrotate/endscript - выполнить скрипт после ротации.

Проверяем конфигурацию после создания командой:

sudo logrotate -d /etc/logrotate.d/bind9

Смотрим лог на наличие ошибок, их быть не должно. Вывод в консоль следующий:

Handling 1 logs

rotating pattern: /var/log/named/*.log  after 1 days (30 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/named/named.log
Creating new state
  Now: 2024-11-12 22:10
  Last rotated at 2024-11-12 22:00
  log does not need rotating (log has already been rotated)
considering log /var/log/named/security-info.log
Creating new state
  Now: 2024-11-12 22:10
  Last rotated at 2024-11-12 22:00
  log does not need rotating (log has already been rotated)
considering log /var/log/named/update-debug.log
Creating new state
  Now: 2024-11-12 22:10
  Last rotated at 2024-11-12 22:00
  log does not need rotating (log has already been rotated)
not running postrotate script, since no logs were rotated

Запускаем, проверяем

Разрешаем доступ к 53 порту из локальной сети добавив правило ufw: sudo ufw allow in from 192.168.1.0/24 to any port 53. Проверяем конфигурацию на корректность sudo named-checkconf, запускаем сервис sudo systemctl start bind9, проверяем статус работы sudo systemctl status bind9, статус должен быть running:

● named.service - BIND Domain Name Server
     Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled)
     Active: active (running) since Tue 2024-10-22 23:00:10 +07; 13h ago
       Docs: man:named(8)
   Main PID: 10828 (named)
     Status: "running"
      Tasks: 14 (limit: 9346)
     Memory: 9.7M (peak: 10.8M)
        CPU: 23.455s
     CGroup: /system.slice/named.service
             └─10828 /usr/sbin/named -f -u bind

Проверять сразу предлагаю с клиента, для примера можно на Windows запустить Windows PowerShell, и выполнить пару комманд nslookup для проверки имен в локальной зоне и имен в сети интернет. На все запросы должен быть получен ответ от локально настроенного сервера ns.savenkoff.local: