Поднимаем свой DNS сервер Unbound и блокировщик рекламы Pihole в docker

Поднимаем свой DNS сервер Unbound и блокировщик рекламы Pihole в docker

Обновлено 12.08.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. Я стараюсь всегда отвечать в нём, в своё свободное время.

Спасибо, что читаете! Успехов вам в резолвинге имён 😉

Полезные источники

Подписаться
Уведомить о
2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии