Настройка dns-сервера bind9 на ubuntu 20.04 lts

Быстрая установка, или еще раз об одном и том же

Итак, как установить BIND 9 в Debian/Ubuntu, в Сети очень и очень много материала. Так что быстро пройдемся по этому пункту, не вдаваясь в подробности. Для начала необходимо установить BIND 9 в систему. Для пользователей MS Windows есть версия BIND 9 под их платформу.

apt-cache search bind9

INFO

Подробно о версии для Windows 2008 можно почитать тут: «Установка BIND 9 в Windows Server 2008».

Для других дистрибутивов руководств по сборке из исходных кодов на просторах Сети предостаточно, забирай быстрее, переписывай в блокноты, пока новый «суперполезный» закон не накрыл весь интернет или пока тебя не отругали за то, что ты ходишь или ходил на сайт с запрещенной литературой.

После установки переходим в каталог и видим там основной файл конфигурации , внутри подключены остальные файлы . Как настраивать мастер-зону, опустим, поскольку в Сети информация изложена очень подробно. Добавим в файл named.conf строку

чем подключим новый файл в конфиг для правил подсетей. Далее создаем файл и добавляем правила:

Здесь мы разделили сети на группы для дальнейшей обработки. Прежде чем продолжим, уточню один момент. Для корректной обработки зон необходимо в каждую группу правил добавлять все зоны. Можно это делать в одном файле или вынести настройки зоны в отдельный файл и потом просто подключать в нужных местах. Итак, в файл вносим изменения:

Здесь мы обозначаем группу, с которой будет работать BIND. Добавляем сюда клиенты из правил, которые мы определили выше. Назначаем вышестоящий сервер, на который будут пересылаться запросы, пришедшие из сетей, согласно описанным правилам. Здесь это единственная группа адресов School. В качестве вышестоящего DNS задал DNS-сервер Яндекс, который фильтрует «плохой» контент. Можно аналогично использовать другие DNS-сервисы, такие как SkyDNS.

Далее в этот же файл ниже добавляем вторую или остальные группы клиентов. Зона zone2.ru подключена как slave-зона, указан DNS-мастер-сервер и файл — путь к базе.

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score!
Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя!
Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.

Я уже участник «Xakep.ru»

Вариант простейшей настройки «Кеширующий сервер DNS»

Если у вас уже есть настроенный и доступный DNS-сервер (собственный, или сервер провайдера), создание в локальной сети кеширующего DNS-сервера позволит без особых затрат ускорить работу с Интернет за счет ускорения разрешения имен по запросам различных сетевых служб и/или пользовательскими программами.

Для примера предположим, что у нас есть:

сервер DNS с  адресом 192.168.32.211

Для создания кеширующего dns-сервера

раскомментируем в файле конфигурации /etc/bind/named.conf.options строки

//  forwarders {
//      0.0.0.0;
//  };
  • указываем адреса используемых DNS-серверов, которым нужно передавать запросы (для примера взяты адреса DNS-серверов Google)
  • и, в этом примере, отключаем авторизацию dnssec (использование dnssec будет рассмотрено позже)
forwarders {
	8.8.8.8;
	8.8.4.4;
};
dnssec-validation False;

Можно , но не обязательно, ещё добавить список интерфейсов компьютера, через сервис DNS должен принимать запросы:

listen-on {
	127.0.0.1;
	192.168.1.1;
};
  • сохраняем файл конфигурации
  • проверяем правильность конфигурации командой (если команда не выдаёт никаких сообщений — значит ошибок нет)

sudo named-checkconf

и перезапускаем сервис

sudo systemctl restart bind9

Посылаем первый запрос:

dig @localhost www.astralinux.ru | grep msec
dig @localhost www.astralinux.ru | grep msec

Directives

Directives are special attributes with the prefix. Directive attribute values are expected to be binding expressions, so the rules about JavaScript expressions and filters mentioned above apply here as well. A directive’s job is to reactively apply special behavior to the DOM when the value of its expression changes. Let’s review the example we saw in the introduction:

<p v-if="greeting">Hello!</p>

Here, the directive would remove/insert the element based on the truthiness of the value of the expression .

Arguments

Some directives can take an “argument”, denoted by a colon after the directive name. For example, the directive is used to reactively update an HTML attribute:

<a v-bind:href="url"></a>

Here is the argument, which tells the directive to bind the element’s attribute to the value of the expression . You may have noticed this achieves the same result as an attribute interpolation using : that is correct, and in fact, attribute interpolations are translated into bindings internally.

Another example is the directive, which listens to DOM events:

<a v-on:click="doSomething">

