Предыстория
Прожорливый Bind9
Пришлось мне пару лет назад покинуть свой родной дом и переехать в другой город. В результате свой самосборный медиа-центр пришлось оставить, а на новом месте купить телеприставку AuraHD Plus. Весьма не плохой девайс за свои деньги, особенно если учесть, что в нем встроены приложения для доступа к сервисам с фильмами и т.п.
Все бы ничего, но реклама там крутится на каждый чих. Пришлось изобретать, как же ее "порезать". Первая мысль была — поднять свой DNS сервер и отправлять все неугодные домены в /dev/null на 127.0.0.1. К этому моменту мой домашний серверок вернулся ко мне и занял свое почетное место на шкафу в качестве NAS сервера.
Сказано — сделано. Поднят Bind9, прописаны конфиги для нескольких доменов, все отлично. Летим.
Спустя пару недель пришла мысль в голову, а почему бы не использовать этот метод для фильтрации рекламы для всех устройств дома? Дело не хитрое же.
Поиск списков с рекламными доменами привел меня к нескольким урлам и я взялся их парсить. Где-то на просторах Хабра была статья, которая помогла мне с парсингом и написанием скриптов для генерации конфигов для Bind9 (спасибо автору, но я не смог найти ссылку, пусть меня простит).
Все сделано и пришло время запускать Bind9. Старт и все отлично. Кроме одного. Этот прожорливый монстр съел всю оперативку и попросил своп. 5 гигабайт памяти на 400 тысяч доменов!
По-мучая таким образом свой бедный сервер на Intel Atom я решил, что это не дело.
Миграция на PowerDNS
Погуглив и поизучав другие варианты, я пришел к выводу, что Bind9 не совсем то, что нужно. Нужен более легкий по ресурсам DNS сервер, который смог бы лопатить такое количество доменов.
PowerDNS подошел как нельзя к стати, т.к. он умеет сам читать конфиги Bind9 и использовать их в работе. Поставил, настроил (собственно в этом нет никакой сложности) backend Bind9 запустил.
Результат превзошел все ожидания — 700 MB потребляемой памяти после 5 гигабайт! Это ли не мечта? Особенно при наличии всего 4 GB в сервере. :)
Несколько месяцев так все и проработало, пока я не задумался, что конфиги Bind9 это конечно хорошо, но старт PowerDNS какой-то ну совсем медленный. Время на "всасывание" всех доменов до неприличия большое и стоит как-то оптимизировать этот процесс.
Из оптимизации оставалось влить только все эти домены с рекламой в MySQL. Это дало бы возможность более гибко управлять списком доменов, добавлять, удалять, поддерживать свои внутренние домены.
Закатали рукава и приступили. Оказалось все довольно просто — zone2sql решает все проблемы :) Оставалось завернуть все это в доккер и поднять. Сделал довольно быстро и без особых проблем.
Так оно летит уже с полгода дома и радует. Но сегодня вышла статья на Хабре о блокировщике рекламы для смартфонов Samsung и мне предложили в комментариях выдать мое поделие в открытый доступ.
Что ж, делюсь.
Зависимости
docker
Поскольку все это крутится внутри контейнеров docker, то эта штука нам 100% понадобится. Все действия относятся к Ubuntu Linux, т.к. именно его я использую дома и в работе.
Устанавливается она согласно документации достаточно просто:
curl -sSL https://get.docker.com/ | sh
После завершения работы скрипта docker будет готов и им можно пользоваться.
Если вы предпочитаете другой метод установки, то всегда можно обратиться к документации и выбрать то, что вам будет по душе.
docker-compose
Docker Compose предназначен для планирования и организации процессов в контейнерах Docker (запуска, отключения, создания межконтейнерных соединений и томов, и т.п.).
Установка не сложнее самого докера:
curl -L "https://github.com/docker/compose/releases/download/1.8.1/docker-compose-$(uname -s)-$(uname -m)" > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
Запуск собственного фильтра рекламы
Клонируем репозиторий
Логичное действие и не нуждается, наверное, в пояснениях, зачем это делать. :)
sudo mkdir /opt/docker
sudo chown <user> /opt/docker
git clone https://github.com/DmitriyLyalyuev/powerdns-no-ads /opt/docker/pdns
cd /opt/docker/pdns
Создаем базу данных
docker-compose up -d mysql
Пользователь базы данных
Для доступа к консоли MySQL сервера нужно выполнить:
docker exec -ti pdns_mysql_1 mysql -u root -p
Пароль по умолчанию для пользователя root — 12345.
Создаем пользователя и базу:
CREATE USER 'powerdns_user'@'%' IDENTIFIED BY 'powerdns';
GRANT ALL PRIVILEGES ON powerdns.* TO 'powerdns_user'@'%';
CREATE DATABASE powerdns;
exit
Стартуем DNS сервер
docker-compose up -d
Обновление списков рекламных доменов
Для обновления списков запускаем:
docker exec -ti pdns_pdns_1 bash
cd /etc/powerdns/bind
./getnewlist.sh && ./import.sh && ./clean.sh
exit
White listing
Список для исключения доменов содержится в начале файла /opt/docker/pdns/powerdns-server/bind/getnewlist.sh.
Пользуйтесь, экспериментируйте и давайте сделаем интернет чище. Хотя бы у себя дома. ;)
Комментарии (33)
776166
02.11.2016 14:29-4когда вы повыедетесь уже! :) ©
4dmonster
02.11.2016 15:35+2Глупость, повторенная дважды, не становиться шуткой.
776166
02.11.2016 15:36-1Блокировка рекламы — это вам не шутки.
4dmonster
02.11.2016 15:37+6Да, это вынужденная необходимость.
776166
02.11.2016 19:00-1Не думаю, что это вынужденная необходимость: блокировать всю рекламу скопом.
4dmonster
04.11.2016 12:59Поскольку в настоящее время, это решение работает лучше, чем решение с «приемлемой» рекламой, мы вынуждены блокировать всю рекламу.
Пока нет возможности отфильтровать только порнуху, мошенников и неприемлемые форматы, блокироваться будет всё.
lolipop
02.11.2016 14:53+1dnsmasq потребляет память в килобайтах, делает всё то же самое, работает даже на роутерах с 16мб оперативки.
зачем этот велосипед было городить — непонятно.dmitriylyalyuev
02.11.2016 14:58+2Вы в него пробовали запихнуть 400 тысяч доменов?
Пробовали управлять всем этим делом?
Как быстро он стартует с таким багажом?
Сомневаюсь, что он сможет это все адекватно переваривать.lolipop
02.11.2016 15:43root@router:/etc/dnsmasq.d# cat ad* | wc -l
635317
стартует минуту на слабом железе.dmitriylyalyuev
02.11.2016 16:15+1Рад, что он так отлично работает. Надо будет посмотреть в его сторону.
acmnu
02.11.2016 16:41На самом деле причина такой колосальной разницы между «настоящими» DNS и dnsmaq в том, что большие DNS сделаны для того, чтобы обслуживать крупные авторитативные DNS в интернете. Поэтому они сразу тащат все в память, предполагая, что производительность важнее и хостер с 400к доменов уж может себе позволить 5G памяти.
А dnsmasq сделан именно как прокладка между локальным компом или максимум локальной сеткой и большим миром, поэтому логика его работы совсем другая. Если не пытаться разом обратится ко все 600К доменам, то и память он не должен так кушать.
tony
02.11.2016 16:34поделитесь роскошным файликом)
wmlex
02.11.2016 16:49+1Тоже использую dnsmasq для блокировки рекламы.
# cat /etc/dnsmasq.hosts | wc -l
48306
Базы обновляю при помощи скрипта в cron.
#!/bin/bash # if test -s /tmp/hosts_list.* then rm -f /tmp/hosts_list.* fi wget --no-check-certificate -O /tmp/hosts_list.1 http://hosts-file.net/ad_servers.txt && wget --no-check-certificate -O /tmp/hosts_list.2 https://adaway.org/hosts.txt && cat /tmp/hosts_list.* | grep -v ^# | sort -u > /etc/dnsmasq.hosts && rm -f /tmp/hosts_list.* && /bin/systemctl reload dnsmasq
neumeika
02.11.2016 16:46так же быстр nsd, хотя да, dnsmasq есть во всех роутерах,
А уж цеплять скуль к днс — сильное снижение времени ответаdmitriylyalyuev
02.11.2016 16:47-1$ dig @127.0.0.1 ya.ru ; <<>> DiG 9.9.5-3ubuntu0.8-Ubuntu <<>> @127.0.0.1 ya.ru ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30975 ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;ya.ru. IN A ;; ANSWER SECTION: ya.ru. 6685 IN A 213.180.193.3 ya.ru. 6685 IN A 93.158.134.3 ya.ru. 6685 IN A 213.180.204.3 ;; Query time: 44 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Wed Nov 02 15:46:33 EET 2016 ;; MSG SIZE rcvd: 82
Да вроде не сильно снижает время ответа. ;)
neumeika
02.11.2016 17:01Это, прошу прощения, в сравнении с чем?
у меня вафлероутер (на атоме вроде) говорит за 1(кеш) и 4 (not cached) msec, т.е. в 11 раз быстрее, что всё-таки является показателем, имхо.
Про unbound забыл, тоже очень быстрое/простое поделие, но сие для диких нагрузокdmitriylyalyuev
02.11.2016 17:04+1Вот и я говорю — в сравнении с чем… Меня это время ответа устраивает. Я из дома не устраиваю гонки на бирже. Меня больше волнует отсутствие рекламы дома.
На работе я не использую PowerDNS, само собой. Там все по другому.
dmitriylyalyuev
03.11.2016 23:56Сделал вот на dnsmasq — https://github.com/DmitriyLyalyuev/dnsmasq-no-ads
Но статью писать по этому делу, думаю, не стоит. :)
sena
02.11.2016 16:38+1Вроде бы squid для этого раньше применяли.
Ivan_83
02.11.2016 21:36Капетанская тема.
бинд — тот ещё кусок мамонта.
700 метров поверднса тоже перебор.
Докер тут лишний, как и база: там конфигов полторы штуки компактно лежат в одной папке, ради этого использовать докер, созданный в качестве костыля для горе погромистов у которых прога работает только на компе на котором написана или горе админов, которые не в силах осилить повторную настройку софтины.
Нафига держать список из ххх тыщ доменов не понятно, когда хватает от силы пары сотен чтобы не видеть 99% рекламы, ибо она в основном в популярных сетях крутится а их мало.
Юзаю unbound, он занимается рекурсией (те ни провайдерские днс ни 8.8.8.8 мне ну нужны вообще), навесил на него ещё и фильтрацию: для доменов из списка он возвращает NX — те типа домена нет, это лучше чем 127.0.0.0 или прочее.
Вот блок для гугла:
### Google
local-zone: «doubleclick.net» static
local-zone: «fonts.googleapis.com» static
local-zone: «google-analytics.com» static
local-zone: «google-analyzing.com» static
local-zone: «googleadservices.com» static
local-zone: «googlesyndication.com» static
local-zone: «safebrowsing-cache.google.com» static
local-zone: «safebrowsing.clients.google.com» static
local-zone: «safebrowsing.google.com» static
local-zone: «video-stats.video.google.com» static
2 lolipop
Днсмаск как днс — фуфло полное.
Он не умеет рекурсию, кеш там посредственный, про DNSec молчу, ибо не нужен.
2 sena
Раньше да.
Потом я применял nginx для проксирования с целью фильтрации, потом стало много https и такое проксирование стало практически бесполезно.
С приходом блокировок я вернул nginx, он теперь автоматом проксирует сайты которые напрямую открыть не может.
2 acmnu
бинд сделан чтобы соотвествовать тому что написано в RFC, это основная цель работы его создателей — ISC, производительность и пр для них глубоко вторичны.
2 neumeika
анбоунд далеко не прост.
Там и рекурсер и кеш и валидатор и пр, собирается он далеко не моментально с исходников.neumeika
02.11.2016 21:56Проще чем bind, ни вьюх, ни плагинов, бэкенд не поменяешь для зон.
Из исходников? я подобным только на проектах с BSD занимаюсь, а там j4, минимум.
SlavikF
03.11.2016 00:39Снизойдите ко мне, если я совсем в танке…
Я, в общем знаю, что такое DNS, а вот Bind и прочее — не сильно.
Из статьи я понял, как настроить сёрвис, нокак вот сделать так, чтобы мои устройства дома использовали этот сёрвис?
— нужно ли будет в каждом устройстве прописывать DNS server, указывая на мой?
— или это каким-то образом надо будет сделать на роутере, чтобы он всем раздавал это в настройках сети через DHCP?strelkan
03.11.2016 08:31dhcp в стандартных прошивках роутеров обычно указывает себя в качестве днс-сервера, всё зависит от модели
SlavikF
03.11.2016 08:35Ну да. Поэтому я и спрашиваю — как заставить это всё работать?
Нужно чтобы роутер умел указывать на нужный DNS? Или он указывает на себя, а сам смотрит на поставленный PowerDNS вместо провайдера?
Или надо на конечных устройствах указывать на свой PowerDNS сервер?
Dreyk
Спасибо!
Создание базы можно подсунуть в скрипт
тогда база будет создаваться сама.
UPD: а, у вас maria, надо посмотреть, умеет ли их image такую штуку
UPD2: да, умеет, тут у них с mysql совместимость
dmitriylyalyuev
Спасибо, посмотрю в эту сторону. :)