Как проверить, что VPN в Windows на самом деле маршрутизирует, в PowerShell
Подключённая плитка VPN не доказывает покрытие. Прочитайте сохранённый флаг профиля, актуальную таблицу маршрутов и правила NRPT в этом порядке.
Я подключил клиент 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 see | Most likely cause | Check next |
|---|---|---|
| Public traffic leaves the physical adapter while SplitTunneling reads False | A more specific route on that adapter wins over the tunnel default | Find-NetRoute for the exact destination, then look for a /24 or host route on the physical interface |
| Internal name fails, internal IP works | No NRPT rule for that namespace, or a broader rule matches first | Get-DnsClientNrptPolicy and the namespace order |
| A dual-stack site opens directly while IPv4 uses the tunnel | The profile covers only the IPv4 default route | The IPv6 route table on both interfaces |
| Routes look right but one app still goes direct | The app uses its own proxy, or the client keeps a per-app list | The 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: принудительное и раздельное туннелирование — источник, который я держу открытым, читая вывод.