Селективная маршрутизация DNS через VPN: готовые конфигурации WireGuard, OpenVPN и strongSwan | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Селективная маршрутизация DNS через VPN: готовые конфигурации WireGuard, OpenVPN и strongSwan

08 июня 2026 10 мин. чтения

Проблема: почему весь трафик через VPN - плохая идея

Подключение к корпоративной сети через VPN часто превращает весь интернет-трафик в медленный и перегруженный поток. Доступ к внутреннему wiki или Jira начинает замедлять загрузку YouTube, работу с облачными сервисами вроде AWS Console или GitLab. Техническая причина - увеличение latency из-за дополнительного хопа через корпоративный шлюз и нагрузка на ограниченный канал VPN-сервера. Политика компании может блокировать доступ к внешним ресурсам, например, социальным сетям, что мешает работе.

Решение - разделение трафика (split-tunneling) и, что критически важно, разделение DNS-запросов (split-DNS). Split-tunneling маршрутизирует только трафик к внутренним подсетям через туннель. Split-DNS гарантирует, что DNS-запросы к внутренним доменам разрешаются через корпоративные серверы внутри VPN, а все остальные - через публичные DNS (1.1.1.1, 8.8.8.8) напрямую. Без правильной настройки split-DNS возникает утечка DNS: запрос к домену google.com может уйти через VPN-туннель на корпоративный DNS, раскрывая историю просмотров. Эта утечка - ключевая угроза безопасности и приватности.

Что такое split-DNS и как он решает задачу

Split-DNS - это конфигурация системы, при которой DNS-резолвер направляет запросы к определённым доменным суффиксам на заданные серверы. Например, запросы к доменам *.corp.company.local отправляются на внутренний DNS-сервер 10.0.0.1 через VPN-туннель. Все остальные запросы (к google.com, github.com) идут на публичные резолверы напрямую, через физический сетевой интерфейс.

Различие между split-tunneling и split-DNS фундаментально. Split-tunneling работает на уровне IP-адресов (маршрутизация пакетов), а split-DNS - на уровне имён доменов, до установления соединения. Даже если маршрутизация трафика настроена правильно, неправильно настроенный DNS может отправить запрос на разрешение имени через туннель, что создаёт задержку и потенциальную утечку метаданных. Изоляция DNS-трафика так же важна, как и изоляция IP-трафика.

Готовые конфигурации для WireGuard

WireGuard предлагает простой и производительный способ настройки split-DNS. Ключевые параметры конфигурации - DNS и AllowedIPs. Пример рабочего конфигурационного файла /etc/wireguard/wg0.conf для клиента:

[Interface]
PrivateKey = <ваш_приватный_ключ>
Address = 10.0.100.2/32
# Указываем КОРПОРАТИВНЫЙ DNS-сервер
DNS = 10.0.0.1
# Отключаем автоматическое управление таблицей маршрутизации
Table = off
# Скрипты для применения правил маршрутизации и firewall
PostUp = ip route add 10.0.0.0/24 via %i
PostUp = iptables -I OUTPUT ! -o %i -p udp --dport 53 -j REJECT
PostUp = iptables -I OUTPUT ! -o %i -p tcp --dport 53 -j REJECT
PostDown = ip route del 10.0.0.0/24 via %i
PostDown = iptables -D OUTPUT ! -o %i -p udp --dport 53 -j REJECT
PostDown = iptables -D OUTPUT ! -o %i -p tcp --dport 53 -j REJECT

[Peer]
PublicKey = <публичный_ключ_сервера>
Endpoint = vpn.company.com:51820
# Критически важный параметр: указываем ТОЛЬКО корпоративные подсети
AllowedIPs = 10.0.0.0/24
# PersistentKeepalive = 25

Параметр DNS = 10.0.0.1 сообщает системе использовать корпоративный DNS. Table = off и PostUp скрипты вручную добавляют маршрут только к внутренней подсети (10.0.0.0/24). AllowedIPs = 10.0.0.0/24 указывает WireGuard направлять через туннель только трафик к этой подсети. Весь остальной трафик идёт напрямую.

Вариант 1: Интеграция с systemd-resolved

В современных дистрибутивах на базе systemd (Ubuntu 22.04+, Debian 11+, Fedora, Arch) DNS управляется службой systemd-resolved. Для настройки split-DNS нужно отредактировать /etc/systemd/resolved.conf или, что предпочтительнее, использовать drop-in файлы для конкретного интерфейса WireGuard.

