Установка и настройка Bind DNS.

Сегодня погорим о DNS, сейчас, конечно, более актуальным является PowesDNS, хотя бы за счет того, что он имеет API и к нему есть не мало хороших веб интерфейсов, что делает его куда более привлекательным в сравнении с Bind, но и у PowerDNS есть свои недостатки. Сегодня мы поговорим именно о Bind DNS. И поговорим о том, как правильно его готовить. Рассматривать будем на примере контейнера docker. Я буду разварачивать его на Alpine Linux, т.к. его размер более привлекательный чем та же Ubuntu, но конфигурационные файлы подойдут под любую систему, разница лишь в относительных путях. Я набросал вот такой Dockerfile:

FROM alpine

WORKDIR /etc/bind
COPY named.conf /etc/bind/named.conf

RUN apk --update add bind bind-tools bind-dnssec-tools && \
    rm -rf /var/lib/apt/lists/* && \
    rm /var/cache/apk/*

EXPOSE 53
CMD ["/usr/sbin/named", "-c", "/etc/bind/named.conf", "-p", "53", "-u", "named", "-f"]

Здесь надо уделить внимание только на строку копирования файла конфигурации named.conf, в остальном я думаю не должно возникнуть вопросов, устанавливаем сам сервер, далее запускаем его и открываем 53 порт. Важно что для корректной работы необходимо открывать как TCP так и UDP порт. Теперь можно переходить непосредственно к самому файлу named.conf:

options {
  directory "/var/bind";
	listen-on { 127.0.0.1; };
	listen-on-v6 { none; };

  forwarders {
      77.88.8.8; 8.8.8.8;
  };

  recursion yes;
  allow-recursion {
    any;
  };

  version "DNS";
  notify no;

  rate-limit {
    responses-per-second 25;
    window 5;
  };

  allow-query {
    any;
  };

	allow-transfer {
		none;
	};

	pid-file "/var/run/named/named.pid";
};

logging {

  channel bind_stdout {
  stderr;
  severity info;
  print-category yes;
  print-severity yes;
  print-time yes;
  };

  category default { bind_stdout; };
  category update { bind_stdout; };
  category update-security { bind_stdout; };
  category security { bind_stdout; };
  category queries { bind_stdout; };
};

zone "." {
	type hint;
	file "/usr/share/dns-root-hints/named.root";
};

include "/etc/bind/zone/main.conf";
Немного о директивах в этом файле,  listen-on { 127.0.0.1; }; говорит о том какой адрес необходимо слушать серверу. В боевых условиях, где сервер будет обслуживать реальные зоны вы должны указать внешний адрес, либо установить значение в any.  forwarders { 77.88.8.8; 8.8.8.8; };  если адрес к которому мы обращаемся не находиться в пределах обслуживаемых нами зон, то отдавать запросы следующим серверам, я указал dns сервера яндекса и гугла. Остается на ваше усмотрение, может быть вы добавите туда сервера AD. 
recursion yes;
allow-recursion {
    any;
  };

Разрешаем рекурсивные запросы, как раз то, о чем шла речь выше, то есть все клиенты которые будут обращаться к вашему серверу, если зона находиться за пределами будут перенаправлены. Здесь можно и в каких-то случаях нужно, перечислить сети и адреса которым рекурсия разрешена.
allow-query {
    any;
  };

allow-transfer {
    none;
  };

Мы разрешаем опрашивать наш сервер всем, в противном случае, ограничьте возможность делать запросы только вашими сетями. То же самое касается трансфера зон от мастера к слейву, но в нашем примере у нас только один сервер. По этому это значение none. 

Все остальные директивы не столь значимы, можно интуитивно понять для чего они, а так же почитать официальную документацию. https://kb.isc.org/docs/aa-00851

Все готово, теперь нам необходимо создать наши зоны, об этом говорит последняя строка конфигурационного файла include «/etc/bind/zone/main.conf»;

zone "yakunin.local" {
    type master;
    file "/etc/bind/zone/yakunin.local.conf";
    allow-query     { any; };
};

zone "0.0.127.in-addr.arpa" {
    type master;
    file "/etc/bind/zone/0.0.127.in-addr.arpa.conf";
    allow-query     { any; };
};

Здесь мы как раз указываем зоны которые будем обслуживать, в качестве примера, я сделал домен yakunin.local, обратите внимание что ниже есть обратная зона, это зона адресов которые вы будете использовать что бы создавать PTR записи. По этому для домена мы заводим 2 зоны, прямую и обратную. Рассмотрим сначала прямую:

$TTL  3600
@ IN  SOA ns1.yakunin.local. postmaster.yakunin.local. (
  2021111502  ; Serial
  3600        ; Refresh
  900         ; Retry
  2419200     ; Expire
  3600 )      ; Negative Cache TTL

  IN  NS  ns1.yakunin.local.

@ MX  10  mail.yakunin.local.
@ IN  TXT "v=spf1 +a +mx ~all"

@     IN  A 127.0.0.1
www   IN  A 127.0.0.1
ns1   IN  A 127.0.0.1
mail  IN  A 127.0.0.1

Объясню немного, первая строка задает время жизни записей о зоне для других DNS серверов, другими словами, если вы выключите свой сервер, данные о вашей зоне будет доступно в интернете или на других локальных днс серверах ещё 3600 минут. Далее мы задаем параметры зоны, у нас один сервер, он же главный, по этому ns1.yakunin.local, bind не позволяет передавать символ @ так как он является якорем для домена, то есть указывая @ мы говорим это это и есть тот самый домен который описан. А строка postmaster.yakunin.local. это лишь интерпритация емайл адреса администратора домена, то есть, это эквивалентно postmaster@yakunin.local

Далее идет серийный номер записи, это один из важных моментов, по правилам саомго bind, этот параметр должен быть равен ггггммдднн (год,месяц,день,номер_изменения записи) последнюю пару цифр вы должны менять всегда, когда вносите изменения в файл зоны (добавляете или удаляете запись и т.д.) каждое изменение это увеличение счетчика на один. Таким образом остальные сервера будут понимать что у вас произошло изменение и его необходимо «забрать».

Далее задаем NS (Name Server), в данном случае у нас только один сервер, по этому мы объявляем только одну запись со значением ns1.yakunin.local, если у нас несколько серверов мы должны перечислить и указать их все, каждый с новой строки. Далее мы объявляем какой почтовый сервер будет обслуживать наш домен и его приоритет. Так же добавим SPF запись для почтового домена. И в конце файла мы указываем записи для каждого поддомена. Первой строкой @ IN A 127.0.0.1 мы говорим что основной адрес нашего домена это 127.0.0.1, теперь все что будет пиговаться с маской, будет отдавать 127.0.0.1 ping *.yakunin.local, где * это любое значение, даже то, которое не описано в файле зон. Следующие записи указывают явно присвоение адреса к поддомену, то есть, у каждой записи может быть разный IP, которому сопоставлена запись. Наверное все это не сильно понятно, но если вы обратитесь к документации, то все будет более понятно. Теперь рассмотрим файл обратной зоны:

$TTL  3600
@ IN  SOA   ns1.yakunin.local. postmaster.yakunin.local.  (
  2021111505  ; Serial
  3600        ; Refresh
  900         ; Retry
  2419200     ; Expire
  3600 )      ; Negative Cache TTL

      IN  NS  ns1.yakunin.local.
1     IN  PTR  yakunin.local.

Как ведите шапка файла сталось неизменной,что же тогда такое обратная зона? Когда мы делаем ping yakunin.local в ответ мы получаем IP адрес, то же самое и наоборот, то есть мы сделаем ping 127.0.0.1 то в после хост будет yakunin.local. Для чего это нужно? В первую очередь для построения почтовых серверов, если адрес не имеет обратной записи, то доверия к такому серверу будет куда меньше, а в некоторых случаях домены не имеющие обратной записи, вообще попадают сразу в спам. Какой принцип построения? В данном примере обслуживается 127.0.0.0/24, и из этой сети мы берем первый адрес 127.0.0.1 в обратном порядке это будет 1.0.0.127 и именно так, а не 1.0.0.721, то есть октет должен остаться таким же, но в зеркалом порядке. Строка: 1 IN PTR yakunin.local. горит что из сети 127.0.0.0/24, адрес 127.0.0.1 присвоен домену yakunin.local. А если бы надо было добавить ещё какой-то? Например адрес 127.0.0.2 домену ftp.yakunin.dev то строка была бы такой: 2 IN PTR ftp.yakunin.local. Надеюсь вы поняли смысл, так же при изменении этого файла вам необходимо увеличивать последние 2 числа серийного номера. Как и в случае с прямой зоной. Теперь когда у нас есть все файлы, мы можем сделать docker-compose.yaml:

version: "3.2"
services:
  bind:
    image: bind:alpine
    container_name: bind
    hostname: bind-dns
    build: ./src
    restart: always
    volumes:
      - ./zone:/etc/bind/zone
    cap_add:
      - NET_ADMIN
      - SYS_ADMIN
    ulimits:
      memlock:
        soft: -1
        hard: -1
    logging:
      driver: "json-file"
      options:
        max-size: "1m"
        max-file: 2
    network_mode: host

После чего структура у вас должна получиться такой:

.
├── docker-compose.yaml
├── src
│   ├── Dockerfile
│   └── named.conf
└── zone
    ├── 0.0.127.in-addr.arpa.conf
    ├── main.conf
    └── yakunin.local.conf

2 directories, 6 files

Можно запускать стек:

> docker compose up --build --detach

Обратите внимание что контейнер запускается в режиме сети — хост, то есть что бы сервер заработал убедитесь что никакие другие службы не занимают 53 порт на адресе 127.0.0.1 иначе вы получите ошибку. Например начиная с Ubuntu 20.04 в её составе работает unbound. По этому их необходимо отключить:

> sudo systemctl disable systemd-resolved.service 
> sudo systemctl stop systemd-resolved.service 
> sudo unlink /etc/resolv.conf
> sudo systemctl disable unbound.service 
> sudo systemctl disable unbound-resolvconf.service
> sudo systemctl stop unbound.service 
> sudo systemctl stop unbound-resolvconf.service
> sudo echo "nameserver 127.0.0.1" > /etc/resolv.conf

Теперь мы можем запускать наш стек и пробовать проверить работу сервера:

> sudo docker logs bind

25-Aug-2022 13:12:10.940 zoneload: info: zone 0.0.127.in-addr.arpa/IN: loaded serial 2021111505
25-Aug-2022 13:12:10.940 zoneload: info: zone yakunin.local/IN: loaded serial 2021111502
25-Aug-2022 13:12:10.944 general: notice: all zones loaded
25-Aug-2022 13:12:10.944 general: notice: running
25-Aug-2022 13:12:10.972 dnssec: info: managed-keys-zone: Key 20326 for zone . is now trusted (acceptance timer complete)
25-Aug-2022 13:12:11.060 resolver: info: resolver priming query complete
> ping yakunin.local
PING yakunin.local (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.103 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.078 ms
^C
--- yakunin.local ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2048ms
rtt min/avg/max/mdev = 0.027/0.069/0.103/0.031 ms

> nslookup yakunin.local
Server:		127.0.0.1
Address:	127.0.0.1#53

Name:	yakunin.local
Address: 127.0.0.1

> nslookup 127.0.0.1
1.0.0.127.in-addr.arpa	name = yakunin.local.

Как видим все работает. Попробуйте заменить домен на какой-то свой и добавить другие записи в зону. Для удобства я выложил все это в гит, можно склонировать репозиторий к себе и попробовать запустить. Кстати в примерах выше я использую docker compose plugin который теперь входит в ядро докера и его не надо устанавливать отдельным бинарным файлом как это было раньше. Почитайте об этом на официальном сайте докер. Ссылка на резпозиторий: https://git.yakunin.dev/yakunin/docker/-/tree/main/bind-alpine

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *