Не работает DNS через WireGuard: как исправить
Туннель активен, но сайты не открываются или запросы идут мимо VPN? Разберитесь в трех причинах сбоев DNS в WireGuard, включая конфликты resolvconf и ошибки маршрутизации.
Почему DNS перестает работать сразу после поднятия туннеля WireGuard
Проблемы с DNS поверх WireGuard возникают по трем причинам, и для каждой есть свое решение. Либо имена не разрешаются вовсе, либо запросы уходят с вашего компьютера в обход туннеля, либо системный менеджер резолверов перезаписывает настройки через несколько секунд после запуска интерфейса. Проблема почти никогда не кроется в самом туннеле. Причина — в одной строке, указывающей клиенту, какой резолвер использовать, и в маршрутизации, определяющей путь пакетов к этому резолверу.
WireGuard передает IP-пакеты и ничего не знает о DNS (системе доменных имен, сервисе, который преобразует имена, такие как example.com, в IP-адреса). Параметр DNS = в блоке [Interface] клиента не является настройкой WireGuard. Его считывает wg-quick — оболочка, которая поднимает интерфейс, а затем wg-quick изменяет конфигурацию резолвера клиента на время работы туннеля и восстанавливает её при wg-quick down. Таким образом, любая из описанных ниже проблем связана с маршрутизацией или wg-quick, но никак не с криптографией. Если туннель еще не настроен, начните с развертывания собственного VPN на базе WireGuard на вашем VPS, а затем вернитесь к этой странице.
Перед тем как менять настройки DNS, убедитесь, что туннель исправен.
sudo wg show
ping -c 3 10.8.0.1
ping -c 3 1.1.1.1wg show должен показывать пира с недавним latest handshake, и оба пинга должны проходить. Если ping 1.1.1.1 завершается по таймауту, у вас проблема с пересылкой пакетов или NAT (трансляцией сетевых адресов), а не с DNS, и никакие правки конфигурации резолвера не помогут. Если пинги проходят, но скорость падает при передаче реального трафика, это отдельная проблема, и низкая скорость WireGuard почти всегда связана с MTU, а не с чем-либо, описанным на этой странице. В каждом примере здесь 10.8.0.0/24 используется как подсеть туннеля, а 10.8.0.1 — как адрес сервера в туннеле. Подставьте свои значения.
Сбой один: ничего не разрешается, так как резолвер не отвечает
Симптом предельно ясен. ping 1.1.1.1 работает, а curl https://example.com возвращает следующее:
curl: (6) Could not resolve host: example.comЗапросите туннельный резолвер напрямую с клиента. Утилита dig входит в пакет dnsutils в Ubuntu и Debian.
dig +short @1.1.1.1 example.com
dig +short @10.8.0.1 example.comПервая команда возвращает адрес, что доказывает прохождение пакетов в интернет через туннель. Вторая не возвращает ничего и выводит ;; communication timed out; no servers could be reached. Это и есть весь диагноз: ваш клиент настроен на 10.8.0.1, а 10.8.0.1 не отвечает на UDP-порт 53.
К этому приводят две причины. Либо на сервере не запущен резолвер, либо серверный файрвол отбрасывает запрос до того, как он доходит до цели. Проверьте оба варианта на сервере.
sudo ss -ulnp | grep ':53'
sudo nft list rulesetЗапущенный и корректно привязанный резолвер показывает строку с 10.8.0.1:53 или 0.0.0.0:53. В Ubuntu сюрпризом обычно оказывается 127.0.0.53:53: это stub-слушатель systemd-resolved, который привязывается к loopback-адресу и намеренно недоступен с других машин. Настройка VPN-клиента на сервер, где единственным резолвером является этот stub, приводит именно к такому таймауту.
Решение заключается в установке резолвера, который слушает адрес туннеля, и добавлении правила файрвола, разрешающего узлам доступ к нему.
sudo apt update && sudo apt install -y unbound
printf 'server:\n interface: 10.8.0.1\n access-control: 10.8.0.0/24 allow\n' \
| sudo tee /etc/unbound/unbound.conf.d/wireguard.conf
sudo systemctl restart unbound
sudo ss -ulnp | grep '10.8.0.1:53'Затем откройте порт только для туннельного трафика. При использовании nftables добавьте эти две строки в цепочку input в файле /etc/nftables.conf и перезагрузите конфигурацию командой sudo systemctl reload nftables.
udp dport 53 iifname "wg0" accept
tcp dport 53 iifname "wg0" acceptПри использовании ufw ту же задачу выполняет sudo ufw allow in on wg0 to any port 53. Никогда не открывайте порт 53 для публичного интернета. Открытый рекурсивный резолвер обнаруживается сканерами в течение нескольких дней и используется для усиления DDoS-атак, и ваш провайдер заметит этот трафик раньше вас.
Повторно запустите dig +short @10.8.0.1 example.com с клиента. Адрес в выводе означает, что путь к резолверу работает, и теперь клиенту нужно только начать его использовать. Добавьте строку в блок [Interface] на клиенте и перезапустите интерфейс командой sudo wg-quick down wg0 && sudo wg-quick up wg0.
[Interface]
PrivateKey = <client private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1Вторая ошибка: утечки DNS из-за того, что split tunnel не направляет запросы к резолверу
Эта проблема опаснее, так как всё выглядит рабочим. Имена разрешаются, страницы загружаются, а запросы передаются в открытом виде через локальную сеть, которой вы не доверяли.
К этому приводят две конфигурации. Первая — клиент с AllowedIPs = 0.0.0.0/0, ::/0 без строки DNS =. wg-quick устанавливает маршрут по умолчанию в своей таблице маршрутизации и добавляет правило с suppress_prefixlength 0, которое намеренно сохраняет более специфичные локальные маршруты, чтобы машина могла, например, получить доступ к принтеру. Резолвер, полученный клиентом по DHCP (обычно это маршрутизатор по адресу 192.168.1.1), соответствует одному из этих локальных маршрутов. Ваш трафик идет через туннель, но локальная сеть по-прежнему получает полный список имен, которые вы запрашиваете.
Вторая причина — split tunnel: AllowedIPs = 10.8.0.0/24 с DNS = 9.9.9.9. Поскольку 9.9.9.9 находится вне AllowedIPs, у клиента нет маршрута к нему через туннель, поэтому запрос уходит через локальный интерфейс, как и в первом случае.
Проверьте, какой именно резолвер отвечает на запросы. whoami.akamai.net — это публичное тестовое имя, которое возвращает IP-адрес рекурсивного резолвера, выполнившего запрос. Вы можете сравнить этот ответ с публичным адресом вашего сервера.
resolvectl status
dig +short whoami.akamai.net
sudo tcpdump -ni any -c 10 port 53resolvectl status выводит по одному блоку для каждого сетевого интерфейса. Если в блоке для вашего Ethernet или Wi-Fi интерфейса по-прежнему указан Current DNS Server: 192.168.1.1, а в блоке wg0 пусто — это утечка. dig +short whoami.akamai.net, возвращающий адрес вашего домашнего провайдера вместо адреса вашего сервера, подтверждает это с другой стороны. Строка tcpdump — это решающее доказательство: при корректной настройке каждый пакет на 53 порт уходит через wg0, а при утечке — через wlan0 или enp3s0.
Исправление состоит из двух частей, и необходимы обе. Установите DNS на адрес, который находится внутри туннеля, и убедитесь, что этот адрес входит в AllowedIPs.
[Interface]
Address = 10.8.0.2/32
DNS = 10.8.0.1
[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 10.20.0.0/1610.8.0.1 находится внутри 10.8.0.0/24, поэтому запрос шифруется и отправляется на сервер. Если вы настаиваете на использовании публичного резолвера при split tunnel, добавьте его как хостовый маршрут: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. Пакеты будут передаваться через туннель, хотя локальная сеть всё равно сможет увидеть, что вы выбрали этого провайдера на основе предыдущих сессий. Использование собственного резолвера снимает этот вопрос.
Назначение DNS-резолвера — одно из заметных различий между WireGuard, настроенным вручную, и управляемой mesh-сетью. Это часть компромисса, описанного в сравнении WireGuard и Tailscale. Запуск самостоятельно размещённого управляющего сервера Headscale даёт такую координацию без передачи ключевого материала третьей стороне. Если вас беспокоит именно последнее, учтите: Tailscale никогда не хранит ключи, которыми шифруется ваш трафик. Поэтому точнее спросить, что скомпрометированный сервер координации или украденная учётная запись скомпрометированной идентичности смогут добавить в вашу сеть.
Сбой три: конфликт resolvconf и systemd-resolved на Linux-клиентах
Клиенты на macOS, Windows, iOS и Android применяют DNS = через официальное приложение и редко вызывают проблемы. В Linux настройка применяется с помощью shell-скрипта, который должен угадать, какой из нескольких менеджеров DNS-резолверов вы используете.
Первый сбой проявляется явно. sudo wg-quick up wg0 завершается с ошибкой:
resolvconf: command not foundwg-quick обращается к resolvconf, а этот бинарный файл не установлен. Установите реализацию, которая взаимодействует с systemd-resolved, затем снова поднимите интерфейс.
sudo apt install -y openresolv
sudo systemctl restart systemd-resolved
sudo wg-quick down wg0 && sudo wg-quick up wg0
resolvectl status wg0Второй сбой протекает скрыто, и именно он отнимает целый вечер. Интерфейс поднимается, resolvectl status wg0 корректно отображает DNS Servers: 10.8.0.1, но запросы всё равно уходят к старому резолверу. systemd-resolved хранит отдельный список резолверов для каждого линка и выбирает линк для каждого запроса. Если ни один линк не помечен как маршрут по умолчанию для имён, система продолжает использовать резолвер беспроводного соединения, так как у него есть домен поиска, а у вашего — нет.
Установите резолвер и назначьте маршрут по умолчанию одним действием. %i разворачивается в имя интерфейса, поэтому этот блок работает без изменений на любом интерфейсе.
[Interface]
Address = 10.8.0.2/32
PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~.
PostDown = resolvectl revert %iУдалите строку DNS =, когда используете PostUp таким образом, иначе два механизма будут записывать состояние резолвера, и только один из них очистит его после завершения. Аргумент ~. — это важная часть: он помечает wg0 как домен маршрутизации для всех имён, поэтому systemd-resolved отправляет все запросы туда, вместо того чтобы выбирать линк для каждого запроса. Проверьте это.
resolvectl status wg0Корректный вывод содержит DNS Servers: 10.8.0.1 и Default Route: yes. Если Default Route содержит no, значит, часть resolvectl domain не выполнилась, и вы снова вернулись к выбору линка.
Стоит упомянуть ещё один случай. Если /etc/resolv.conf является обычным файлом, а не символической ссылкой на /run/systemd/resolve/stub-resolv.conf, значит, им управляет что-то другое, обычно NetworkManager или среда выполнения контейнеров. Запустите ls -l /etc/resolv.conf перед тем, как приступать к отладке чего-либо ещё, так как инструмент, перезаписывающий этот файл при каждом изменении сети, отменит вашу работу в самый неподходящий момент.
Обновление: собственный фильтрующий резолвер через туннель
Когда запросы начинают стабильно проходить через туннель, удаленный резолвер становится точкой контроля. Запуск AdGuard Home на этом узле обеспечивает фильтрацию по спискам блокировки и журнал запросов для всех подключенных устройств без установки клиентского ПО и настройки каждого устройства в отдельности. Официальный скрипт установки, проверенный в июле 2026 года, состоит из одной строки.
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -vПри первом запуске мастер настройки ожидает подключений на порту 3000. Получите к нему доступ через туннель по адресу http://10.8.0.1:3000, вместо того чтобы открывать этот порт для публичного доступа. В мастере установите адрес прослушивания DNS и адрес панели администратора на 10.8.0.1. Если unbound из первой ошибки всё ещё занимает этот адрес, сначала остановите его командой sudo systemctl disable --now unbound, так как два процесса не могут одновременно использовать UDP порт 53 на одном адресе, и второй процесс завершится с ошибкой listen udp 10.8.0.1:53: bind: address already in use.
Клиентские конфигурации не требуют изменений, если в них уже указан адрес DNS = 10.8.0.1. Теперь в журнале запросов будут отображаться все обращения от всех узлов. Это решение в области приватности, а не просто бесплатное преимущество: вы переносите доверие со своего интернет-провайдера на себя, и теперь именно вы обязаны поддерживать актуальность обновлений безопасности на этом сервере. Сервер, доступный из Интернета, должен быть предварительно защищен базовыми настройками, которые описаны в руководстве первые десять минут на новом VPS.
FAQ
Почему мой туннель WireGuard устанавливается, но имена не разрешаются?
Туннель передает пакеты и не занимается обработкой имен, поэтому работающий туннель при неработающем разрешении имен означает, что используемый резолвер не отвечает. Проверьте это с помощью dig +short @10.8.0.1 example.com на клиенте. Ответ communication timed out означает, что либо на этом адресе туннеля не запущен резолвер (часто из-за того, что stub-резолвер systemd-resolved привязан только к 127.0.0.53), либо сетевой экран сервера блокирует UDP-порт 53, поступающий на wg0. Сначала настройте прослушивание, затем откройте порт только для wg0.
Как проверить, не происходит ли утечка DNS через WireGuard?
Запустите sudo tcpdump -ni any -c 10 port 53 на клиенте и следите за столбцом интерфейса во время просмотра веб-страниц. Каждый пакет должен проходить через wg0. Если они появляются на вашем беспроводном или Ethernet-интерфейсе, запросы уходят в открытом виде. dig +short whoami.akamai.net дает второе мнение, так как сервис отвечает публичным адресом того рекурсивного резолвера, который отправил запрос. Ответ, отличный от адреса вашего сервера, подтверждает утечку.
Нужна ли мне строка DNS =, если я использую split tunnel?
Да, и адрес резолвера также должен находиться внутри AllowedIPs, иначе у клиента не будет маршрута к нему. При AllowedIPs = 10.8.0.0/24 резолвер на 10.8.0.1 охвачен правилом, и запрос передается в зашифрованном виде. Публичный резолвер, такой как 9.9.9.9, не охвачен, поэтому запрос уходит через локальное соединение, даже если строка DNS выглядит корректно.
Почему resolvectl показывает правильный сервер, но запросы уходят в другое место?
systemd-resolved хранит список резолверов для каждого соединения и выбирает соединение для каждого запроса, поэтому корректная запись в wg0 игнорируется, если другое соединение имеет маршрут по умолчанию для имен. Добавьте PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. в блок [Interface] на клиенте и удалите строку DNS =. После этого resolvectl status wg0 должен показывать Default Route: yes.
Какой клиент исправлять первым, если не работают несколько?
Исправьте один Linux-клиент, так как это единственная платформа, которая показывает механизм работы. resolvectl status и tcpdump покажут вам, какой резолвер ответил и какой интерфейс передал пакет. Мобильные и десктопные приложения применяют те же значения DNS и AllowedIPs без видимых настроек, поэтому, настроив Linux-клиент, вы просто скопируете уже проверенную конфигурацию.