Как запустить фильтр для рекламы?
Что происходит в обычном сценарии подключения к интернету в домашней сети?
Этапы:
Получение настроек: Устройства получают от роутера адрес DNS-сервера
Использование публичного DNS: Обычно это DNS провайдера, Google (8.8.8.8) или Cloudflare (1.1.1.1)
Отправка всех запросов: Все DNS-запросы уходят на внешний сервер
Получение ответов: Ответы приходят напрямую к устройствам
Проблемы этой схемы:
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 раз):
Роутер назначает Pi-hole в качестве DNS-сервера для всех устройств
Все устройства автоматически начинают использовать Pi-hole
Когда вы заходите на сайт:
Устройство спрашивает у Pi-hole: «Где находится определенный сайт?»
Pi-hole проверяет: если это реклама → блокирует, если нет → спрашивает Unbound
Unbound напрямую обращается к корневым DNS-серверам в интернете
Получает «чистый» ответ без посредников
Ответ возвращается к вашему устройству
Что это дает:
✅ Блокировка рекламы на всех устройствах
✅ Безопасность: 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 секретами выше. В самом начале никакой статистики мы не будем видеть, так как на пути устройств в Интернет ничего не изменилось. Исправлять этот момент будем на следующем этапе.
Настройки роутера
Заходим в интерфейс роутера, обычно это 192.168.0.1.
Авторизируемся.
Делаем бэкап настроек роутера на всякий случай 😆.
Находим настройку, которая отвечает за DNS. В моем TP Link Archer A6 v2.0: Дополнительные настройки -> Сеть -> Дополнительные настройки. В окнах с «Предпочитаемый DNS-сервер»и «Альтернативный DNS-сервер» указываем IP VM или ПК, где развернуты наши сервисы.
Перезагружаем роутер. Теперь должны увидеть статистику, которая постоянно изменяется, так как наши устройства постоянно делают запросы через наш роутер.
Проверка работы сервисов
Проверка запросов:
# Первый запрос (должен быть медленнее, >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 месте устанавливаем:
Карточка Pi-hole из HACS. Теперь можем видеть в 1 месте статистику Pi-hole:
Мои наблюдения
До 2022 г.:
До 30% трафика блокировалось.
Устройство с самым большим количеством заблокированных DNS-запросов была умная колонка с Алисой.
Ничего этим не хочу сказать, просто наблюдения.
Итог
На всех наших устройствах фильтруется реклама на уровне DNS-запросов.
Ссылки: