Пряморукий DNS:
делаем	правильно
Лев	Николаев
О	чем	буду	рассказывать
• Как	сделать	резольвер (unbound,	bind)
• Как	держать	зоны (PowerDNS)
• Как	взболтать,	но	не	смешивать	(PowerDNS +	unbound)
Делаем	резольвер
Это	штука,	которая	умеет	превращать	ya.ru в	87.250.250.242
Кому	нужен	свой	резольвер?
• Организации
• Если	резольвер провайдера	отсутствует	или	жмет	спереди
• ЦОД	или	провайдер
• От	Вас	просто	будут	ждать	его	наличия
• Почему	резольвера нет	из	коробки	в	ОС?	(Кроме	FreeBSD	;)
• Вопрос	к	размышлению
Выбор	софта	для	резольвера
• Мне	нравится	unbound
• Это	результат	его	эксплуатации
• Да	можно	и	bind	использовать
• Если	не	смущает	забивать	гвозди	микроскопом
Привет	убунтуводам
• Разумеется,	что	юнита	для	systemd из	коробки	нет	в	16.04
• А	генератор	там	создает	ад
• Поэтому	не	наступайте	на	мои	грабли
• Это	стоило	30	тысячам	абонентов	получаса	«радости»
• Пишите	юнит!	Или	возьмите	у	меня
Что	должно	быть	в	резольвере?
• Никаких	форвардов	к	Яндексу	или	Google
• SO_REUSEPORT
• Prefetch
• Expired
• DNSSEC-валидация
Никакого	форварда
• Сторонние	DNS-серверы	ограничивают	количество	запросов
• Будет	тормозить	и	тупить
• Ходим	от	корневых	серверов	сами
SO_REUSEPORT ускоряэ
• Ядро	>= 3.9
• Да,	забудьте	о	всяких	там	адских ядрах	версии	2.6.моябабушкаизRedHat
• Несколько	процессов	или	потоков	могут	биндить один	порт
• У	них	должен	быть	одинаковый	UID,	чтобы	порт	не	«угнать»
• Нагрузка	распределяется	равномерно
• SO_REUSEADDR	так	не	делало
Prefetch помогаэ
• Запрашивает	домен	раньше,	чем	истек	его	TTL
• Это	позволяет	отвечать	из	кэша,	т.е.	быстро
• Приводит	к	росту	объема	трафика	процентов	на	10
• Кого	это	вообще	волнует?
• С	короткими	TTL	так	себе
Expired	предохраняэ
• В	bind	не	нашел,	есть	в	unbound
• Возвращает	просроченную	запись
• А	в	фоне	пытается	получить	свежую
• Хорошо	помогает	от	падений	ребят аля Dyn
• Либо	от	падения	внешней	связности
DNSSEC	защищаэ
• Валидировать нужно!
• Современные	TTL	стремятся	к	нулю
• Шанс	отравления	есть
• Мало	кто	даже	из	крупных	провайдеров	это	делает
• Ростелеком,	например,	не
Мелочи	жизни
• Никакого	ANY
iptables -A INPUT -p udp --dport 53 -m string --hex-string "|0000ff0001|" --algo bm -j DROP
• Rate-limit,	если	Вы	не	закрыты	извне
[здесь -j ACCEPT для всех тех, от кого закрываться не надо]
iptables -A INPUT -p udp --dport 53 -m state --state NEW -m recent …
--set --name DNSQF --rsource
--update --seconds 1 --hitcount 70 --name DNSQF --rsource -j DROP
• Для	unbound	хорошо	interface-automatic:	yes
• Тогда	может	отвечать	с	любого	адаптера
Что	мониторить?
Запросы	здорового	человека Запросы	курильщика
Виды	запросов
Виды	ответов
Не	надо	участвовать	в	DNS	Water	Torture
dnstop
• Чтобы	он	показывал	нормальное
• dnstop <интерфейс>	-i <наш ip>
• с	+	2
Грабли	(делюсь	своими)
• Криво	настроенные	роутеры	или	софт
• Тонны	PTR	запросов
• Китайские	видеорегистраторы
• «… А	у	меня	там	даже	компьютеров	нет,	только	камеры»
• Ботнеты в	Вашей	сети
• И	пользователям	на	них	совершенно	наплевать
Держим	зоны
Кто	держит	зоны	у	себя?
• Организации	– при	наличии	своих	особых	амбиций
• ЦОД	или	провайдер	– от	него	этого	ждут
Не	надо	совмещать
• Совмещать	на	одной	машине	резольвер и	зоны	– плохо!
• Однако	будет	много	искушений	так	поступить
• Ubuntu	Server	Guide	– одно	из	них
• Если	клиент	«увел»	домен	от	Вас,	то	клиенты	об	этом	не	узнают
• У	клиентов	Вашего	резольвера он	будет	старый
• А	у	всего	остального	мира	– новый
Выбор	софта
• Здесь	не	выбирается	софт,	а	выбирается	формат	хранения
• DNS	– это	база	данных
• Нет	ничего	глупее,	чем	хранить	ее	в	текстовых	файлах
• Даже	если	генерировать	их	Ansible или	chef
• Ответ:	PowerDNS
Привет	убунтуводам
• В	репозиториях 16.04	лежит	альфа	версия	PowerDNS 4.х
• Уже	год	к	версии	4.х	тянется	открытый	мной	issue	#3824
• Посвящен	тому,	что	от	рестарта	MySQL	оно	может	перестать	работать
• 3.х	вполне	себе	съедобно
• Ставится	из	.deb,	работает	хорошо
Вдумчивая	архитектура
• Удобный	редактор	базы	данных	– PowerAdmin
• Web-приложение	на	PHP
• Сразу	понятно,	что	его	нельзя	держать	на	реальном	ns
• А	кроме	того,	ns	обычно	несколько
• *XFR зон	далеко	не	самый	хороший	механизм
• В	нашем	случае	он	не	позволит	уйти	от	понятия	master/slave
PowerAdmin
MySQL
ns-сервер
mysqldump --skip-extended-insert
sql-файл
- загрузить	в	другую	БД
- RENAME	TABLE
- git commit	&&	git push
Сложности
• У	нас	есть	БД,	копии	которой	надо	разложить	по	другим	машинам
• БД	должна	накатываться	атомарно
• Либо	накатиться	вся,	либо	никак
• Репликация	тут	не	лучший	друг
• Очень	хочется	при	этом	видеть	суть	произошедших	изменений
• Например,	diff	с	прошлым	разом
Что	получим
• Скрипт	на	каждом	ns	делает	mysqldump с	машины	с	PowerAdmin
• Заливает	это	во	временную	БД
• Никаких	«промежуточных»	состояний
• А	потом	выполняет	RENAME	TABLE нескольких	таблиц
• Атомарно,	либо	все	выполнилось,	либо	все	обломалось
• git commit,	git push	там	же,	если	успешно
Что	получим
• Это	очень	простые	операции
• 225	строк	на	PHP	во	имя	добра
• Каждый	ns	это	делает	*/2
• Поскольку	начинают	одновременно,	получают	одинаковую	базу
• Для	git нужно	выгружать	с	--skip-extended-insert
• Тогда	каждый	INSERT	на	отдельной	строке,	git рад
Что	получим
• Забудьте	про	понятие	master/slave
• У	нас	есть	один	сервер,	где	редактируем
• И	допустим	10,	откуда	раздаем
• Нам	просто	нужно	держать	БД	одинаковой
Хьюстон,	у	нас	проблема
Это	работает	только	если	мы	master	и	slave.
Хьюстон,	у	нас	проблема
• Давайте	переосознаем роль	master/slave
• Master	шлет	уведомления,	как	только	у	него	изменилась	зона
• И	отвечает	на	запросы
• Slave	получает	уведомления	об	изменениях
• И	отвечает	на	запросы
Есть	два	стула варианта
• Клиент	хочет,	чтобы	мы	держали	у	себя	slave
• А	он	будет	master,	т.е.	мы	должны	забирать	у	него	данные
• Этот	вариант	потребует	телодвижений
• Клиент	хочет,	чтобы	мы	держали	у	себя	master
• А	он	будет	slave,	т.е.	будет	забирать	у	нас	копию
• Это	крайне	простой	вариант,	от	нас	не	нужно	ничего
• Любой	из	наших	серверов	готов	отдать	актуальную	копию	данных
Выход
• Назначить	один	из	серверов	ответственным	за	прием	*XFR
• Это	не	может	делать	сервер	с	PowerAdmin
• Там	нет	DNS-сервера
• В	итоге,	один	из	наших	серверов	с	получает	зоны
• Он	вносит	эти	изменения	в	свою	базу
• Которую	синхронизирует	обратно	с	PowerAdmin для	slave-доменов
PowerAdmin
MySQL
ns-сервер
- просто	синхронизация
ns-сервер	+	slave
- принимать	*XFR
- отдать	новое	в	PowerAdmin
- просто	синхронизация
Что	получим
• Тоже	достаточно	простая	операция	сравнения
• 215	строк	на	PHP	во	имя	добра
• Ответственный	за	slave	ns	это	делает	перед синхронизацией
• В	итоге,	он	сначала	записывает	данные	для	PowerAdmin
• А	потом	получает… их	же
Что	мониторить?
• Latency,	т.е.	сколько	времени	занял	ответ (микросекунды)
• Хорошо	позволяет	видеть	проблемы	с	базой	данных	или	занятость	
машины
Что	мониторить?
• Протокол,	по	которому	пришел	запрос
• TCP	нужен	только	для	больших	ответов	(они	редко	таковы	легитимно)
Что	мониторить?
• Виды	запросов	(A,	AAAA,	…)
Что	мониторить?
• Отправку	SERVFAIL	и	поломанные	пакеты
Взболтать,	но	не	смешивать
… ты	же	говорил,	что	так	делать	не	надо?!
Когда	нужна	связка	PowerDNS +	unbound?
• Локальные	домены	с	хитрой	структурой	(.local	или	еще	что)
• Это	можно	делать	в	unbound,	но	неудобно
• Один	из	механизмов	блокировки	сайтов	в	России
• «Плохой»	сайт	резолвится в	заглушку,	«хороший»	– нормально
• Корпоративное	рабство
• Смесь	предыдущих	двух	пунктов
• И	защита	от	вирусов	порой
Архитектура
• Запрос	принимает PowerDNS и	смотрит	в	базу
• Если	там	есть	запрашиваемое,	то	отдает
• Если	нет,	то	передает	unbound	на	этой	же	машине	для	резолва
Спасибо!
• Код
• https://github.com/maniaque/rootconf2017
• Контакты
• nikolaev@kasatkina.org
• Skype:	maniaque.ru

Пряморукий DNS: делаем правильно / Лев Николаев (Макснет)