Проверьте статус службы: systemctl status systemd-resolved.

Создайте конфигурационный файл для интерфейса WireGuard. Для netdev-конфигурации systemd-networkd создайте файл /etc/systemd/network/50-wg0.network:

[Match]
Name = wg0

[Network]
# Основной DNS-сервер (через VPN)
DNS = 10.0.0.1
# Домены, которые должны разрешаться через этот DNS
Domains = corp.company.local internal.company
# Резервный DNS для всех остальных доменов (используется, если первый не отвечает)
DNS = 1.1.1.1
# Альтернативный вариант: использовать DNSOverTLS для публичных запросов
# DNSOverTLS = yes

Примените изменения и перезапустите службы:

sudo systemctl restart systemd-networkd systemd-resolved
sudo resolvectl status wg0

Команда resolvectl domain wg0 должна показать домены corp.company.local internal.company. Запросы к этим доменам будут идти на сервер 10.0.0.1, остальные - на 1.1.1.1.

Вариант 2: Настройка через dnsmasq

Для систем без systemd или где dnsmasq уже используется как локальный кэширующий резолвер, настройка split-DNS выполняется через его конфигурацию.

Установите dnsmasq: sudo apt install dnsmasq (Debian/Ubuntu) или sudo yum install dnsmasq (RHEL/CentOS).

Основной конфигурационный файл - /etc/dnsmasq.conf. Добавьте директивы:

# Не читать /etc/resolv.conf для upstream-серверов
no-resolv
# Указываем upstream DNS-сервер для ОБЩИХ запросов
server=1.1.1.1
server=8.8.8.8
# Указываем upstream DNS-сервер для КОНКРЕТНЫХ доменов (через VPN)
server=/corp.company.local/10.0.0.1
server=/internal.company/10.0.0.1
# Локальный кэш
cache-size=1000
local-ttl=300

Настройте /etc/resolv.conf для использования локального dnsmasq:

nameserver 127.0.0.1

Перезапустите dnsmasq: sudo systemctl restart dnsmasq. Теперь все DNS-запросы сначала идут на локальный dnsmasq. Запросы для *.corp.company.local он перенаправляет на 10.0.0.1 через VPN-туннель, а все остальные - на публичные DNS.

Правила firewall для предотвращения утечек DNS

Вектор атаки при утечке DNS прост: приложение или система игнорирует настройки локального резолвера и отправляет DNS-запрос напрямую на публичный сервер через порт 53 (UDP/TCP) или 853 (DoT), минуя VPN-туннель. Это раскрывает факт обращения к домену.

Готовые правила iptables блокируют все исходящие DNS-запросы, кроме тех, что идут через VPN-интерфейс или на локальный резолвер. Добавьте эти правила в скрипты PostUp конфигурации WireGuard (пример выше) или в отдельный скрипт инициализации.

# Блокировка DNS на порту 53 (UDP/TCP) вне туннеля WireGuard (wg0)
iptables -I OUTPUT ! -o wg0 -p udp --dport 53 -j REJECT
iptables -I OUTPUT ! -o wg0 -p tcp --dport 53 -j REJECT
# Блокировка DNS-over-TLS (порт 853) вне туннеля
iptables -I OUTPUT ! -o wg0 -p tcp --dport 853 -j REJECT
# Исключение для локального loopback и dnsmasq/systemd-resolved
iptables -I OUTPUT -o lo -p udp --dport 53 -j ACCEPT
iptables -I OUTPUT -o lo -p tcp --dport 53 -j ACCEPT

Аналогичные правила для nftables (более современная замена iptables):

nft add rule inet filter output meta oifname != "wg0" udp dport 53 counter reject
nft add rule inet filter output meta oifname != "wg0" tcp dport 53 counter reject
nft add rule inet filter output meta oifname != "wg0" tcp dport 853 counter reject
nft add rule inet filter output meta oifname "lo" udp dport 53 counter accept
nft add rule inet filter output meta oifname "lo" tcp dport 53 counter accept

Эти правила гарантируют, что даже при сбое в работе локального резолвера DNS-запросы не покинут систему через непредназначенный для этого интерфейс. Для комплексной защиты сетевых интерфейсов рассмотрите полное руководство по защите веб-интерфейсов, где описаны ACL и другие методы изоляции.

Настройка селективного DNS для OpenVPN

OpenVPN, в отличие от WireGuard, часто использует механизм push-опций от сервера, что может переопределять локальные настройки. Ключевая директива для избежания полного туннелирования - route-nopull в сочетании с явными route.

