Как запустить фильтр для рекламы?

Что происходит в обычном сценарии подключения к интернету в домашней сети?

Этапы:

  1. Получение настроек: Устройства получают от роутера адрес DNS-сервера

  2. Использование публичного DNS: Обычно это DNS провайдера, Google (8.8.8.8) или Cloudflare (1.1.1.1)

  3. Отправка всех запросов: Все DNS-запросы уходят на внешний сервер

  4. Получение ответов: Ответы приходят напрямую к устройствам

Проблемы этой схемы:

1. Конфиденциальность 👁️

  • Провайдер видит ВСЕ: Каждый запрос, каждый сайт, каждое приложение

  • Google/Cloudflare знают о вас: Если используете их DNS, они строят профиль

  • Полная история посещений: Доступна третьим лицам

2. Реклама и трекеры 🎯

  • Нет фильтрации: Вся реклама проходит беспрепятственно

  • Трекеры следят за вами: Сайты знают, где вы были и что искали

  • Таргетированная реклама: На основе ваших запросов показывается релевантная реклама

3. Безопасность ⚠️

  • DNS-спуфинг: Легче подменить ответы

  • Нет проверки подлинности: Ответы могут быть от поддельных серверов

  • Манипуляции с трафиком: Провайдер может перенаправлять запросы

4. Цензура и ограничения 🚫

  • Фильтрация на уровне DNS: Провайдер может блокировать сайты

  • Гео-ограничения: DNS может определять ваше местоположение

  • Троттлинг: Замедление определенных запросов

        flowchart TD
    subgraph "Обычный сценарий"
        Router[Роутер провайдера<br>или домашний роутер]

        subgraph "Устройства"
            Phone[Смартфон]
            Laptop[Ноутбук]
            TV[Умный телевизор]
        end

        Phone -->|"1 DHCP запрос<br>Дай настройки сети"| Router
        Laptop -->|"1 DHCP запрос<br>Дай настройки сети"| Router
        TV -->|"1 DHCP запрос<br>Дай настройки сети"| Router

        Router -->|"2 Назначает DNS-сервер<br>(обычно DNS провайдера<br>или Google/Cloudflare)"| Phone
        Router -->|"2 Назначает DNS-сервер<br>(обычно DNS провайдера<br>или Google/Cloudflare)"| Laptop
        Router -->|"2 Назначает DNS-сервер<br>(обычно DNS провайдера<br>или Google/Cloudflare)"| TV

        Phone -->|"3 DNS-запрос<br>Где vk.com?"| ProviderDNS[DNS провайдера<br>или публичный DNS]
        Laptop -->|"3 DNS-запрос<br>Где vk.com?"| ProviderDNS
        TV -->|"3 DNS-запрос<br>Где kinopoisk.ru?"| ProviderDNS

        ProviderDNS -->|"4 Все запросы видны<br>провайдеру/DNS-сервису"| Internet[Интернет]

        Internet -->|"5 Ответ<br>(часто с рекламой)"| ProviderDNS
        ProviderDNS -->|"6 Ответ устройству<br>(без фильтрации)"| Phone
        ProviderDNS -->|"6 Ответ устройству<br>(без фильтрации)"| Laptop
        ProviderDNS -->|"6 Ответ устройству<br>(без фильтрации)"| TV
    end

    subgraph "Проблемы"
        Problem1[Сбор данных<br>Ваша история посещений]
        Problem2[Таргетированная реклама<br>на основе ваших запросов]
        Problem3[Реклама и трекеры<br>на всех сайтах]
        Problem4[Провайдер видит<br>все ваши запросы]
    end

    style Router fill:#ffccbc
    style Phone fill:#e1f5fe
    style Laptop fill:#e1f5fe
    style TV fill:#e1f5fe
    style ProviderDNS fill:#ffccbc
    style Problem1 fill:#ffebee
    style Problem2 fill:#ffebee
    style Problem3 fill:#ffebee
    style Problem4 fill:#ffebee
    

В этой статье будем стараться исправить имеющиеся у нас «проблемы» при взаимодействии с Интернет.

docker-compose

Для фильтрации DNS-запросов будем использовать Pi-hole, а в роли DNS-сервера будем использовать Unbound .

Чтобы описать docker-compose.yml сначала опишем концептуальную схему:

        flowchart TD
    subgraph "Домашняя сеть"
        Router[Роутер<br>раздает настройки сети]

        Devices[Все устройства:<br>телефоны, ноутбуки, ТВ]
    end

    subgraph "Docker-сервисы"
        Pihole["Pi-hole<br>1. Фильтрует рекламу<br>2. Принимает DNS-запросы"]

        Unbound["Unbound<br>1. Безопасный DNS-резолвер<br>2. Запрашивает сайты напрямую<br>   у корневых серверов"]
    end

    Router -->|"Назначает Pi-hole<br>как DNS-сервер"| Devices
    Devices -->|"Все DNS-запросы<br>(куда пойти?)"| Pihole

    Pihole -->|"Проверка:<br>реклама? → блок<br>нет? → спрашиваем Unbound"| Unbound

    Unbound -->|"Безопасный запрос<br>в интернет"| Internet[Интернет]

    Internet -->|"Чистый ответ"| Unbound
    Unbound -->|"Безопасный ответ"| Pihole
    Pihole -->|"Очищенный от рекламы"| Devices

    style Router fill:#ffecb3
    style Devices fill:#e1f5fe
    style Pihole fill:#f3e5f5
    style Unbound fill:#e8f5e8
    style Internet fill:#fff3e0
    

Как это работает:

  1. Настройка (1 раз):

    • Роутер назначает Pi-hole в качестве DNS-сервера для всех устройств

    • Все устройства автоматически начинают использовать Pi-hole

  2. Когда вы заходите на сайт:

    • Устройство спрашивает у Pi-hole: «Где находится определенный сайт?»

    • Pi-hole проверяет: если это реклама → блокирует, если нет → спрашивает Unbound

    • Unbound напрямую обращается к корневым DNS-серверам в интернете

    • Получает «чистый» ответ без посредников

    • Ответ возвращается к вашему устройству

  3. Что это дает:

    • Блокировка рекламы на всех устройствах

    • Безопасность: Unbound не использует сторонние DNS-серверы

    • Конфиденциальность: ваши запросы не идут к Google/Cloudflare

    • Скорость: кэширование часто запрашиваемых сайтов

Создадим необходимые файлы для работы:

# Создаем папки и файлы
mkdir {dns,dns/config_pihole,dns/config_unbound}
cd dns
touch {docker-compose.yml,.env,config_unbound/a-records.conf,config_unbound/srv-records.conf,config_unbound/forward-records.conf}

cat > .env << 'EOF'
PIHOLE_PASSWORD=<your_secret_password>
EOF

cat > config_unbound/unbound.conf << 'EOF'
server:
    verbosity: 1
    interface: 0.0.0.0@53
    access-control: 0.0.0.0/0 allow
    do-ip4: yes
    do-udp: yes
    do-tcp: yes
    hide-identity: yes
    hide-version: yes
    prefetch: yes
    prefetch-key: yes
    num-threads: 2
    so-reuseport: yes
EOF

Редактируем systemd-resolved, чтобы 53 порт был у нас не занят и мы могли управлять DNS-запросами через наши сервисы:

# Открываем для редактирования конфиг systemd-resolved
$ sudo nano /etc/systemd/resolved.conf
# Вставляем/заменяем (пункт должен быть раскомментирован)
DNSStubListener=no

Перезапускаем и проверяем systemd-resolved:

# Перезапускаем службу
sudo systemctl restart systemd-resolved
# Проверяем
sudo ss -tulpn | grep :53

Редактируем docker-compose.yml через nano docker-compose.yml:

services:
  unbound:
    container_name: unbound
    image: mvance/unbound:latest
    restart: unless-stopped
    volumes:
      - './config_unbound:/opt/unbound/etc/unbound/'
    networks:
      dns:

  pihole-init:
    image: pihole/pihole:latest
    container_name: pihole_init
    volumes:
      - './config_pihole:/etc/pihole'
    environment:
      - TZ=Europe/Moscow
      - FTLCONF_webserver_api_password=${PIHOLE_PASSWORD}
      - FTLCONF_dns_listeningMode=ALL
      - FTLCONF_dns_upstreams=8.8.8.8;1.1.1.1
    dns:
      - 8.8.8.8
      - 1.1.1.1
    command: >
      sh -c "
      if [ ! -f /etc/pihole/gravity.db ]; then
        echo 'Создаём базу данных с публичными DNS...';
        # Запускаем создание базы данных
        pihole-FTL &
        sleep 5
        pihole updateGravity
        sleep 30
        pkill pihole-FTL
        echo 'База создана!';
      else
        echo 'База уже существует, пропускаем инициализацию';
      fi
      "
    restart: "no"  # Запускаем только один раз
    networks:
      dns:

  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "280:80/tcp"
    environment:
      - TZ=Europe/Moscow
      - FTLCONF_webserver_api_password=${PIHOLE_PASSWORD}
      - FTLCONF_dns_listeningMode=ALL
      - FTLCONF_dns_upstreams=unbound
    volumes:
      - './config_pihole:/etc/pihole/'
    cap_add:
      - NET_ADMIN
      - SYS_NICE
    env_file:
      - ".env"
    restart: unless-stopped
    networks:
      dns:
    depends_on:
      - unbound
      - pihole-init

networks:
  dns:
    driver: bridge

Перед запуском создаем сеть:

docker network create dns

# Проверить создание
# docker network ls

Сервис pihole-init нужен для первого запуска и я не нашел как запустить иначе. После запуска его можно остановить docker stop pihole-init.

После запуска в UI Pi-hole мы можем попасть по адресу: http://<your_ip>:280/admin. Вводим пароль, который мы указали в файле c секретами выше. В самом начале никакой статистики мы не будем видеть, так как на пути устройств в Интернет ничего не изменилось. Исправлять этот момент будем на следующем этапе.

Настройки роутера

  1. Заходим в интерфейс роутера, обычно это 192.168.0.1.

  2. Авторизируемся.

  3. Делаем бэкап настроек роутера на всякий случай 😆.

  4. Находим настройку, которая отвечает за DNS. В моем TP Link Archer A6 v2.0: Дополнительные настройки -> Сеть -> Дополнительные настройки. В окнах с «Предпочитаемый DNS-сервер»и «Альтернативный DNS-сервер» указываем IP VM или ПК, где развернуты наши сервисы.

  5. Перезагружаем роутер. Теперь должны увидеть статистику, которая постоянно изменяется, так как наши устройства постоянно делают запросы через наш роутер.

Проверка работы сервисов

Проверка запросов:

# Первый запрос (должен быть медленнее, >50 мс)
$ docker exec pihole dig @127.0.0.1 stackoverflow.com | grep -E "Query time|IN.*A"
# Сразу же второй запрос (должен быть быстрее, <5 мс
$ docker exec pihole dig @127.0.0.1 stackoverflow.com | grep -E "Query time|IN.*A"
;stackoverflow.com.             IN      A
stackoverflow.com.      300     IN      A       198.252.206.1
;; Query time: 20 msec
;stackoverflow.com.             IN      A
stackoverflow.com.      300     IN      A       198.252.206.1
;; Query time: 1 msec

Видим косвенное подтверждение работы: первый запрос выполнился, а затем сработал кэш Unbound.

Проверка перенаправления unbound:

$ docker exec pihole tail -f /var/log/pihole/pihole.log | grep "forwarded"
Dec 19 13:50:53 dnsmasq[55]: forwarded open.selezen.org to 172.20.0.3
Dec 19 13:50:53 dnsmasq[55]: forwarded open.selezen.org to 172.20.0.3

Должный увидеть вывод как в примере выше, который говорит о работе Unbound. 172.20.0.3 - это IP нашего контейнера Unbound.

Умный дом

Чтобы видеть всю статистику в 1 месте устанавливаем:

  1. Интеграция Pi-hole.

  2. Карточка Pi-hole из HACS. Теперь можем видеть в 1 месте статистику Pi-hole:

Мои наблюдения

До 2022 г.:

  1. До 30% трафика блокировалось.

  2. Устройство с самым большим количеством заблокированных DNS-запросов была умная колонка с Алисой.

Ничего этим не хочу сказать, просто наблюдения.

Итог

На всех наших устройствах фильтруется реклама на уровне DNS-запросов.

Ссылки:

  1. Зачем нужен собственный сервер в 2025?

  2. Как установить Proxmox?