Поднимаем свой DNS сервер Unbound и блокировщик рекламы Pihole в docker
Обновлено 02.10.2024
Приветствую!
Как вы поняли из названия, сегодня мы установим и запустим локальный DNS сервер Unbound в связке с блэкджеком.. блокировщиком рекламы посредством DNS запросов – Pi-hole, с помощью docker. Все управление этим хозяйством будет производиться через удобный веб GUI программы Pi-hole. Ну и соответственно, мы подключим этот локальный DNS к нашему VPN серверу на базе OpenConnect, который мы настроили ранее. Будет интересно и не сложно, честно)
Присоединяйтесь к нашему каналу в телеграм: t.me/r4ven_me, уведомления о новых постах приходят туда в день публикации. А если у вас есть вопросы или просто желание пообщаться по тематике – заглядывайте в чат: t.me/r4ven_me_chat.
Все действия были протестированны в среде дистрибутивов Debian 12 и Ubuntu 22.04.
Короткое введение
Unbound — это Open source продукт от компании NLnet Labs, представляющий собой удостоверяющий, рекурсивный и кэширующий DNS сервер. Распространяется под лицензией BSD.
Pi-hole — это Linux приложение для блокировки рекламы и интернет-трекеров на сетевом уровне, которое действует как DNS-sinkhole и, опционально, как DHCP-сервер. Обычно используется в частных сетях. Также имеет открытый код и распространяется под лицензией EUPL.
Прошу обратить внимание, что данная статья не ставит целью разобрать все тонкости работы системы доменных имён и в частности сервера Unbound. Мы лишь разворачиваем личные сервисы 😉 Подразумевается, что у вас есть минимальное представление о данной технологии.
Подготовка
Для развертывания сервисов нам требуется установленный Docker engine. Если он еще не установлен, то инструкция воть: Установка Docker engine на Linux сервер под управлением Debian
Теперь выполним некоторые подготовительные действия:
- получаем привилегии root и создаём директории и файлы проекта:
sudo -s
mkdir -p /opt/pihole/{pihole_data,unbound_data} && cd /opt/pihole
touch ./unbound_data/{a,srv,forward}-records.conf
Создание пустых файлов *-records.conf
необходимо для сервиса unbound, который не запуститься без них)
- далее создадим отдельную сеть docker для объединения контейнеров из разных сервисов:
docker network create \
--opt com.docker.network.bridge.name=br_vpn \
--driver bridge --subnet 10.10.11.0/24 vpn_network
docker network ls
Как видно, мы создали сеть с адресацией 10.10.11.0/24, названием vpn_network и задали имя виртуальому сетевому устройству-мосту (bridge): br_vpn.
На этом подготовка завершена, приступаем к созданию файла описания сервисов-контейнеров docker.
Создание docker-compose.yml
Открываем новый файл на редактирование любым удобным консольным редактором. Мои читатели знают, что в качестве такового я предпочитаю Vim/Neovim.
Не премину сообщить, что у меня на сайте есть цикл статей про данный редактор. Найдёте их
у старого дубапо соответствующему тегу 😉
vim docker-compose.yml
И вставляем в него следующее содержимое:
---
networks:
vpn_network:
external: true
ipam:
driver: default
config:
- subnet: 10.10.11.0/24
services:
unbound:
image: mvance/unbound:latest
container_name: unbound
restart: unless-stopped
hostname: "unbound"
volumes:
- "./unbound_data/:/opt/unbound/etc/unbound/"
networks:
vpn_network:
ipv4_address: 10.10.11.200
pihole:
#depends_on: [unbound]
container_name: pihole
image: pihole/pihole:latest
restart: unless-stopped
hostname: pihole
dns:
- 127.0.0.1
- 10.10.11.200 # Points to unbound
environment:
TZ: "Europe/Moscow"
WEBPASSWORD: "" # Blank password - Can be whatever you want.
ServerIP: 10.10.11.100 # Internal IP of pihole
DNS1: 10.10.11.200 # Unbound IP
DNS2: 10.10.11.200 # If we don't specify two, it will auto pick google.
volumes:
- "./pihole_data/:/etc/pihole/"
- "./dnsmasq_data/:/etc/dnsmasq.d/"
ports:
- 127.0.0.1:80:80
# Recommended but not required (DHCP needs NET_ADMIN)
# https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
cap_add:
- NET_ADMIN
networks:
vpn_network:
ipv4_address: 10.10.11.100
Актуальная версия файла docker-compose.yml
также доступна на GitHub.
Кратко пробежимся по содержимому. На всякий ссылку на справку по наполнению файлов compose оставлю тут и в конце статьи.
В блоке networks мы определяем сетевые параметры среды наших сервисов. Тут все стандартно, кроме параметра external: true
из-за которого мы и создавали нашу сеть на этапе подготовки. Без предварительного создания сети, сервисы compose просто не запустяться.
Далее идёт блок services. Тут мы описываем параметры наших сервисов-контейнеров DNS сервера Unbound и программы Pi-hole. Здесь желательно ничего не менять, ну кроме возможно вашей адресации и монтируемых volume.
Важно четко задать IP адрес каждому контейнеру в параметре networks, и указать эти адреса в качестве environment в сервисе pihole. Все это нужно для корректного взаимодействия этих двух сервисов.
Обратите внимание, что директивой ports у сервиса pihole мы прокидываем 80 порт (веб GUI) в хостовую систему, которая будет прослушивать его по адресу 127.0.0.1:80, т.е. доступ к GUI будет только из среды самого сервера.
Если будете настраивать доступ к веб GUI для доступа из локальной сети или из VPN, то замените 127.0.0.1 на существующий адрес сетевого интерфейса хоста. В случае доступа через интернет – настройте перенаправление портов по защищенному каналу, например SSH. Что мы и сделаем чуть позже.
Если не указывать конкретный адрес, будет использован 0.0.0.0, что автоматически откроет данный порт наружу. А это, как известно, небезопасно, если ваш сервер доступен по внешнему IP.
Ах да, еще один момент. В переменной WEBPASSWORD: ""
можно задать пароль админа при входе в GUI pihole. Если оставить его пустым, вход будет, как очевидно, без авторизации.
Теперь сохраняем файл и переходим к запуску контейнеров.
Запуск Pihole + Unbound
В директории проекта запускаем наши контейнеры такой командой:
docker compose up -d && docker compose logs -f
Вы увидите нечто подобное:
Если все запустилось корректно, выходим из режима просмотра вывода контейнеров нажмитем Ctrl+c
.
Для просмотра статуса запущенных контейнеров воспользуемся командой:
docker compose ps
Всё работает, всё корректно. Сразу настроим автозапуск.
Настройка автозапуска с systemd
Создаём файл сервиса:
vim /etc/systemd/system/pihole.service
Наполняем его:
[Unit]
Description=Pihole and Unbound service
Requires=docker.service
After=docker.service
[Service]
Restart=always
RestartSec=5
WorkingDirectory=/opt/pihole
ExecStart=/usr/bin/docker compose up
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
Актуальная версия файла pihole.service
также доступна на моём GitHub.
Останавливаем запущенные вручную сервисы и активируем {авто}запуск уже с помощью systemd:
docker compose down
systemctl enable --now pihole
systemctl status pihole
docker compose ps
На вид рабочее) мы молодцы, переходим к веб GUI.
Подключение к веб GUI
Если вы разворачивали DNS сервер на машине, с которой и работаете, то просто перейдите по адресу http://localhost/admin
.
Если ваш DNS сервер находится удаленно, то с учётом того, что наш GUI слушает порт 80 на локальном порту сервера, необходимо настроить перенаправление портов с помощью SSH. Делается это для безопасного доступа к веб интерфейсу.
На клиенте открываем терминал и выполняем:
ssh -L 8080:localhost:80 user@example.com
Где:
-L
– ключ перенаправления локального порта;8080
– порт, который будет слушать клиентская машина и перенаправлять его на 80 порт сервера;localhost
– адрес сервера, на котором он слушает порт;80
– соответственно порт, на который перенаправляем;user@example.com
– пользователь и адрес сервера SSH.
В моём примере команда такая:
Теперь открываем браузер и переходим по адресу: http://localhost:8080/admin
И попадаем в наш веб GUI:
Интерфейс, как это принято говорить, интуитивно понятен. Нас тут интересует локальные записи DNS и списки блокировки рекламных доменов.
Записи DNS расположены в разделе Local DNS 😉 Для теста добавим несколько новых:
К слову, основной конфиг файл сервера Unbound лежит по пути
/opt/pihole/unbound_data/unbound.conf
.
Списки доменов для блокировки задаются в разделе Adlists
. Они представляют собой ссылку на текстовый файл с самим списком в формате hosts: ip_address domain_name
Блокировка достигается простым перенаправлением нежелательного доменного имени на адрес-заглушку 0.0.0.0
. Всё гениальное – просто)
Как видно на скриншоте, в Pi-hole уже добавлен один публичный список. Вы можете с легкостью добавлять сюда свои:
Или в файле /opt/pihole/pihole_data/adlists.list
.
Переходим к настройкам DNS на клиентах.
Настройка DNS на клиентах
В мире Linux существует множество способов настройки DNS на клиентах, что только запутывает многих пользователей. Я разберу лишь самые популярные способы.
Файл resolv.conf
Самый классический способ настройки DNS в Linux – это файл resolv.conf. Открываем его на редактирование:
vim /etc/resolv.conf
И добавляем запись. Важно чтобы она была выше уже существующих параметров nameserver
:
nameserver 10.10.11.100
Сохраняем, закрываем. Настройки подхватываются на лету.
Systemd-resolved
Во многих современных дистрибутивах Linux для управления DNS используется один из модулей systemd – systemd-resolved.
Для редактирования параметров DNS открываем файл конфигурации:
vim /etc/systemd/resolved.conf
И изменяем (или дополняем) директиву DNS=
:
Сохраняем и перезапускаем службу + очищаем кэш DNS:
systemctl restart systemd-resolved
resolvectl flush-caches
По опыту, в случае systemd-resolved предпочтительным будет перезапустить систему целиком)
reboot
NetworkManager
А на десктопных линуксах, сетью, в т.ч. и параметрами DNS, управляет NetworkManager. Тут придется покликать мышкой.
Заходим в сетевые соединения через апплет на рабочем столе или через меню приложений:
Далее выбираем наше основное физическое соединение:
Переходим на вкладку настроек IPv4 и задаём адрес DNS сервера:
Готово)
Проверка
Для проверки корректности настроек DNS в случае resolve.conf и NetwrokManager выполняем:
nslookup google.ru
Имя резолвится через локальный DNS, то, что нужно.
А в случае systemd-resolved команды такие:
resolvectl dns
resolvectl query google.ru
Отлично.
Теперь проверим добавленные ранее в веб интерфейсе Pi-hole DNS записи:
ping -c3 dns.r4ven.me
ping -c3 localhost.r4ven.me
Работает!
Теперь перейдем к настройке DNS параметров на VPN сервере (если он у вас есть).
Настройка DNS в конфиге OpenConnect (ocserv)
Если вы настраивали ocserv по моей статье, то после добавления в схему DNS сервера, она будет выглядеть так:
И так, для настройки связки ocserv
c pihole+unbound
первым делом необходимо добавить в compose файл проекта:
vim /opt/openconnect/docker-compose.yml
Определение сети:
networks:
vpn_network:
external: true
ipam:
driver: default
config:
- subnet: 10.10.11.0/24
А в параметры контейнеров добавьте директиву networks:
...
networks:
- vpn_network
...
Теперь необходимо отредактировать конфиг файл самого сервера ocserv:
vim /opt/openconnect/data/ocserv.conf
Добавив значение параметра dns (первого):
После необходимо перечитать конфиг или перезапустить сервис OpenConnect любым способом:
# перечитывание конфига
docker exec -it openconnect occtl reload
# перезапуск контейнера
docker restart openconnect
# или
systemctl restart openconnect
А также переподключиться на клиентах и готово.
Заключение
Вот мы и настроили наш локальный DNS сервер на базе Unbound + Pi-hole. А также сконфигурировали обращение к нему клиентов. Дополнительно мы задали адрес DNS сервера в конфиге OpenConnect сервера, тем самым получив завершённое VPN решение.
Конечно мы с вами рассмотрели далеко не все возможности данного стека. Но повторюсь, такой цели и не ставилось. Pi-hole из коробки имеет множество интересных функций, например DHCP сервер, с настройкой в веб GUI и пр. Но это уже выходит за рамки данной статьи. Все источники на документацию вы найдёте ниже.
Подписывайтесь на наш канал в телеграм @r4ven_me чтобы не пропустить новые посты на сайте Вороний блог)
А если остались вопросы, добавляйтесь в наш чат там же: @r4ven_me_chat. Я стараюсь всегда отвечать в нём, в своё свободное время.
Спасибо, что читаете! Успехов вам в резолвинге имён 😉
Полезные источники
- Файлы проекта в моём репо на GitHub
- Официальный сайт проекта Unblound (EN)
- Статья про Unbound на ArchWiki
- Репозиторий docker обараз Unbound из статьи (EN)
- Официальный сайт проекта Pi-hole (EN)
- Репозиторий docker образа Pihole (EN)
- Справка по docker-compose.yml (EN)
- Моя статья по настройке VPN сервера OpenConnect (ocserv)
- Установка Docker engine на Linux сервер под управлением Debian
Вопрос из чата в телеграм: “Чем различаются dnsmasq и unbound?”
Отличаются по функционалу. Unbound это полноценное DNS решение, резолвер, рекурсивный, кэширующий сервер и пр. + Поддержка протоколов безопасности, таких как DNSsec. Современный аналог популярного bind сервера.
В тоже время dnsmasq легковесный DNS сервер, но вроде как без резолвинга, только форвардинг и кэш. И включает в себя DHCP сервер. Небольшой комбайн)
Выбрал unbound в качестве сервера DNS, чтобы закрыть все потребности в таком инструменте
Если интересно именно про эту связку, вот статья с оф доки pihole
https://docs.pi-hole.net/guides/dns/unbound/
Unbound напрямую общается с корневыми серверам, в итоге предоставит истинный адрес в ответе. Что повышает конфиденциальность, но за счёт рекурсии, при первичных запросах может быть небольшая задержка. Но после данные все равно сохранятся в кэше.