Я подключил клиент VPN на ноутбуке с Windows 11, плитка перешла в состояние Connected, открылась внутренняя файловая папка, а публичный сайт всё ещё загружался напрямую через Wi-Fi офиса. Эта смесь выглядит как сломанный туннель. На самом деле это обычный результат профиля, который часть трафика отправляет через VPN, а остальное оставляет на физическом адаптере. Принудительное туннелирование меняет то, какому маршруту по умолчанию Windows отдаёт предпочтение; оно не удаляет более конкретные маршруты и не обещает, что трафик остановится при обрыве соединения. Далее — порядок, которого я придерживаюсь, когда клиент заявляет о покрытии: состояние клиента, сохранённый профиль, применённые маршруты, распознаватель и затем реальные потоки.

Начните с клиента, а затем перестаньте ему доверять

Клиент — правильное место для начала только потому, что он сообщает, какой профиль активен. Откройте свойства подключения и запишите точное имя профиля, для кого он создан — для текущего пользователя или для всех на машине, — и какой адаптер появляется в ncpa.cpl после подключения. На моём тестовом ноутбуке адаптер носил имя профиля, и это делало вывод маршрутов удобным для чтения. На других машинах он отображается как запись WAN Miniport, и имя ничего вам не говорит.

Чего клиент не может вам сказать — это покрытие. Подключённая плитка описывает состояние туннеля, а не перечень назначений. Сторонние клиенты также хранят собственную конфигурацию, поэтому штатный профиль Windows и любое его свойство, которое вы прочитаете, может не иметь ничего общего с тем, что установил этот клиент. Если VPN пришёл через AnyConnect, OpenVPN GUI, WireGuard или агент поставщика, проверки PowerShell ниже в основном не применяются, и вместо них следует читать собственные настройки раздельного туннеля и маршрутизации этого клиента.

Читайте сохранённый профиль, а не плитку

Для штатного профиля Windows (IKEv2, L2TP, SSTP или профиля, продвигаемого MDM) сохранённое решение о раздельном туннеле — это одно свойство:

Get-VpnConnection -Name 'Office' | Select-Object Name, ServerAddress, SplitTunneling, DnsSuffix

Добавьте -AllUserConnection, когда профиль создан для всех на устройстве. Без этого вы читаете список текущего пользователя, который может быть пустым или содержать другую запись с похожим именем. Значение False в SplitTunneling означает, что профиль сохранён как полный туннель: Windows устанавливает маршрут по умолчанию через адаптер VPN. True означает раздельный туннель, и покрытие тогда полностью зависит от маршрутов и правил разрешения имён, которые продвигает этот профиль.

Относитесь к этому значению как к конфигурации, а не как к наблюдению. Оно фиксирует, что профиль запросил в момент подключения. Windows может остаться с другими применёнными маршрутами — из-за более конкретного маршрута другого интерфейса, параметра политики или остатка от предыдущего подключения, — поэтому логическое значение само по себе вопрос не решает.

Сравните сохранённое значение с применённой таблицей маршрутов

После подключения перечислите маршруты на адаптере туннеля вместо прокрутки всей таблицы:

$vpn = Get-NetAdapter | Where-Object InterfaceDescription -match 'VPN|WAN Miniport'
Get-NetRoute -InterfaceIndex $vpn.ifIndex | Sort-Object DestinationPrefix
Find-NetRoute -RemoteIPAddress 10.20.4.15 | Select-Object -First 1

Find-NetRoute — полезная половина. Он отвечает на вопрос, на который клиент никогда не отвечает: для этого назначения какой интерфейс и какой адрес источника Windows действительно использует? Запустите его для внутреннего узла, публичного узла и всего, что вы считаете намеренным исключением. Профиль полного туннеля должен показывать интерфейс туннеля для публичного адреса. Профиль раздельного туннеля обычно показывает там физический адаптер, тогда как внутренние префиксы по-прежнему разрешаются через VPN.

