Дві конфігурації Windows виглядають у «Параметрах» однаково й поводяться зовсім по-різному. Одна — скопійований профіль VPN із тригером застосунку, тож запуск одного виконуваного файлу піднімає тунель. Друга — профіль із роздільним тунелюванням, чий список маршрутів випадково покриває те, з чим спілкується цей застосунок. Перша відповідає, коли тунель існує. Друга відповідає, які пакети до нього входять, і лише друга залишає решту машини на фізичному каналі, поки застосунок залишається підключеним.

Тригер — правило життєвого циклу, а не правило маршрутизації

Add-VpnConnectionTriggerApplication прив'язує шлях до виконуваного файлу до назви профілю. Коли цей процес запускається, диспетчер підключень віддаленого доступу набирає профіль, і коли умова тригера завершується, з'єднання може впасти. Ніщо в цьому обміні не перевіряє сокети. Командлету потрібна підвищена оболонка, повний шлях до бінарника і -Force коли ви замінюєте наявний запис. Переконайтеся, що зв'язок зберігся, за допомогою Get-VpnConnectionTrigger замість того, щоб довіряти запрошенню; довідник Microsoft щодо Add-VpnConnectionTriggerApplication перелічує параметри та приклади.

Дві межі пояснюють більшість повідомлень «тригер нічого не робить». Тригери будуються навколо профілів для всіх користувачів, тому область профілю — перше, що треба владнати, а шлях застосунку має збігатися з реально запущеним бінарником, а не з ярликом чи завантажувачем, що створює другий процес. Друга межа навмисна: у мережі, яку Windows класифікує як довірену, тригер залишається бездіяльним, бо профіль розрахований на роботу поза офісом.

Add-VpnConnectionTriggerApplication -Name "APP_VPN" -ApplicationID "C:\Program Files\Vendor\app.exe" -Force
Get-VpnConnectionTrigger -Name "APP_VPN" | Format-List *
Get-VpnConnection -Name "APP_VPN" | Format-List Name,ConnectionStatus,SplitTunneling,AllUserConnection

Роздільне тунелювання вирішує, що перетинає тунель

Коли роздільне тунелювання вимкнене, Windows встановлює на інтерфейс VPN класовий маршрут за замовчуванням із низькою метрикою. Йому слідує кожен сокет, зокрема браузер і служба оновлень, тому тригер у такій конфігурації рухає всю машину, поки профіль підключений. Тригер і далі лише правило життєвого циклу; радіус ураження прийшов від маршруту.

Коли роздільне тунелювання ввімкнене, профіль несе лише префікси, які просуває шлюз або які ви додаєте на інтерфейс VPN. Усе інше далі використовує фізичний маршрут за замовчуванням. Це та схема, яку зазвичай мають на увазі під «один застосунок через окремий вихід», і вона від початку до кінця є рішенням про маршрутизацію.

Set-VpnConnection -Name "APP_VPN" -SplitTunneling $true
Get-VpnConnection -Name "APP_VPN" | Select-Object SplitTunneling
Get-NetRoute -InterfaceAlias "APP_VPN" | Sort-Object DestinationPrefix

Де маршрутизоване розділення перестає ізолювати застосунок

Типовий збій — призначення, яке так і не з'являється в списку маршрутів тунелю. Застосунок, який входить за однією адресою, а потім стримить із CDN або розв'язує десяток змінних кінцевих точок, частину з'єднань покладе на інтерфейс VPN, а решту — на Wi-Fi. IPv6 — окрема таблиця, тому профіль, який просуває лише префікси IPv4, може виглядати правильним, поки трафік застосунку через IPv6 залишається локальним.

Два менші ефекти важать не менше. Перемагає найдовший збіг префікса, тому конкретніший on-link маршрут, /32, просунутий для хоста керування, або підмережа другого адаптера можуть переграти тунель саме для потрібної вам адреси. Розв'язання імен теж відбувається до маршрутизації: якщо DNS-сервери профілю або правило NRPT не покривають ім'я, застосунок може розв'язати його через фізичний адаптер і потім набрати адресу, якої ніколи не було всередині тунельованих префіксів.

Три форми і що кожна дає

Таблиця — та частина, яку я приклеїв би на стіну, бо рішення про радіус ураження, а не про функції. Якщо призначення застосунку — стабільні префікси, які можна перелічити, маршрутизоване розділення дає ізоляцію з найменшим слідом. Якщо ні, профіль із маршрутом за замовчуванням за віртуальною машиною або другим пристроєм зберігає розділення чесним ціною переміщення більш ніж одного процесу.

ShapeWhat starts the tunnelWhat enters itPick it when
Trigger plus routed splitProcess startOnly pushed or added prefixesThe app's endpoints are stable prefixes and the host should stay direct
Trigger plus default routeProcess startEverything, machine-wideYou need one exit for all traffic and accept the wider scope
Separate VM or deviceGuest boot or loginEverything inside that guestThe app's destinations rotate, or the host must keep its own public address

Чого жоден із цих варіантів не дає — прив'язки на рівні сокета на хості. У класичного клієнта Windows VPN немає правила, що цей процес мусить використовувати той адаптер; тригери й фільтри маршрутів живуть у різних шарах, а шар, що вибирає інтерфейс, — це таблиця маршрутизації. Якщо посібник обіцяє примус за застосунками лише зі скопійованого профілю, запитайте, який маршрут або який фільтр робить роботу.

Перевірте пару за один прохід

Перевіряйте життєвий цикл і маршрутизацію окремо, у такому порядку. Закрийте застосунок, переконайтеся, що профіль повідомляє Disconnected, потім запустіть застосунок і перевірте, чи змінився стан. Лише коли тунель піднято, варто питати, куди йде конкретне призначення, і використовувати треба адресу, яку застосунок справді набирає, а не здогад.

$app = Get-Process app | Select-Object -First 1
Get-VpnConnection -Name "APP_VPN" | Select-Object ConnectionStatus
Get-NetTCPConnection -OwningProcess $app.Id -State Established | Select-Object RemoteAddress,RemotePort
Find-NetRoute -RemoteIPAddress 203.0.113.10

Find-NetRoute називає інтерфейс і наступний стрибок, який поніс би це призначення. Фізичний псевдонім там означає, що тунель піднято і для цього потоку неважливий: перевірте просунуті префікси, потім конкретніші маршрути, потім IPv6. Якщо стан узагалі не змінюється, тригер не спрацював, і шлях до виконуваного файлу, область профілю та операційний журнал клієнта VPN — три місця, куди дивитися.

Приберіть усе охайно, щоб наступний тест був чесним

Видаляйте в зворотному порядку складання: спершу тригер застосунку, потім профіль. Видалення профілю при залишеному тригері залишає висячий зв'язок, який заплутує наступну спробу, і Remove-VpnConnection -Force не завжди очищає запис телефонної книги, створений поза командлетами.

Записи для окремих користувачів лежать у rasphone.pbk користувача в профілі Roaming; записи для всіх користувачів лежать у ProgramData. Перевірте сховище, що відповідає області профілю, знову підключіть збережений профіль і переконайтеся, що його маршрути й DNS поводяться як раніше, щоб пізніший тест вимірював внесену зміну, а не залишковий стан.

  • Тунель піднімається під час запуску процесу, а не під час входу.
  • На інтерфейсі VPN з'являються лише призначені префікси.
  • Справжня віддалена адреса застосунку розв'язується в псевдонім VPN.
  • Після видалення профілю не залишається висячого тригера.

Схожі статті