Настройка dns-сервера bind9 на ubuntu 20.04 lts
Содержание:
- Быстрая установка, или еще раз об одном и том же
- INFO
- Вариант простейшей настройки «Кеширующий сервер DNS»
- Directives
- Какие функции выполняет name-сервер?
- Shorthands
- Debian Wheezy and earlier
- Losing “this”
- Тестовый стенд
- Обновление системы
- Примеры
- MVC Todo
- Зона прямого просмотра
- EXAMPLES top
- Создание файла зоны и настройка записей
Быстрая установка, или еще раз об одном и том же
Итак, как установить 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-серверов. Они выполняют несколько базовых функций.
- Преобразуют введенное в адресную строку доменное имя в IP-адрес или наоборот (обратное преобразование).
- Сообщают об ошибках, если запросы направлены к несуществующей адресам.
- Предоставляют информацию о сервере, отвечающем за дочернюю зону (поддомены).
- Кэшируют записи, полученные с других name-серверов. Кэширование помогает увеличить скорость доступа к сайтам. Запросы к удаленному DNS-серверу занимают много времени, поэтому DNS-сервер провайдера хранит адреса ранее запрошенных сайтов в кэше.
Существует 3 основных типа DNS-серверов:
- Первичный (Primary, master), хранит файл зоны домена с информацией о всех ресурсных записях.
- Вторичный (Secondary, slave), загружает и хранит копию файла зоны с первичного DNS-сервера. Используется для повышения отказоустойчивости службы DNS.
- Кэширующий. Предназначен только для кэширования, применяется для разгрузки первичных и вторичных серверов, а также для повышения скорости доступа к сайтам.
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. Ее стоит описать отдельно. Она хранит общие настройки для зоны.
|
<имя узла> | Собственно доменное имя хоста. Может записываться без домена (как в данном примере) — он будет дописан автоматически. Также может быть записан полностью с доменом — в таком случае необходимо поставить точку на конце, например, mail.test.local. Если не указывается или обозначается знаком собаки (@), запись создается для имени зоны (в данном случае, test.local). |
<класс> | Всегда используется IN (Internet). Указывает на тип сети. |
<тип записи> |
Основные типы записей, использующиеся в DNS:
|
<значение> | Используется IP-адрес, имя узла, текстовая запись. |
Чтобы зона начала работать, перечитываем ее:
rndc reload