WSL2 не достигает подсети VPN: прочитайте маршрут хоста
Дистрибутив находится за собственным NAT и никогда не видит туннель Windows. Прочитайте текущий адрес и префикс с хоста, затем добавьте их внутри WSL.
Изнутри дистрибутива ping до внутреннего сервера завершается тайм-аутом, тогда как тот же адрес отвечает из Windows. VPN подключён, и маршрут Windows верен, поэтому разрыв — это граница WSL. Пройдите путь от неудачной команды обратно до интерфейса хоста. Исправление — не фиксированный CIDR в файле конфигурации; это чтение текущего адреса и добавление его туда, где дистрибутив может его использовать.
Подтвердите, где путь останавливается
Выполните один и тот же тест с обеих сторон: разрешите и подключитесь к одному внутреннему хосту из Windows, затем повторите это в дистрибутиве. Успех в Windows плюс тайм-аут в дистрибутиве локализуют сбой между ними, а не в клиенте VPN или внутреннем сервере. Сделайте это до изменения любого маршрута, чтобы оба результата описывали один и тот же пункт назначения.
Внутри дистрибутива ip -4 addr показывает виртуальный адаптер с адресом из диапазона WSL NAT, а ip route показывает маршрут по умолчанию к шлюзу WSL. Маршрута для корпоративного префикса нет, потому что у туннельного адаптера хоста нет аналога внутри дистрибутива. Шлюз по умолчанию ведёт к WSL NAT, а не в корпоративную сеть.
Добавление корпоративного маршрута без предварительного добавления локального адреса на достижимом канале даёт тайм-аут или ошибку недоступности сети. Именно адрес делает маршрут пригодным, поэтому сначала прочитайте его, а маршрут считайте вторым шагом.
Выберите зеркальную сеть или маршрут скриптом
Зеркальная сеть отдаёт дистрибутиву собственные интерфейсы хоста, поэтому туннель и его маршруты появляются без копирования. Функция зависит от свежей сборки Windows и от networkingMode=mirrored в .wslconfig, а её включение меняет несвязанное поведение, например пересылку localhost. Считайте это сменой платформы, а не настройкой маршрута. Если сборка поддерживает её и побочные эффекты приемлемы, это самый короткий путь.
Более узкий подход сохраняет NAT по умолчанию и копирует адрес и маршрут туннеля в дистрибутив при каждом поднятии туннеля. Он работает на большем числе сборок, не меняет поведение localhost и заметно отказывает, когда VPN выключен. Цена — небольшой скрипт, который нужно запускать при каждом подключении.
Выберите один и запишите его. Смешивание зеркальной конфигурации с ручными маршрутами даёт дистрибутив с двумя путями к одному префиксу и без явного владельца ни одного из них. Один документированный метод отлаживать проще, чем два полунастроенных.
Получите текущие параметры туннеля с хоста
Сопоставляйте адаптер по MAC-адресу, а не по имени, потому что имена меняются вместе с клиентом VPN и порядком подключения. Перечислите адаптеры один раз, запишите MAC туннельного адаптера, затем запросите его адрес и префикс. MAC остаётся у виртуального адаптера между переподключениями, а имя и индекс интерфейса — нет:
powershell.exe 'Get-NetAdapter | Where-Object { $_.MacAddress -eq "3C-52-82-0A-1B-7C" } | Get-NetIPAddress -AddressFamily IPv4 | Select-Object IPAddress, PrefixLength'Шлюз берётся из конфигурации интерфейса. Сначала получите индекс интерфейса, затем прочитайте следующий хоп. Индекс может измениться после перезагрузки или сброса адаптера, поэтому скрипт должен читать его, а не хранить:
powershell.exe '(Get-NetAdapter | Where-Object { $_.MacAddress -eq "3C-52-82-0A-1B-7C" }).InterfaceIndex'
powershell.exe '(Get-NetIPConfiguration -InterfaceIndex 27).IPv4DefaultGateway.NextHop'Пропустите вывод через tr -d '\r' перед присваиванием переменной. PowerShell завершает строки символом возврата каретки, и без очистки последнее поле несёт скрытый символ, из-за которого команда маршрута падает с непонятной ошибкой разбора.
Примените адрес и маршрут внутри дистрибутива
Установите адрес туннеля как адрес с префиксом на интерфейсе дистрибутива, затем направьте корпоративный блок через шлюз хоста:
sudo ip addr add 172.20.14.37/22 dev vpn
sudo ip route add 172.20.0.0/16 via 172.20.12.1 dev vpnNetworkManager сбрасывает вручную настроенный адрес, когда соединение перезапускается, и ни один клиент DHCP не просит замену. Задайте метод автоматическим, чтобы каждое переподключение обновляло адрес, затем снова поднимите соединение. Ручной метод выглядит стабильным до первого переподключения:
nmcli con show vpn
sudo nmcli con mod vpn ipv4.method auto
sudo nmcli con up vpnВыполняйте оба шага из хука, который запускает VPN, а не из интерактивной оболочки. Скрипт, который читает адрес, добавляет его, добавляет маршрут и записывает значения в журнал, превращает повторяющийся ручной ремонт в воспроизводимый, и журнал — первое, что нужно прочитать при смене префикса.
Закрепите имя и докажите путь
Ядро может переименовать интерфейс дистрибутива между eth1 и eth2 после переключения сети, и скрипт, написанный под имя, тогда правит не то устройство. Правило udev, привязанное к MAC, даёт интерфейсу стабильную метку:
SUBSYSTEM=="net", ACTION=="add", ATTRS{address}=="3c:52:82:0a:1b:7c", NAME="vpn"Затем проверьте адресом, маршрутом и реальным TCP-соединением: ip -4 addr show dev vpn, ip route get 172.20.4.10 и соединением с известным внутренним портом. Поиск маршрута должен назвать устройство vpn и добавленный вами адрес источника.
Если все три проверки проходят внутри дистрибутива, а соединение всё равно не работает, пакет покидает WSL и отбрасывается на стороне Windows. Проверьте брандмауэр хоста и собственную фильтрацию клиента VPN, прежде чем менять скрипт, потому что ещё одна правка маршрута не исправит пакет, который уже доходит до хоста.