VPN шифрует трафик и скрывает IP-адрес, но DNS-запросы часто остаются слабым звеном. Если клиент отправляет их напрямую провайдеру или публичному резолверу, наблюдатель видит полный список доменов, которые вы посещаете, даже не расшифровывая сам трафик DNS leak: как VPN может скрыть IP, но выдать DNS-запросы, и как это проверить. Решение — поднять собственный рекурсивный или фильтрующий DNS-сервер на VPN-узле и направлять все запросы исключительно через туннель.
Типичная ситуация: клиент подключается к WireGuard, трафик идёт через туннель, но системный резолвер по-прежнему указывает на DNS провайдера или на 8.8.8.8. Провайдер видит plaintext-запросы и сопоставляет их с временными метками подключения. Это называется DNS leak DNS leak: как VPN может скрыть IP, но выдать DNS-запросы, и как это проверить.
Причины утечек:
Целевая схема:
Клиент отправляет DNS-запросы на адрес VPN-сервера внутри туннеля (например, 10.10.0.1). На сервере запросы обрабатывает локальный резолвер, который выполняет рекурсию самостоятельно или фильтрует через списки блокировок. Внешний наблюдатель видит только зашифрованный UDP-трафик WireGuard и не может определить, какие домены запрашиваются Что видит интернет-провайдер при использовании VPN: метаданные, DNS и границы приватности.
Unbound выполняет полную рекурсию: от корневых серверов до авторитативных, не передавая запросы промежуточным резолверам вроде 8.8.8.8 или 1.1.1.1. Это означает, что ни один сторонний сервис не видит ваши запросы.
Здесь нет
AdGuard Home — DNS-сервер с встроенной фильтрацией рекламы, трекеров и вредоносных доменов. В отличие от Unbound, он не выполняет рекурсию самостоятельно, а перенаправляет запросы на вышестоящие серверы. Приватность здесь достигается за счёт того, что запросы не уходят к провайдеру, а фильтрация происходит локально.
После установки AdGuard Home доступен на
Распространённая схема: AdGuard Home слушает порт 53 и фильтрует запросы, а для «чистых» запросов перенаправляет их на Unbound, работающий на порту 8053 того же хоста. Это даёт и фильтрацию, и полную рекурсию без сторонних серверов.
В настройках AdGuard Home в поле «Вышестоящие DNS-серверы» указывают
Конфигурация Unbound для этой связки отличается от самостоятельной рекурсии:
Здесь Unbound слушает только loopback на порту 8053, чтобы не конфликтовать с AdGuard Home на порту 53. Параметр
На стороне клиента в конфигурации WireGuard нужно убедиться, что DNS-запросы идут через туннель. В файле конфигурации клиента:
Директива
На сервере в конфигурации WireGuard:
WireGuard ассоциирует туннельные IP-адреса с публичными ключами. Когда сервер получает пакет от клиента, он проверяет, что source IP соответствует
NetworkManager может перезаписать DNS при подключении туннеля. Чтобы этого не произошло:
Дополнительная защита — запретить исходящие DNS-запросы мимо туннеля через iptables:
Это гарантирует, что даже если приложение проигнорирует системный резолвер, запрос не уйдёт напрямую. Правила применяются немедленно и действуют до перезагрузки; для постоянства их сохраняют через
Если IPv6 не маршрутизируется через туннель, DNS-запросы по AAAA-записям могут уходить в обход. Варианты:
После настройки нужно убедиться, что DNS-запросы действительно идут через туннель:
Если в логе видны запросы с IP клиента из туннеля — всё работает. Если запросов нет, а сайты открываются — DNS уходит в обход.
Почему DNS ломает приватность VPN
Типичная ситуация: клиент подключается к WireGuard, трафик идёт через туннель, но системный резолвер по-прежнему указывает на DNS провайдера или на 8.8.8.8. Провайдер видит plaintext-запросы и сопоставляет их с временными метками подключения. Это называется DNS leak DNS leak: как VPN может скрыть IP, но выдать DNS-запросы, и как это проверить.
Причины утечек:
- Сетевой менеджер не переназначает DNS при поднятии туннеля VPN-клиент на Linux: как NetworkManager управляет маршрутами и DNS при подключении туннеля.
- В конфигурации VPN не указан
DNS = ...для интерфейса.
- Приложения используют hardcoded-резолверы, игнорируя системные настройки.
- IPv6-запросы уходят в обход туннеля, если IPv6 не маршрутизируется через VPN.
Архитектура: VPN-узел как DNS-сервер
Целевая схема:
Код:
Клиент ──WireGuard──▶ VPN-сервер ──▶ Unbound / AdGuard Home ──▶ корневые серверы
(wg0) (127.0.0.1:53)
Клиент отправляет DNS-запросы на адрес VPN-сервера внутри туннеля (например, 10.10.0.1). На сервере запросы обрабатывает локальный резолвер, который выполняет рекурсию самостоятельно или фильтрует через списки блокировок. Внешний наблюдатель видит только зашифрованный UDP-трафик WireGuard и не может определить, какие домены запрашиваются Что видит интернет-провайдер при использовании VPN: метаданные, DNS и границы приватности.
Unbound: рекурсивный резолвер без логирования
Unbound выполняет полную рекурсию: от корневых серверов до авторитативных, не передавая запросы промежуточным резолверам вроде 8.8.8.8 или 1.1.1.1. Это означает, что ни один сторонний сервис не видит ваши запросы.
Конфигурация для самостоятельной рекурсии
YAML:
server:
interface: 10.10.0.1
port: 53
access-control: 10.10.0.0/24 allow
hide-identity: yes
hide-version: yes
qname-minimisation: yes
private-address: 10.0.0.0/8
private-address: 192.168.0.0/16
Здесь нет
forward-zone — Unbound сам выполняет рекурсию от корневых серверов. Параметр interface: 10.10.0.1 привязывает резолвер к адресу WireGuard-интерфейса, поэтому сервис должен запускаться после поднятия туннеля. В systemd это решается через [email protected] в unit-файле или через ExecStartPre с проверкой доступности адреса.Ключевые параметры приватности
| Параметр | Назначение |
|---|---|
qname-minimisation: yes | Отправляет минимально необходимое имя в запросе к вышестоящим серверам |
hide-identity: yes | Не раскрывает hostname сервера в ответах |
hide-version: yes | Не раскрывает версию Unbound |
access-control | Ограничивает, какие клиенты могут отправлять запросы |
Установка и запуск
Bash:
## Debian/Ubuntu
sudo apt install unbound
sudo systemctl enable --now unbound
## Проверка конфигурации
unbound-checkconf
## Проверка, что резолвер отвечает
dig @10.10.0.1 example.com
AdGuard Home: фильтрация и приватность в одном сервисе
AdGuard Home — DNS-сервер с встроенной фильтрацией рекламы, трекеров и вредоносных доменов. В отличие от Unbound, он не выполняет рекурсию самостоятельно, а перенаправляет запросы на вышестоящие серверы. Приватность здесь достигается за счёт того, что запросы не уходят к провайдеру, а фильтрация происходит локально.
Конфигурация через веб-интерфейс
После установки AdGuard Home доступен на
http://<адрес_сервера>:3000 для первоначальной настройки. В интерфейсе задаются:- Адрес и порт прослушивания (например, 10.10.0.1:53).
- Вышестоящие DNS-серверы. Для максимальной приватности выбирают резолверы с поддержкой DoH/DoT: Cloudflare, Quad9, NextDNS или собственный Unbound на том же хосте.
- Списки фильтрации (EasyList, AdGuard DNS filter и др.).
Связка AdGuard Home + Unbound
Распространённая схема: AdGuard Home слушает порт 53 и фильтрует запросы, а для «чистых» запросов перенаправляет их на Unbound, работающий на порту 8053 того же хоста. Это даёт и фильтрацию, и полную рекурсию без сторонних серверов.
Код:
Клиент ──▶ AdGuard Home (:53) ──фильтрация──▶ Unbound (:8053) ──▶ корневые серверы
В настройках AdGuard Home в поле «Вышестоящие DNS-серверы» указывают
127.0.0.1:8053.Конфигурация Unbound для этой связки отличается от самостоятельной рекурсии:
YAML:
server:
interface: 127.0.0.1
port: 8053
access-control: 127.0.0.0/8 allow
hide-identity: yes
hide-version: yes
qname-minimisation: yes
Здесь Unbound слушает только loopback на порту 8053, чтобы не конфликтовать с AdGuard Home на порту 53. Параметр
do-not-query-localhost по умолчанию равен yes, но в этой схеме он не влияет на работу, поскольку Unbound не пересылает запросы на localhost — он сам является конечной точкой рекурсии.Настройка WireGuard для маршрутизации DNS
На стороне клиента в конфигурации WireGuard нужно убедиться, что DNS-запросы идут через туннель. В файле конфигурации клиента:
INI:
[Interface]
PrivateKey = <ключ_клиента>
Address = 10.10.0.2/24
DNS = 10.10.0.1
[Peer]
PublicKey = <ключ_сервера>
Endpoint = <публичный_IP_сервера>:51820
AllowedIPs = 0.0.0.0/0
Директива
DNS = 10.10.0.1 указывает клиенту использовать адрес сервера внутри туннеля как резолвер. AllowedIPs = 0.0.0.0/0 маршрутизирует весь трафик, включая DNS, через туннель VPN-клиент на Linux: как NetworkManager управляет маршрутами и DNS при подключении туннеля.На сервере в конфигурации WireGuard:
INI:
[Interface]
PrivateKey = <ключ_сервера>
Address = 10.10.0.1/24
ListenPort = 51820
[Peer]
PublicKey = <ключ_клиента>
AllowedIPs = 10.10.0.2/32
WireGuard ассоциирует туннельные IP-адреса с публичными ключами. Когда сервер получает пакет от клиента, он проверяет, что source IP соответствует
AllowedIPs этого пира. Это обеспечивает криптографическую привязку маршрутизации к идентичности Собственный VPN-сервер против коммерческого провайдера: реальные границы приватности.Предотвращение утечек на клиенте
Linux с NetworkManager
NetworkManager может перезаписать DNS при подключении туннеля. Чтобы этого не произошло:
Bash:
## Проверить текущие DNS
resolvectl status
## Убедиться, что для интерфейса wg0 назначен нужный сервер
resolvectl dns wg0 10.10.0.1
resolvectl domain wg0 "~."
domain "~." означает, что все домены маршрутизируются через этот интерфейс VPN-клиент на Linux: как NetworkManager управляет маршрутами и DNS при подключении туннеля.Блокировка DNS в обход туннеля
Дополнительная защита — запретить исходящие DNS-запросы мимо туннеля через iptables:
Bash:
## Запретить UDP/53 мимо интерфейса wg0
sudo iptables -A OUTPUT -p udp --dport 53 ! -o wg0 -j REJECT
sudo iptables -A OUTPUT -p tcp --dport 53 ! -o wg0 -j REJECT
Это гарантирует, что даже если приложение проигнорирует системный резолвер, запрос не уйдёт напрямую. Правила применяются немедленно и действуют до перезагрузки; для постоянства их сохраняют через
iptables-save или переносят в nftables.IPv6
Если IPv6 не маршрутизируется через туннель, DNS-запросы по AAAA-записям могут уходить в обход. Варианты:
- Маршрутизировать IPv6 через WireGuard (добавить IPv6-адрес в
AllowedIPs).
- Отключить IPv6 на клиенте, если он не нужен.
- Убедиться, что резолвер не слушает IPv6 вне туннеля.
Проверка отсутствия утечек
После настройки нужно убедиться, что DNS-запросы действительно идут через туннель:
- dnsleaktest.com — показывает, какие резолверы обрабатывают запросы. В списке должен быть только IP вашего VPN-сервера.
- browserleaks.com/dns — аналогичная проверка с дополнительными деталями.
- Локальная проверка — на сервере включить логирование Unbound и убедиться, что запросы приходят:
YAML:
## В unbound.conf добавить в секцию server:
log-queries: yes
logfile: /var/log/unbound.log
Bash:
sudo systemctl restart unbound
tail -f /var/log/unbound.log
Если в логе видны запросы с IP клиента из туннеля — всё работает. Если запросов нет, а сайты открываются — DNS уходит в обход.
Ограничения и нюансы
- Скорость рекурсии. Unbound при первом запросе домена выполняет полную цепочку от корневых серверов. Это медленнее, чем обращение к кэширующему резолверу. Кэш смягчает проблему, но первый запрос к новому домену занимает 50–200 мс.
- Ресурсы VPS. Полная рекурсия нагружает CPU и память при большом числе клиентов. Для одного-двух пользователей достаточно минимального VPS.
- DNSSEC. Unbound поддерживает валидацию DNSSEC из коробки. AdGuard Home передаёт DNSSEC-ответы, но сам не валидирует их — валидация происходит на стороне Unbound, если он стоит ниже по цепочке.
- DoH/DoT на клиенте. Если клиент использует DoH (например, Firefox), запросы идут поверх HTTPS и не перехватываются правилом iptables на порт 53. В этом случае нужно либо отключить DoH в браузере, либо направить его на собственный DoH-endpoint.
- Локальные домены. Если в сети есть внутренние имена (
.local,.internal), их нужно добавить вlocal-zoneUnbound или в правила AdGuard Home, иначе рекурсия уйдёт наружу.
- Порядок запуска сервисов. Если Unbound привязан к адресу WireGuard-интерфейса, он не сможет запуститься до поднятия туннеля. В systemd-юните добавляют зависимость
[email protected]и[email protected], либо используютinterface: 0.0.0.0с ограничением черезaccess-control.
Итоговая проверка развёртывания
| Шаг | Что проверить |
|---|---|
| WireGuard поднят | wg show отображает интерфейс и пиров |
| DNS назначен клиенту | resolvectl status показывает 10.10.0.1 для wg0 |
| Unbound/AdGuard Home слушает | ss -ulnp | grep :53 на сервере |
| Запросы доходят | Лог Unbound содержит записи |
| Утечек нет | dnsleaktest.com показывает только IP сервера |
| Обход заблокирован | dig @8.8.8.8 example.com с клиента не проходит |
| IPv6 не утекает | dig AAAA example.com идёт через туннель или отключён |
