Что это и кому надо?
Что есть DNS я в данном посте описывать не буду. Нет смысла. Если вы не в курсе (и зачем-то сюда зашли), то просто доверьтесь своему интернет-провайдеру - он за вас уже все настроил. Для тех, кто уже понимает что это такое и имеет немного времени и чуть-чуть навыков, а также небольшой сервер в локальной сети (любой raspberry-pi подобный одноплатник подойдет) посвящается.
Краткое лирическое отступление:
Пару дней назад в инфополе пролетел внезапный скандал по поводу того, что Apple нас слушает. Никакого секрета тут конечно же нет, но если вы думаете, что кроме голосового помощника вас никто не слушает и никакие данные не отправляет, то вы таки сильно ошибаетесь. И проблема далеко не только и не столько в том, что телефон “слушает”. Телефон также отслеживает все, что вы написали (непосредственно с клавиатуры), а также конечно же все ваши поисковые и прочие запросы. Верующим в приватную приватность Apple или независимую независимость Android отдельный привет
Итак, мы по какой-то неведомой причине решили поднять локальный DNS-сервер и не доверять свои DNS запросы провайдеру. В идеале хочется еще и видеть статистику и блокировать часть рекламы, трекеров и прочей пакости. Почему часть? Потому что далеко не вся реклама и трекеры располагаются на каких-то отдельных доменах, а посему на уровне DNS заблокировать вообще все не получится. Но, как мы сможем убедиться дальше, даже на уровне DNS можно отсечь более чем внушительное количество ненужного нам.
Какие у нас есть варианты? Недолгое копание на реддите подсказывает, что есть:
Автор выбрал Pi-hole по трем причинам:
- Проект давно разрабатывается и он более чем стабилен
- Проект разрабатывается с виду независимыми разработчиками (по крайней мере в явном виде не аффилированными к компаниям)
- Под этот проект есть куча гайдов и самое главное - готовых adblock листов доменов
Также, Pi-hole может выступать как DHCP сервер, но это уже для тех, кто делает самосборный роутер на коленке.
Уверен, что и adguard и technitium предлагают хороший продукт, но я решил выбрать Pi-hole.
Что потребуется?
Что по железу?
Теоретически pi-hole поднимается и на роутере. Однако практика показывает, что пара десятков листов на 1600000 доменов уже заставляют pi-hole отожрать что-то около 250мб памяти, если верить docker stats
. Роутеров с более солидным количеством набортной памяти в продаже достаточно, но лично мой имеет всего 128мб и его ресурсов просто не хватит. Также, pihole требует немного диска, но и с этим на роутерах как правило все крайне тесно.
Однако я имею в локальной сети сервер-NAS и у него 16 гигабайт памяти и уж точно достаточным количеством диска, а значит есть где разгуляться. Технически хватит и какого-нибудь raspberry pi не первой свежести или как вариант VPS где-нибудь не слишком далеко. Однако в случае с VPS придется озаботиться настройкой VPN до сервера, если мы не хотим демонстрировать dns запросы провайдеру в открытом виде. Ниже банальный tcpdump, который в случае отправки запросов с вашего роутера на публичные DNS-серверы можно посадить на любом промежуточном хопе и наблюдать как вы ходите на pornhube (конечно же для чтения увлекательной статистики в их блоге!):
tcpdump: data link type LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
12:50:48.890918 enxc84d44260322 Out IP (tos 0x0, ttl 64, id 17163, offset 0, flags [none], proto UDP (17), length 83)
192.168.3.140.47164 > 1.1.1.1.53: [bad udp cksum 0xc686 -> 0x2010!] 32326+ [1au] A? cloudflare.com. ar: . OPT UDPsize=1232 [COOKIE 15b2fc7b14529960] (55)
12:50:48.903036 enxc84d44260322 In IP (tos 0x0, ttl 55, id 48896, offset 0, flags [DF], proto UDP (17), length 103)
1.1.1.1.53 > 192.168.3.140.47164: [udp sum ok] 32326$ q: A? cloudflare.com. 2/0/1 cloudflare.com. [39s] A 104.16.132.229, cloudflare.com. [39s] A 104.16.133.229 ar: . OPT UDPsize=1232 (75)
Что по софту?
docker и compose к нему, а также опционально настроим проксирование вебморды через traefik (но это опционально и только потому, что я уже поднял траефик для ряда других ресурсов на NAS). Теоретически docker конечно имеет накладные расходы, практически же основной оверхед это диск, а диска у меня на сервере много.
Т.к. pi-hole, по понятным причинам, проксирующий dns-сервер ему необходим upstream куда он будет перенаправлять запросы. В общем случае апстримы настраиваются в админке, однако разработчики pi-hole на данный момент не озаботились встроенной поддержкой DNS-over-HTTPS или DNS-over-TLS, а значит придется поднять side-car контейнер со своим сервером DoH. Самый простой и рабочий способ поднять рядом cloudflared, который умеет работать как proxy-dns и отправлять запросы через DoH. DoH нам в данном случае нужен для того, чтобы DNS-запросы в открытом виде не уходили дальше локальной домашней сети.
Что делать?
Первично для поднятия достаточно простого docker-compose.yml:
version: '3.4'
services:
pihole:
container_name: pihole
domainname: docker
hostname: pihole
image: pihole/pihole:2024.07.0
ports:
- 53:53/tcp
- 53:53/udp
environment:
TZ: 'Europe/Moscow'
volumes:
- './pihole:/etc/pihole/'
- './pihole/dnsmasq:/etc/dnsmasq.d/'
dns:
- 1.1.1.1
- 8.8.8.8
networks:
- web
labels:
# Для веб-интерфейса pihole
- "traefik.http.routers.pihole.rule=Host(`pihole.2k600.com`)"
- "traefik.http.routers.pihole.entrypoints=websecure"
- "traefik.http.routers.pihole.tls=true"
- "traefik.http.routers.pihole.service=pihole"
- "traefik.http.routers.pihole.tls.certresolver=myresolver"
- "traefik.http.services.pihole.loadbalancer.server.port=80"
restart: always
cloudflared:
container_name: cloudflared
image: cloudflare/cloudflared:2024.11.1
restart: always
command: proxy-dns
# See the list of environment variables at https://github.com/cloudflare/cloudflared/blob/master/cmd/cloudflared/proxydns/cmd.go
environment:
TUNNEL_DNS_UPSTREAM: "https://1.0.0.1/dns-query,https://1.1.1.1/dns-query,https://8888.google/dns-query,https://doh.opendns.com/dns-query"
TUNNEL_DNS_PORT: 5053
TUNNEL_DNS_ADDRESS: "0.0.0.0"
TZ: 'Europe/Moscow'
labels:
- "traefik.enable=false"
networks:
web:
ipv4_address: "172.26.0.7"
dns:
- 1.1.1.1
- 8.8.8.8
networks:
web:
external: true
Прежде чем побежим дальше несколько комментариев:
web
network это в данном случае docker-network в котором у меня работает traefik, по сути может и не быть external, но сеть создать придется.ports
не знаю все ли были в курсе, но DNS работает не только по udp, но и по tcp, также, крайне желательно указать конкретный IP NAS (особенно, если у вас их больше одного), на котором pi-hole будет отдавать DNS.ipv4_address: "172.26.0.7"
вот тут прямо важно и опциональности никакой нет. Контейнеру c cloudflared необходимо задать какой-то статический IP внутри docker network, потом он пригодиться, когда будем направлять upstream внутри интерфейса pihole.TUNNEL_DNS_UPSTREAM
тут мы через запятую перечисляем куда хотим отправлять DoH запросы с cloudflaredTUNNEL_DNS_PORT
иTUNNEL_DNS_ADDRESS
это порт и адрем DNS cloudflared. В нашем случае необходимости делать их кастомными нет, но сам факт возможности задать их через env радует- labels traefik необходимы для проксирования веб-морды, но они опциональны. Если нет trefik и лень с ним заморачиваться просто уберите эти labels, а в ports добавьте
80:8080
и админка станет доступна на порте 8080.
Вариант без traefik:
version: '3.4'
services:
pihole:
container_name: pihole
domainname: docker
hostname: pihole
image: pihole/pihole:2024.07.0
ports:
- 53:53/tcp
- 53:53/udp
- 80:8080
environment:
TZ: 'Europe/Moscow'
volumes:
- './pihole:/etc/pihole/'
- './pihole/dnsmasq:/etc/dnsmasq.d/'
dns:
- 1.1.1.1
- 8.8.8.8
networks:
- web
restart: always
cloudflared:
container_name: cloudflared
image: cloudflare/cloudflared:2024.11.1
restart: always
command: proxy-dns
# See the list of environment variables at https://github.com/cloudflare/cloudflared/blob/master/cmd/cloudflared/proxydns/cmd.go
environment:
TUNNEL_DNS_UPSTREAM: "https://1.0.0.1/dns-query,https://1.1.1.1/dns-query,https://8888.google/dns-query,https://doh.opendns.com/dns-query"
TUNNEL_DNS_PORT: 5053
TUNNEL_DNS_ADDRESS: "0.0.0.0"
TZ: 'Europe/Moscow'
networks:
web:
ipv4_address: "172.26.0.7"
dns:
- 1.1.1.1
- 8.8.8.8
networks:
web:
driver: bridge
ipam:
config:
- subnet: 172.26.0.0/16
Дальше все стандартно - docker-compose up -d
и все полетит.
Настройка pi-hole
Задаем пароль от админки pi-hole
docker exec -it pihole bash
pihole -a -p
Настраиваем upstream-ы
- Заходим в веб-морду (внимание, все настраивается через
/admin
напримерhttp://192.168.1.8:8080/admin
где192.168.1.8
это IP вашего сервера) и вводим пароль. - Идем в Settings/DNS и настраиваем все аналогично картинке ниже:
Настраиваем Adlists
По умолчанию pi-hole поставляется с одним листом доменов и почти ничего не блокирует. Основных форматов 2: непосредственно для pi-hole, а также для adguard. Все что нужно знать - pihole всеяден и готов есть и то и другое. Листов в интернете великое множество, но есть подборка крайне годных списков, которые уже рассортированы по качеству и назначению. Добавляются они внутри интерфейса pi-hole на вкладке Adlist (почти уверен, что их можно как-то настроить через ENV, но это перебор как по мне). Рекомендую использовать “влоб”, те, что отмечены зеленым.
Из листов “общего назначения” от себя я также хотел бы добавить:
- https://adguardteam.github.io/HostlistsRegistry/assets/filter_27.txt
- https://blocklistproject.github.io/Lists/tracking.txt
- https://blocklistproject.github.io/Lists/ads.txt
Отдельного упоминания достойны:
- лист жести тут автор явно из наших резких и дерзких и умудрился засунуть в blacklist даже yandex.ru. При всей суровости этого листа ему можно найти применение, если не использовать его как дефолт
- xiaomi лист - это лист с мусорными доменами, к которым пытаются ходить девайсы xiaomi/poco и прочих суббрендов великолепной компании имени рисового зернышка
- smart-tv лист - лист с доменами к которым ходят разного рода “умные” телевизоры
Чуть более тонкая настройка
У pi-hole есть возможность настроить группы девайсов, которые находятся в сети. По умолчанию все девайсы попадают в группу Default. Девайс можно зарегистрировать внутри pi-hole (по IP или mac-адресу) и назначить ему группу (или несколько групп). Листы можно применять к группам и вся эта машинерия позволяет нам более гибко применять списки и назначить отдельным девайсам отдельные листы. Что не может не радовать. Например в моем случае лист жести, xiaomi лист и smart-tv лист назначены телевизорам в локальной сети, а для телефона автора применены Default и xiaomi лист.
Тут уже все зависит от вашей фантазии.
Настройка роутера
Естественно, не забываем настроить на роутере (или непосредственно на конкретных девайсах) хождение за DNS на наш pi-hole (иначе зачем все это?). Как конкретно настравать на каждом роутере сказать не могу. Тут каждый выкручивается сам. В keenetic это делается через профили DNS. В mikrotik традиционно через жопу.
Итоги
А результат на табло
42% запросов DNS были заблокированы за последние сутки у меня в локальной домашней сети. Хочу заметить, что заблокированы они были безо всякой потери для работоспособности (ну если не считать пропавшую частично рекламу).
Больше всего заблокированных доменов от телевизоров и в топе, как можно заметить, вовсе не реклама. Выводы делайте сами, однако я уже врядли захочу выпускать DNS-запросы из локальной сети просто так.