Here the argument is the event name to listen to. We will talk about event handling in more detail too.

Modifiers

Modifiers are special postfixes denoted by a dot, which indicate that a directive should be bound in some special way. For example, the modifier tells the directive to interpret its attribute value as a literal string rather than an expression:

<a v-bind:href.literal="/a/b/c"></a>

Of course, this seems pointless because we can just do instead of using a directive. The example here is just for demonstrating the syntax. We will see more practical uses of modifiers later.

Какие функции выполняет name-сервер?

Привычные пользователям домены не являются настоящими адресами хостов в сети, для идентификации которых на практике используются IP-адреса. Работа с ними неудобна для пользователей, поэтому применяется система DNS-серверов. Они выполняют несколько базовых функций.

  1. Преобразуют введенное в адресную строку доменное имя в IP-адрес или наоборот (обратное преобразование).
  2. Сообщают об ошибках, если запросы направлены к несуществующей адресам.
  3. Предоставляют информацию о сервере, отвечающем за дочернюю зону (поддомены).
  4. Кэшируют записи, полученные с других name-серверов. Кэширование помогает увеличить скорость доступа к сайтам. Запросы к удаленному DNS-серверу занимают много времени, поэтому DNS-сервер провайдера хранит адреса ранее запрошенных сайтов в кэше.

Существует 3 основных типа DNS-серверов:

  1. Первичный (Primary, master), хранит файл зоны домена с информацией о всех ресурсных записях.
  2. Вторичный (Secondary, slave), загружает и хранит копию файла зоны с первичного DNS-сервера. Используется для повышения отказоустойчивости службы DNS.
  3. Кэширующий. Предназначен только для кэширования, применяется для разгрузки первичных и вторичных серверов, а также для повышения скорости доступа к сайтам.

Shorthands

The prefix serves as a visual cue for identifying Vue-specific attributes in your templates. This is useful when you are using Vue.js to apply dynamic behavior to some existing markup, but can feel verbose for some frequently used directives. At the same time, the need for the prefix becomes less important when you are building an SPA where Vue.js manages every template. Therefore, Vue.js provides special shorthands for two of the most often used directives, and :

Shorthand

<a v-bind:href="url"></a>

<a :href="url"></a>
or
<button v-bind:disabled="someDynamicCondition">Button</button>

<button :disabled="someDynamicCondition">Button</button>

Shorthand

<a v-on:click="doSomething"></a>

<a @click="doSomething"></a>

They may look a bit different from normal HTML, but all Vue.js supported browsers can parse it correctly, and they do not appear in the final rendered markup. The shorthand syntax is totally optional, but you will likely appreciate it when you learn more about its usage later.

Debian Wheezy and earlier

The named daemon is started using the bind user by default.

This option is found in the bind service config file /etc/default/bind9

OPTIONS="-u bind"

The bind start script /etc/init.d/bind9 reads this config file when the service is started.

Starting bind as a non root user is good practice but to run the daemon in a chroot environment we also need specify the chroot directory. This is done using the same OPTIONS variable in /etc/default/bind9.

To begin, start by stopping the bind service:

/etc/init.d/bind9 stop

Then edit /etc/default/bind9:

OPTIONS="-u bind -t /var/bind9/chroot"

If bind refuses to start with error messages like «network unreachable resolving: » followed by a host and an IPv6 address, then you might add argument «-4» to force bind to always use IPv4 instead of IPv6:

OPTIONS="-u bind -4 -t /var/bind9/chroot"

Now create the chroot directory structure:

mkdir -p /var/bind9/chroot/{etc,dev,var/cache/bind,var/run/named}

Create the required device special files and set the correct permissions:

mknod /var/bind9/chroot/dev/null c 1 3
mknod /var/bind9/chroot/dev/random c 1 8
mknod /var/bind9/chroot/dev/urandom c 1 9
chmod 660 /var/bind9/chroot/dev/{null,random,urandom}

Move the current config directory into the new chroot directory:

mv /etc/bind /var/bind9/chroot/etc

Now create a symbolic link in /etc for compatibility:

ln -s /var/bind9/chroot/etc/bind /etc/bind 

If you want to use the local timezone in the chroot (e.g. for syslog):

cp /etc/localtime /var/bind9/chroot/etc/

Change the ownership on the files you’ve just moved over and the rest of the newly created chroot directory structure:

chown bind:bind /var/bind9/chroot/etc/bind/rndc.key
chmod 775 /var/bind9/chroot/var/{cache/bind,run/named}
chgrp bind /var/bind9/chroot/var/{cache/bind,run/named}