Две ловушки объясняют большинство сообщений «маршрутизирует не туда». Самый конкретный префикс всегда побеждает, поэтому /24 на физическом адаптере бьёт маршрут по умолчанию на VPN, как бы низка ни была метрика туннеля. Метрика лишь разрешает равенство между маршрутами для одного префикса. А IPv4 и IPv6 решаются отдельно: профиль, покрывающий 0.0.0.0/0, может оставить IPv6 на локальном канале, из-за чего двухстековый сайт выглядит наполовину туннелированным. Проверьте Get-NetRoute -AddressFamily IPv6, прежде чем заключать, что туннель в порядке.

What you seeMost likely causeCheck next
Public traffic leaves the physical adapter while SplitTunneling reads FalseA more specific route on that adapter wins over the tunnel defaultFind-NetRoute for the exact destination, then look for a /24 or host route on the physical interface
Internal name fails, internal IP worksNo NRPT rule for that namespace, or a broader rule matches firstGet-DnsClientNrptPolicy and the namespace order
A dual-stack site opens directly while IPv4 uses the tunnelThe profile covers only the IPv4 default routeThe IPv6 route table on both interfaces
Routes look right but one app still goes directThe app uses its own proxy, or the client keeps a per-app listThe app's proxy settings and the client's application list

Проверьте разрешение имён отдельно с помощью NRPT

Внутренние имена, которые не работают, тогда как внутренние IP-адреса работают, указывают на политику распознавателя, а не на маршрутизацию. Windows решает DNS для каждого пространства имён через таблицу политики разрешения имён, независимую от таблицы маршрутов:

Get-DnsClientNrptPolicy -Effective | Select-Object Namespace, NameServers
Get-DnsClientServerAddress -InterfaceIndex $vpn.ifIndex

Когда правило совпадает с *.corp.example, запросы для этого пространства имён идут на DNS-серверы туннеля, даже если путь данных к этим серверам в режиме раздельного туннеля остаётся на физическом адаптере. Такова задумка, и поэтому тест в браузере, открывающий публичный сайт, ничего не говорит о внутренних именах. Если адаптер перечисляет ожидаемые серверы, но поиск всё равно уходит в другое место, сравните порядок правил NRPT и проверьте, не совпадает ли первым более конкретное пространство имён.

Проверьте потоки, а затем решите, что вы на самом деле просили

Пройдите назначения в фиксированном порядке, чтобы результаты были сопоставимы между машинами: публичный адрес, внутренний адрес, внутреннее имя и одно намеренное исключение, например локальный принтер или видеозвонок. Запишите интерфейс и адрес источника, которые Find-NetRoute возвращает для каждого. После любого изменения политики подключитесь заново и повторите те же четыре проверки; таблица маршрутов после переподключения — единственное доказательство того, что новый профиль вступил в силу.

Затем отделите маршрутизацию от принуждения. Принудительное туннелирование предпочитает туннель для покрытого трафика, пока он поднят. Это не kill switch. Если требование состоит в том, чтобы при падении туннеля ничего не покидало машину, это должно исходить из блокирующего решения: профиль брандмауэра, привязанный к состоянию туннеля, постоянно включённый профиль с фильтрами трафика или собственная опция закрытия при сбое у клиента поставщика. Принудительное туннелирование также должно оставлять адрес самого VPN-сервера доступным вне туннеля, а блокировка его во имя «принудить всё» — надёжный способ запереть себя вне соединения, которое вы пытаетесь обеспечить.

Прежде чем что-то менять, пройдите этот список. Каждый невыполненный пункт сужает, где находится настоящая проблема.

  • Имя и область профиля подтверждены, для профилей на уровне машины использован -AllUserConnection.
  • SplitTunneling прочитан и воспринят как конфигурация, а не как доказательство покрытия.
  • Маршруты адаптера туннеля перечислены отдельно для IPv4 и IPv6.
  • Find-NetRoute запущен для одного публичного, одного внутреннего и одного исключительного назначения.
  • Правила NRPT проверены прежде, чем винить маршруты в отказе имени.
  • Требование блокировки перечитано: предпочтительная маршрутизация — не то же самое, что обеспеченная блокировка.

Решение о полном или раздельном туннеле принадлежит владельцу профиля, а заметки Microsoft о маршрутизации описывают поведение, которое Windows реализует, когда профиль его задаёт. Microsoft: принудительное и раздельное туннелирование — источник, который я держу открытым, читая вывод.

Похожие статьи