Проблема: почему весь трафик через 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-решений.
- Определите целевые домены и подсети. Составьте список внутренних доменов (например,
corp.local, jira.internal) и IP-подсетей (например,10.0.0.0/24, 192.168.1.0/24), доступ к которым должен идти через VPN. - Настройте VPN-клиент только на эти подсети. Используйте
AllowedIPsв WireGuard,route-nopullи явныеrouteв OpenVPN,rightsubnetв strongSwan. Никогда не маршрутизируйте весь трафик (0.0.0.0/0) через туннель, если это не требуется. - Настройте локальный DNS-резолвер на раздельное разрешение. Используйте systemd-resolved с опцией
Domains=или dnsmasq с директивамиserver=/domain/. Направьте системныйresolv.confна локальный резолвер (127.0.0.1). - Примените firewall-правила для блокировки утечек DNS. Заблокируйте исходящие DNS-запросы на порты 53/853 на всех интерфейсах, кроме VPN-туннеля и loopback. Используйте iptables или nftables.
- Протестируйте конфигурацию. Проверьте разрешение внутренних и внешних доменов, убедитесь в отсутствии утечек с помощью
digиtcpdump.
Выбор решения зависит от инфраструктуры. WireGuard - для простоты, высокой скорости и современных систем. OpenVPN - для максимальной совместимости, поддержки сложных аутентификационных схем и устоявшихся корпоративных развёртываний. strongSwan (IPsec/IKEv2) - для интеграции со стандартизированными enterprise-средами, межсетевыми экранами и операционными системами, где требуется поддержка на уровне ядра.
Этот подход обеспечивает безопасный доступ к внутренним ресурсам без компромиссов в скорости общего интернет-соединения. Для более сложных сценариев маршрутизации, например, на уровне отдельных приложений или контейнеров, изучите возможности таких инструментов, как V2RayTUN. Если вам требуется централизованное управление доступом к множеству AI-моделей без необходимости настройки отдельных VPN для разных сервисов, рассмотрите специализированные сервисы, например, AiTunnel, который агрегирует API более чем 200 моделей, включая GPT и Claude, и предоставляет единый интерфейс с оплатой в рублях.