Пример клиентского конфигурационного файла client.ovpn для split-tunneling:

client
dev tun
proto udp
remote vpn.company.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
cipher AES-256-GCM
# Критически важные опции для split-DNS и split-tunnel
# Не применять маршруты, отправленные сервером
route-nopull
# Явно указываем маршрут только к корпоративной подсети
route 10.0.0.0 255.255.255.0
# Указываем корпоративный DNS-сервер
dhcp-option DNS 10.0.0.1
# Скрипт для обновления DNS-настроек системы
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

Директива route-nopull предотвращает добавление маршрута по умолчанию (0.0.0.0/0) через туннель, который обычно push-ится сервером. route 10.0.0.0 255.255.255.0 вручную добавляет маршрут к нужной подсети. dhcp-option DNS 10.0.0.1 передаёт системе адрес DNS-сервера.

Использование скриптов up и down для автоматизации

Скрипты up и down позволяют автоматически применять сложные настройки DNS и маршрутизации при установке и разрыве VPN-соединения. Стандартный скрипт update-resolv-conf часто идёт в пакете OpenVPN. Для более тонкого контроля, например, интеграции с systemd-resolved, можно создать свой скрипт.

Пример пользовательского скрипта /etc/openvpn/split-dns-up.sh для systemd-resolved:

#!/bin/bash
# Получаем переданные OpenVPN переменные
DOMAINS="corp.company.local internal.company"
DNS_SERVER="${foreign_option_1##*dhcp-option DNS }"
# Настраиваем systemd-resolved для интерфейса $dev
resolvectl dns "$dev" "$DNS_SERVER"
resolvectl domain "$dev" $DOMAINS
# Логируем действие
echo "$(date): Split-DNS настроен для $dev. DNS: $DNS_SERVER, Domains: $DOMAINS" >> /var/log/openvpn-split-dns.log

Скрипт должен быть исполняемым (chmod +x). В конфигурации client.ovpn укажите:

script-security 2
up /etc/openvpn/split-dns-up.sh
down /etc/openvpn/split-dns-down.sh

Скрипт down должен очищать настройки. Меры предосторожности: проверяйте права на файлы (только root), делайте скрипты идемпотентными (повторный вызов не ломает систему), логируйте действия для отладки.

Конфигурация strongSwan для корпоративных сценариев

strongSwan - это реализация IPsec/IKEv2, часто используемая в enterprise-средах для site-to-site и remote-access VPN. Его конфигурация для split-DSN сосредоточена в файлах /etc/ipsec.conf и /etc/ipsec.secrets.

Основы конфигурации подключения в ipsec.conf:

conn corp-vpn
  left=%defaultroute
  leftsourceip=%config
  leftauth=eap-mschapv2
  leftid=user@company.com
  right=vpn.company.com
  rightsubnet=10.0.0.0/24
  rightid=@vpn.company.com
  eap_identity=%identity
  auto=start
  # Важно: указываем только нужные подсети
  # Это предотвращает маршрутизацию всего трафика
  # Для получения настроек DNS от сервера
  modecfgdns="10.0.0.1"
  modecfgdomains="corp.company.local"

Параметры modecfgdns и modecfgdomains указывают демону charon (подсистема strongSwan) передать эти настройки клиенту через режим конфигурации (Mode Config). Клиентские настройки, например, в NetworkManager или Windows, должны поддерживать получение этих опций.

Настройка политик маршрутизации определяется параметрами leftsubnet и rightsubnet. Убедитесь, что rightsubnet содержит только корпоративные подсети, а не 0.0.0.0/0. Интеграция с плагинами strongSwan, такими как systemd или resolvconf, может автоматически применять полученные DNS-настройки к системе. Для детальной настройки сетей и VPN ознакомьтесь с практическим руководством по Linux.

Тестирование и отладка работы split-DNS

После настройки необходимо проверить корректность работы. Используйте команды для диагностики.

Проверьте, какой DNS-сервер используется системой и для каких доменов: systemd-resolve --status или resolvectl status. Убедитесь, что для VPN-интерфейса указаны правильные домены и DNS-сервер.

Специфичные тесты раздельного разрешения:

# Запрос к внутреннему домену должен идти через корпоративный DNS (10.0.0.1)
dig @10.0.0.1 internal.corp.company.local
# или с указанием интерфейса
dig internal.corp.company.local
# Запрос к внешнему домену должен идти через публичный DNS
dig @1.1.1.1 example.com
dig example.com