Edit the PIDFILE variable in /etc/init.d/bind9 to the correct path:

PIDFILE=/var/bind9/chroot/var/run/named/named.pid

Finally tell rsyslog to listen to the bind logs in the correct place:

echo "\$AddUnixListenSocket /var/bind9/chroot/dev/log" > /etc/rsyslog.d/bind-chroot.conf

Restart rsyslog and start bind:

/etc/init.d/rsyslog restart; /etc/init.d/bind9 start

Losing “this”

We’ve already seen examples of losing . Once a method is passed somewhere separately from the object – is lost.

Here’s how it may happen with :

As we can see, the output shows not “John” as , but !

That’s because got the function , separately from the object. The last line can be rewritten as:

The method in-browser is a little special: it sets for the function call (for Node.js, becomes the timer object, but doesn’t really matter here). So for it tries to get , which does not exist. In other similar cases, usually just becomes .

The task is quite typical – we want to pass an object method somewhere else (here – to the scheduler) where it will be called. How to make sure that it will be called in the right context?

Тестовый стенд

Чтобы в полной мере насладиться изучением проблемы, нужно эмулировать идеальные условия ее возникновения. Для этого по старинке возьмем Docker.

В интернете ты можешь найти массу способов установки и настройки BIND, а здесь я пробегусь по ключевым моментам, которые позволят воссоздать ситуацию, когда атака возможна.

Первое, что нужно сделать после установки BIND, — это сконфигурировать новую зону в DNS-сервере. В этом нам поможет файл .

Создаем TSIG-ключ, даем ему произвольное имя и указываем алгоритм, который будет использоваться для генерации сигнатур при общении клиента с сервером DNS (и наоборот).

Для успешной эксплуатации уязвимости атакующему нужно угадать ключ и алгоритм хеширования.

Далее настраиваем саму зону (я задал ) и определяем, для каких запросов нужно использовать валидацию через протокол TSIG и соответствующий ключ.

Помимо прочего, нам понадобится какой-нибудь сниффер, например tcpdump.

Если не хочешь со всем этим возиться, то просто скачивай готовый файл Docker из моего репозитория. В нем используется уязвимая версия BIND 9.10.5. Запускай скрипт , он сделает все необходимое, тебе останется только запустить сам сервер командой .

Go-go-go!

Обновление системы

И как всегда первым делом обновим нашу систему:

Создадим папки для хранения конфигураций для локальных и внешних клиентов:

Создадим конфигурацию зон:

Соответственно db.dom замените на ваш домен. Содержимое файла должно быть примерно таким:

10.5.5.1 — внутренний адрес ресурса

Содержимое файла:

11.22.33.44 — внешний адрес ресурса.

Дальше отредактируем конфигурационный файл bind для того, чтобы он возвращал правильный адрес ресурса клиентам:

Приводим содержимое этого файла к следующему виду:

  • acl lan — наш список IP адресов, таких списков может быть несколько. В этой секции мы указываем адреса или сети, для которых хотим отдавать локальный адрес ресурса.
  • view «lan» — обработка для локальных клиентов сети lan.
  • view «inet» — обработка для всех остальных клиентов, которые не входят в список lan.

Еще обратите внимание на параметр recursion no; и recursion yes;. Будьте внимательны, включенные рекурсивные запросы могут использоваться для различных атак с использованием вашего сервера

Если вы не планируете прописывать ваш DNS сервер клиентам — лучше отключите рекурсивные запросы.

Так же неплохо было бы включить логи для нашего DNS сервера, это необязательно, и даже наверное лучше после тестирования выключить. В общем набираем:

Приводим файл named.conf к следующему виду:

