DNS через WireGuard не работает: 3 причины и решения
Разберите три сбоя DNS в WireGuard: имена не разрешаются, запросы обходят туннель или настройка сбрасывается через несколько секунд после запуска.
Почему 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.1Команда wg show должна отображать узел с недавно полученным значением latest handshake, и оба запроса ping должны получать ответы. Если команда ping 1.1.1.1 завершается по тайм-ауту, проблема связана с пересылкой или NAT (преобразованием сетевых адресов), а не с DNS. Изменение конфигурации сервера разрешения имен не поможет. Во всех приведенных примерах используется 10.8.0.0/24 как подсеть туннеля и 10.8.0.1 как адрес сервера в туннеле. Замените их собственными значениями.
Сбой 1: ничего не разрешается, потому что resolver не отвечает
Симптом однозначен. ping 1.1.1.1 работает, а curl https://example.com возвращает следующее:
curl: (6) Could not resolve host: example.comЗапросите tunnel resolver напрямую с клиента. dig входит в пакет dnsutils для Ubuntu и Debian.
dig +short @1.1.1.1 example.com
dig +short @10.8.0.1 example.comПервая команда возвращает адрес. Это подтверждает, что пакеты проходят в интернет через tunnel. Вторая команда ничего не возвращает и выводит ;; communication timed out; no servers could be reached. Диагноз однозначен: клиент настроен на 10.8.0.1, а 10.8.0.1 не отвечает на UDP port 53.
Это происходит по одной из двух причин. Либо на server не запущен resolver, либо server firewall отбрасывает запрос до его поступления. Проверьте оба варианта на server.
sudo ss -ulnp | grep ':53'
sudo nft list rulesetЗапущенный resolver с правильной привязкой показывает строку с 10.8.0.1:53 или 0.0.0.0:53. В Ubuntu обычно проблема связана с 127.0.0.53:53. Это stub listener службы systemd-resolved, который привязан к loopback-адресу и намеренно недоступен с других машин. Если указать VPN-клиенту server, где единственный resolver — этот stub, возникает именно такой timeout.
Исправление состоит в том, чтобы настроить resolver, который слушает tunnel address, и добавить одно firewall rule, разрешающее peers обращаться к нему.
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'Затем откройте port только для tunnel traffic. В nftables добавьте эти две строки в chain input в файле /etc/nftables.conf и перезагрузите configuration с помощью 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. Никогда не открывайте port 53 для public internet. Сканеры находят открытый recursive resolver в течение нескольких дней и используют его для amplification denial-of-service attacks. Ваш provider заметит такой traffic раньше вас.
Снова выполните dig +short @10.8.0.1 example.com на клиенте. Наличие address в выводе означает, что resolver path работает. Теперь клиенту остается только использовать его. Добавьте эту строку в client [Interface] block и перезапустите 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Ошибка 2: утечки DNS, потому что split tunnel не маршрутизирует запросы к DNS-резолверу
Это хуже, потому что всё выглядит рабочим. Имена разрешаются, страницы загружаются, а запросы передаются в открытом виде через локальную сеть, которой вы не хотели доверять.
Причиной могут быть две конфигурации. Первая — клиент с AllowedIPs = 0.0.0.0/0, ::/0 без строки DNS =. wg-quick устанавливает маршрут по умолчанию в собственной таблице маршрутизации и добавляет правило с suppress_prefixlength 0. Это намеренно сохраняет более специфичные локальные маршруты, чтобы компьютер по-прежнему мог обращаться, например, к своему принтеру. Адрес DNS-резолвера, полученный клиентом через 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 выводит отдельный блок для каждого соединения. Если в блоке проводного или беспроводного соединения по-прежнему указан 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 обеспечивает такую координацию без передачи ключевого материала третьей стороне.
Ошибка 3: resolvconf и systemd-resolved конфликтуют на клиентах Linux
Клиенты macOS, Windows, iOS и Android применяют DNS = через официальное приложение и обычно не вызывают проблем. В Linux этот параметр применяет shell-скрипт, которому приходится определять, какой из нескольких менеджеров разрешения имён используется в системе.
Первая ошибка сразу заметна. 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 хранит отдельный список серверов разрешения имён для каждого соединения и выбирает соединение для каждого запроса. Если ни одно соединение не отмечено как маршрут по умолчанию для имён, 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 означает, что на этом адресе туннеля либо нет прослушивающего резолвера, часто потому, что заглушка 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 = при использовании туннеля с выборочной маршрутизацией?
Да. Адрес резолвера также должен находиться внутри 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 вы копируете уже проверенную конфигурацию.