Проверка на утечку DNS: используйте онлайн-сервисы типа "DNS Leak Test" или выполните локальный захват трафика: sudo tcpdump -i any port 53. Запустите запрос к внешнему домену (dig example.com). В выводе tcpdump вы должны видеть DNS-запросы, уходящие только на локальный адрес (127.0.0.1, если используется dnsmasq/resolved) или через VPN-интерфейс. Запросов на публичные IP-адреса (например, 1.1.1.1) на физическом интерфейсе (eth0, wlan0) быть не должно.

Анализ маршрутов: команда ip route get 8.8.8.8 покажет, через какой интерфейс и шлюз пойдёт трафик к публичному DNS. Он должен указывать на ваш стандартный шлюз, а не на туннельный интерфейс.

Диагностика типичных проблем

Проблема: DNS вообще не работает после подключения VPN.
Решение: проверьте, запущены и работают ли локальные DNS-резолверы (systemctl status systemd-resolved dnsmasq). Убедитесь, что правила firewall не блокируют DNS-запросы к локальному резолверу (правила должны содержать исключение для lo). Проверьте конфигурацию /etc/resolv.conf - она должна указывать на 127.0.0.1 или 127.0.0.53.

Проблема: Все DNS-запросы идут через VPN, интернет медленный.
Решение: проверьте параметр AllowedIPs в WireGuard - он не должен содержать 0.0.0.0/0. В OpenVPN убедитесь, что используется route-nopull и нет директивы redirect-gateway. В strongSwan проверьте rightsubnet.

Проблема: Утечка DNS сохраняется, запросы уходят на публичные DNS.
Решение: убедитесь, что правила iptables/nftables активны (iptables -L OUTPUT -v -n). Проверьте, что в системе нет других DHCP-клиентов или сетевых менеджеров (например, NetworkManager), которые перезаписывают настройки DNS. Временно отключите их для тестирования.

Для решения сложных проблем с маршрутизацией и обходом блокировок могут пригодиться альтернативные подходы, описанные в руководстве по обходу IP-блокировок, где рассматриваются тонкости настройки туннелей.

Итог: единая схема настройки для любого VPN

Несмотря на различия в реализации, принцип настройки селективной маршрутизации DNS един для всех VPN-решений.

  1. Определите целевые домены и подсети. Составьте список внутренних доменов (например, corp.local, jira.internal) и IP-подсетей (например, 10.0.0.0/24, 192.168.1.0/24), доступ к которым должен идти через VPN.
  2. Настройте VPN-клиент только на эти подсети. Используйте AllowedIPs в WireGuard, route-nopull и явные route в OpenVPN, rightsubnet в strongSwan. Никогда не маршрутизируйте весь трафик (0.0.0.0/0) через туннель, если это не требуется.
  3. Настройте локальный DNS-резолвер на раздельное разрешение. Используйте systemd-resolved с опцией Domains= или dnsmasq с директивами server=/domain/. Направьте системный resolv.conf на локальный резолвер (127.0.0.1).
  4. Примените firewall-правила для блокировки утечек DNS. Заблокируйте исходящие DNS-запросы на порты 53/853 на всех интерфейсах, кроме VPN-туннеля и loopback. Используйте iptables или nftables.
  5. Протестируйте конфигурацию. Проверьте разрешение внутренних и внешних доменов, убедитесь в отсутствии утечек с помощью dig и tcpdump.

Выбор решения зависит от инфраструктуры. WireGuard - для простоты, высокой скорости и современных систем. OpenVPN - для максимальной совместимости, поддержки сложных аутентификационных схем и устоявшихся корпоративных развёртываний. strongSwan (IPsec/IKEv2) - для интеграции со стандартизированными enterprise-средами, межсетевыми экранами и операционными системами, где требуется поддержка на уровне ядра.

Этот подход обеспечивает безопасный доступ к внутренним ресурсам без компромиссов в скорости общего интернет-соединения. Для более сложных сценариев маршрутизации, например, на уровне отдельных приложений или контейнеров, изучите возможности таких инструментов, как V2RayTUN. Если вам требуется централизованное управление доступом к множеству AI-моделей без необходимости настройки отдельных VPN для разных сервисов, рассмотрите специализированные сервисы, например, AiTunnel, который агрегирует API более чем 200 моделей, включая GPT и Claude, и предоставляет единый интерфейс с оплатой в рублях.

Поделиться:
Сохранить гайд? В закладки браузера