Мы включили логирование, а так же отключили стандартные зоны (обратите внимание на строчку //include «/etc/bind/named.conf.default-zones»;, т.к. мы их прописали в файле named.conf.local, их в данной конфигурации нужно выключать обязательно

Перезапускаем bind:

Проверяем, что он запустился без ошибок:

Он должен быть в статусе active:

После этого можно проверять — для адресов указанных в acl будут возвращаться одни адреса, для всех остальных другие.

Тут есть один нюанс — запрос на ваш сервер будет приходить с адресов DNS серверов, которые указаны у клиента, а не непосредственно с клиентского адреса. Т.е. если у клиента прописаны гугловские DNSы, то и запросы на ваш сервер будут приходить с гугловых серверов, учитывайте это.

Примеры

Пример: Обработать клик и двойной клик по параграфу.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>bind demo</title>
  <style>
  p {
    background: yellow;
    font-weight: bold;
    cursor: pointer;
    padding: 5px;
  }
  p.over {
     background: #ccc;
  }
  span {
    color: red;
  }
  </style>
  <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>

<p>Click or double click here.</p>
<span></span>

<script>
$( "p" ).bind( "click", function( event ) {
  var str = "( " + event.pageX + ", " + event.pageY + " )";
  $( "span" ).text( "Click happened! " + str );
});
$( "p" ).bind( "dblclick", function() {
  $( "span" ).text( "Double-click happened in " + this.nodeName );
});
$( "p" ).bind( "mouseenter mouseleave", function( event ) {
  $( this ).toggleClass( "over" );
});
</script>

</body>
</html>

Демо:

Пример: вывести сообщение при клике по любому из параграфов:

$( "p" ).bind( "click", function() {
 alert( $( this ).text() );
});

Пример: Передаём данные в обработчик:

function handler( event ) {
 alert( event.data.foo );
}
$( "p" ).bind( "click", {
 foo: "bar"
}, handler );

Пример: Отмена стандартного действия:

$( "form" ).bind( "submit", function() {
 return false;
});

Пример: Отмена стандартного действия с помощью метода .preventDefault().

$( "form" ).bind( "submit", function( event ) {
 event.preventDefault();
});

Пример: Отмена стандартного действия с помощью метода .stopPropagation().

$( "form" ).bind( "submit", function( event ) {
 event.stopPropagation();
});

Пример: использование собственного события.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>bind demo</title>
  <style>
  p {
    color: red;
  }
  span {
    color: blue;
  }
  	</style>
  <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>

<p>Has an attached custom event.</p>
<button>Trigger custom event</button>
<span style="display: none;"></span>

<script>
$( "p" ).bind( "myCustomEvent", function( e, myName, myValue ) {
  $( this ).text( myName + ", hi there!" );
  $( "span" )
    .stop()
    .css( "opacity", 1 )
    .text( "myName = " + myName )
    .fadeIn( 30 )
    .fadeOut( 1000 );
  });
$( "button" ).click(function() {
  $( "p" ).trigger( "myCustomEvent",  );
});
</script>

</body>
</html>

Демо:

Пример: Обработка нескольких событий.

$( "div.test" ).bind({
 click: function() {
   $( this ).addClass( "active" );
 },
 mouseenter: function() {
   $( this ).addClass( "inside" );
 },
 mouseleave: function() {
   $( this ).removeClass( "inside" );
 }
});

MVC Todo

  • The code is around 50% longer
  • It does not use special HTML markup, it uses the function below to bind HTML to the model
  • It has two-way binding via observing the model every 100 milliseconds (same mechanism as Angular)
  • It is mostly understandable by people familiar with basic web development
  • It is simple enough

The mapper function:

functionmapper(todos){return{"i:nth-of-type(1)"remaining(),"i:nth-of-type(2)"todos.length,"li"todos.map(function(t,i){return{"@model" t,"@index" i,"input@checked"(t.done?"checked"false),"span"t.text,"span@class"(t.done?"done""")};})};}

Notice how the model is bound to the element in an explicit way.

By no means this little app is meant as proof or even claim of equivalent functionality. Angular is a big project,
with lots of functionality and features. It is meant as a simple comparison exercise to flex Bind’s muscles
with respect to a well known example.

Зона прямого просмотра

Зоны прямого просмотра делегируются нам владельцем родительского домена.

Пример файла зоны, для которой мы являемся мастером (SOA ns1.model.local.)
Сервер ns.example.com. указан в качестве вторичного.

Параметры времени жизни записи:

  • TTL — время, на которое запись считается действительной, после выдачи сервером. Записи в кэше хранятся в течение TTL.
  • Negative Cache TTL — время действия ответа об отсутствии записи (NXDOMAIN). Запись о том, что запрошенное имя не существует хранится в кэше на это время.

TTL можно задавать отдельно для каждой записи. Negative Cache TTL — действует на зоны в целом.

EXAMPLES top

       An example of the use of bind() with Internet domain sockets can be
       found in getaddrinfo(3).

       The following example shows how to bind a stream socket in the UNIX
       (AF_UNIX) domain, and accept connections:

       #include <sys/socket.h>
       #include <sys/un.h>
       #include <stdlib.h>
       #include <stdio.h>
       #include <string.h>

       #define MY_SOCK_PATH "/somepath"
       #define LISTEN_BACKLOG 50

       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       int
       main(int argc, char *argv[])
       {
           int sfd, cfd;
           struct sockaddr_un my_addr, peer_addr;
           socklen_t peer_addr_size;

           sfd = socket(AF_UNIX, SOCK_STREAM, 0);
           if (sfd == -1)
               handle_error("socket");

           memset(&my_addr, 0, sizeof(struct sockaddr_un));
                               /* Clear structure */
           my_addr.sun_family = AF_UNIX;
           strncpy(my_addr.sun_path, MY_SOCK_PATH,
                   sizeof(my_addr.sun_path) - 1);

           if (bind(sfd, (struct sockaddr *) &my_addr,
                   sizeof(struct sockaddr_un)) == -1)
               handle_error("bind");

           if (listen(sfd, LISTEN_BACKLOG) == -1)
               handle_error("listen");

           /* Now we can accept incoming connections one
              at a time using accept(2) */

           peer_addr_size = sizeof(struct sockaddr_un);
           cfd = accept(sfd, (struct sockaddr *) &peer_addr,
                        &peer_addr_size);
           if (cfd == -1)
               handle_error("accept");

           /* Code to deal with incoming connection(s)... */

           /* When no longer required, the socket pathname, MY_SOCK_PATH
              should be deleted using unlink(2) or remove(3) */
       }

Создание файла зоны и настройка записей

Создаем каталог master (если он отсутствует).

В CentOS / Red Hat:

mkdir /var/named/master

В Ubuntu / Debian:

mkdir /var/cache/bind/master

И создаем файл зоны (в нашем примере test.local).

CentOS / Red Hat:

vi /var/named/master/test.local

Ubuntu / Debian:

vi /var/cache/bind/master/test.local

Приводим его к следующему виду:

$TTL 14400
test.local.     IN      SOA     ns1.test.local. admin.test.local. (
        2017082401      ; Serial
        10800           ; Refresh
        3600            ; Retry
        604800          ; Expire
        604800          ; Negative Cache TTL
)
                IN      NS      ns1.test.local.
                IN      NS      ns2.test.local.
                IN      MX 10   mx.test.local.
                IN      MX 20   mx2.test.local.
@               IN      A       192.168.1.1
localhost       IN      A       127.0.0.1
ns1             IN      A       192.168.1.2
ns2             IN      A       192.168.1.3
mx              IN      A       192.168.1.4
mail            IN      A       192.168.1.5
www             IN      CNAME   test.local.

Формат записей: <имя узла> <класс (всегда ставится IN)> <тип записи> <значение>.

Немного подробнее:

Параметр Описание
$TTL Время актуальности записей в секундах. Необходим, чтобы указать другим DNS-серверам, как долго стоит хранить запись у себя в кэше. Слишком малое значение увеличит нагрузку на сервер, а большое приведет к слишком длительному процессу изменения записи.
SOA-запись В данном примере эта запись идет сразу после параметра TTL. Ее стоит описать отдельно. Она хранит общие настройки для зоны.

  • Serial — порядковый номер изменения. Его необходимо каждый раз менять вручную при редактировании файла. С помощью него вторичный сервер (если такой есть), может определить, что были изменения и начать процесс копирования настроек.
  • Refresh указывает вторичным серверам, через какой промежуток времени они должны сделать запрос на обновление зоны.
  • Retry говорит вторичным серверам, как часто повторять попытки на обновление зоны, если первичный сервер не смог дать ответ (сервис был недоступен).
  • Expire — время в секундах, которое может работать вторичный сервер, если недоступен первичный. Если данный период истечет, а вторичный сервер так и не смог обновить зону, он должен прекратить отвечать на запросы. 
<имя узла> Собственно доменное имя хоста. Может записываться без домена (как в данном примере) — он будет дописан автоматически. Также может быть записан полностью с доменом — в таком случае необходимо поставить точку на конце, например, mail.test.local. Если не указывается или обозначается знаком собаки (@), запись создается для имени зоны (в данном случае, test.local).
<класс> Всегда используется IN (Internet). Указывает на тип сети.
<тип записи>

Основные типы записей, использующиеся в DNS:

  1. A — сопоставляет имени узла соответствующий IP-адрес.
  2. NS — указатель на DNS-сервера, которые обслуживают данную зону.
  3. MX — почтовая запись. Указывает на почтовые сервера, которые обслуживают домен. Поддерживает приоритизацию — при указании нескольких записей, клиент будет ориентироваться на значение той, для которой указано меньшее число.
  4. CNAME — aliase или псевдоним. Перенаправляет запрос на другую запись.
  5. TXT — произвольная запись. Чаще всего используется для настройки средств повышения качества отправки почтовых сообщений.
<значение> Используется IP-адрес, имя узла, текстовая запись.

Чтобы зона начала работать, перечитываем ее:

rndc reload

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

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