История о SSH-подключении, которое должно было занять 30 секунд, но вместо этого превратилось в археологические раскопки таблицы маршрутизации Windows, борьбу с VPN-клиентом, перетасовку сетевых интерфейсов и другими неприятностями.

Я решил заменить арендованный VPS своим старым ноутбуком — он мощнее и не требуется арендной платы. Но начиная с первого же ssh root@192.168.31.197 словил массу проблем. В статье мы не придем к моей изначальной цели — организовать собственный self-hosted VPS, а всего лишь сумеем подключиться к моему ноуту в рамках моей локальной сети — прикиньте, это оказалось чертовски сложной задачей. Сам self-hosted VPS мы уже рассмотрим в следующей статье. Если у кого-то появилось желание следить за этой историей — мой тг канал.

Статью буду писать параллельно со своими действиями, чтобы получился воспроизводимый гайд и вместе с этим полезный материал для начинающих DevOps. В какой-то степени местами статья будет выглядеть как дневник разработчика и не исключено, что я буду заходить в тупик, буксовать на ровном месте, но мне хочется запечатлеть всю хронологию работы с пробами и ошибками, что бы поделиться с читателем моим стилем работы, мышлением и подходом к решению сложностей.

Что вы узнаете

  • Как устроена таблица маршрутизации Windows и что реально происходит, когда вы включаете VPN

  • Почему metric=1 не означает «этот маршрут победит» — и что такое суммирование метрик интерфейса и маршрута

  • Как работает Longest Prefix Match и почему /32 бьёт /24 при любой метрике

  • Что делает Amnezia VPN (WireGuard) с вашими маршрутами при AllowedIPs = 0.0.0.0/0

  • Почему route add ... if 29 может отправить ваш трафик в ZeroTier-туннель вместо WiFi — и что с этим можно сделать.

  • Как диагностировать сетевые проблемы на Windows, когда tracert врёт, а ip route get не существует

  • Вооружитесь несколькими аргументами почему цивилизация должна уничтожить Windows и перейти на Linux

Кому будет полезно

  • Разработчикам, которые используют VPN для работы и периодически теряют доступ к локальным устройствам — NAS, принтерам, домашним серверам

  • Начинающим сисадминам и DevOps-инженерам, которые хотят понять маршрутизацию не по учебнику, а на живом примере с реальным хаосом

  • Всем, кто работает на Windows и хоть раз недоумевал, почему ping 192.168.x.x не работает при включённом VPN

  • Тем, кто задумывается о замене VPS домашним сервером ("self-hosting VPS") — и хочет заранее увидеть, с чем придётся столкнуться

Термины и пояснения

Для начала во избежание путаницы определимся с терминами:

  • ПК - рабочая машина с которой я работаю, на нем windows.

  • Ноутбук - наш портативный дата-центр, на нем fedora.

ПК и Ноутбук находятся в одной локальной сети (подключены к одному домашнему роутеру) - 192.168.31.x

Начинаем работу

У меня есть дешевый зарубежный VPS. Я имею к нему SSH доступ и он в данный момент он используется как Self-Hosted VPN через Amnezia. Для удобства работы сделаем так же SSH доступ к нашему ноутбук-серверу с рабочего компа.

На ноутбуке смотрим локальный IP адрес:

ip a

И видим среди множества интерфейсов тот что начинается с 192.168...
В нашем случае это 192.168.31.197

Пытаемся подключиться и получаем ошибку:

ssh root@192.168.31.197
ssh: connect to host 192.168.31.197 port 22: Connection timed out

Похоже daemon (сервер) который прослушивает 22 port не работает. Проверим на ноутбуке:

sudo systemctl status sshd

Именно sshd, а не ssh (так как это ssh daemon - сервер прослушивающий 22 порт).

Судя по выводу он запущен и прослушивает 22 порт. Но соединения нет, наверное firewall. Fedora по умолчанию использует firewalld.

sudo systemctl status firewalld

В результате

Active: inactive (dead)  

Он вообще выключен, может быть дело в таблице маршрутизации?

sudo iptables -L -n

В Chain INPUT (policy ACCEPT), не вижу никаких DROP или REJECT. Значит дело в чем-то другом. Подозрение падает на мой ПК. С которого я пытаюсь подключаться, а тут у меня включен VPN (Amnezia) - она ведь меняет таблицу маршрутизации и перенаправляет весь трафик сразу к серверу. Выключил VPN - соединение прошло. Значит попробуем добавить прям в UI Amnezia исключение для IP 192.168.31.197, у него есть такая фича, правда не всегда работает почему-то.

Открываем клиент Amnezia

Split tunneling enabled → Site-based split tunneling → добавляем `192.168.31.197`.

Перезапускаем и пытаемся переподключиться. Ничего не получилось - Connection refused. Ну ничего не остается кроме как руками править таблицу маршрутизации на windows.

Решаем проблемы

Не выходит, но сдаваться я не намерен. Придется копнуть глубже.

Немного теории о том как работает VPN и моя конфигурация ПК

Он устанавливает правило с наименьшей метрикой из-за которого ОС все запро��ы отправляет в первую очередь на сетевой интерфейс созданный VPN клиентом при установке. Когда происходит какой-то сетевой запрос ОС смотрит таблицу маршрутизации и если видит что целевой маршрут запроса в таблице маршрутизации имеет самую низкую метрику, все запросы будут происходить через указанный интерфейс. Это упрощенно, на самом деле помимо метрики, играет роль так же специфичность маршрута. ОС ищет самый специфичный (longest prefix match) маршрут, затем среди одинаковых — с наименьшей метрикой.

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

route print

Команда покажет нам список существующих сетевых интерфейсов, их ID, комментарий, чтобы понять кто есть кто.
Я покажу свой вывод команды, но уберу лишнее, чтобы упростить:

$ route print
===========================================================================
Список интерфейсов
 31...6a b3 51 82 3f b3 ......ZeroTier Virtual Port
 75...........................WireGuard Tunnel
 30...1e 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #5
 18...1c 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #6
 32...dc 21 5c 03 76 6d ......Intel(R) Wi-Fi 6 AX201 160MHz
 29...1c 61 b4 45 ad 50 ......TP-Link Wireless MU-MIMO USB Adapter
 19...e8 48 b8 c8 20 00 ......Bluetooth Device (Personal Area Network) #2
 27...50 eb f6 b0 a7 00 ......Realtek Gaming 2.5GbE Family Controller
  1...........................Software Loopback Interface 1
 35...00 15 5d cb a0 21 ......Hyper-V Virtual Ethernet Adapter
===========================================================================

IPv4 таблица маршрута
===========================================================================
Активные маршруты:
Сетевой адрес           Маска сети      Адрес шлюза       Интерфейс  Метрика
          0.0.0.0          0.0.0.0     192.168.31.1   192.168.31.202     30
          0.0.0.0          0.0.0.0         On-link          10.8.1.1      5
         10.8.1.1  255.255.255.255         On-link          10.8.1.1    261
      10.147.19.0    255.255.255.0         On-link     10.147.19.124    257
    10.147.19.124  255.255.255.255         On-link     10.147.19.124    257
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  146.103.117.145  255.255.255.255     192.168.31.1    192.168.31.72  24213
     192.168.31.0    255.255.255.0         On-link    192.168.31.202    286
   192.168.31.255  255.255.255.255         On-link    192.168.31.202    286
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331

Краткий онбординг для понимания

Вывод команды route print состоит из 2 таблиц:

  • Список интерфейсов — это все устройства которые участвуют в таблице маршрутизации, виртуальные или физические.

  • IPv4 таблица маршрута — это сама таблица маршрутизации.

Список интерфейсов

Сетевой интерфейс это физическое или виртуальное устройство которое отвечает за передачу пакетов данных. Вы наверняка видели их визуальное представление в GUI windows заглядывая сюда:

Панель управления →
    Сеть и Интернет →
        Центр управления сетями и общим доступом →
            Изменение параметров адаптера

Подробнее можно почитать если поискать NIV и vNIC.

Если рассмотреть мой список интерфейсов можно увидеть его индекс и MAC адрес:

 31...6a b3 51 82 3f b3 ......ZeroTier Virtual Port
 75...........................WireGuard Tunnel
 30...1e 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #5
 18...1c 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #6
 32...dc 21 5c 03 76 6d ......Intel(R) Wi-Fi 6 AX201 160MHz
 29...1c 61 b4 45 ad 50 ......TP-Link Wireless MU-MIMO USB Adapter
 19...e8 48 b8 c8 20 00 ......Bluetooth Device (Personal Area Network) #2
 27...50 eb f6 b0 a7 00 ......Realtek Gaming 2.5GbE Family Controller
  1...........................Software Loopback Interface 1
 35...00 15 5d cb a0 21 ......Hyper-V Virtual Ethernet Adapter

Первая колонка значений 64, 30, 18 и тд. — это индекс интерфейса. Дальше следует MAC адрес. Некоторые виртуальные интерфейсы (особенно работающие на 3-м уровне OSI) могут не иметь MAC-адреса — они сразу заметны в списке.

Комментарии к каждому из них

35...00 15 5d cb a0 21 ......Hyper-V Virtual Ethernet Adapter

Индекс — 35, MAC адрес — 00 15 5d cb a0 21

Если вы устанавливали Docker, то у вас есть такой же. Docker использует его для множества своих фич, например: проброс портов, связь контейнеров друг с другом, доступ в интернет из контейнеров и др.

1...........................Software Loopback Interface 1

Под индексом 1 и без MAC адреса мы видим виртуальный интерфейс. Он создается ОС в самом начале еще до того как добавили какие-то физические устройства и накатили к ним драйвера.
Это особенный интерфейс, его называют loopback, IP-адрес 127.0.0.1 (доменное имя localhost). Подробнее можно почитать в первоисточники RFC-5735

27...50 eb f6 b0 a7 00 ......Realtek Gaming 2.5GbE Family Controller

Индекс — 27, MAC адрес — 50 eb f6 b0 a7 00

Сетевая карта с 1 физическим LAN кабелем для проводного интернета (я ее не использую, только WiFi)

19...e8 48 b8 c8 20 00 ......Bluetooth Device (Personal Area Network) #2

Bluetooth для беспроводных устройств тоже кстати часть сетевой инфраструктуры вашего ПК. Можете использовать свой такой в связке с перехватчиками пакетов (например wireshark) чтобы продебажить почему черт возьми ваши наушники подключаются только с 3-го раза и охотнее определяется соседский холодильник.

29...1c 61 b4 45 ad 50 ......TP-Link Wireless MU-MIMO USB Adapter

Индекс — 29, MAC: 1c 61 b4 45 ad 50

Это USB WiFi-адаптер. Использую его вместо встроенного модуля, так как он лучше ловит сигнал. Проблема в том, что он периодически отваливается, и система переключается на встроенный (32-й интерфейс), у которого скорость заметно ниже.

Тот самый встроенный Wi-Fi модуль соединения:

32...dc 21 5c 03 76 6d ......Intel(R) Wi-Fi 6 AX201 160MHz

Индекс — 32, MAC адрес — dc 21 5c 03 76 6d

30...1e 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #5 18...1c 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #6

Выглядит как какой-то мусор, но заметно что очень похожий MAC адрес. А 1c 61 b4 45 ad 50 и вовсе точно совпадает с интерфейсом:

29...1c 61 b4 45 ad 50 ......TP-Link Wireless MU-MIMO USB Adapter

Значит эти интерфейсы связаны с USB антенной Wi-Fi.

64...........................WireGuard Tunnel

Индекс — 64, MAC адрес - отсутствует

Этот виртуальный интерфейс присутствует так как установлена Amnezia VPN, именно его она и использует.

31...6a b3 51 82 3f b3 ......ZeroTier Virtual Port

Индекс — 31, MAC адрес — 6a b3 51 82 3f b3

ZeroTier — В двух словах это виртуальная локальная сеть через интернет. Я его использовал как аналог корпоративного VPN для доступа к локальной сети офиса. Его намного быстрее и проще можно настроить чем возиться с конфигурацией Microtik (корпоративного офисного роутера).

Попросим AI помочь осознать происходящее и составить табличку MD. Итого моя сетевая конфигурация ПК состоит из:

4 физических интерфейсов:

Индекс

Интерфейс

Назначение

Статус

27

Realtek Gaming 2.5GbE Family Controller

Проводной интернет (LAN)

Не используется

32

Intel(R) Wi-Fi 6 AX201 160MHz

Встроенный Wi-Fi модуль

Резервный — подхватывает соединение, когда отваливается USB-адаптер

29

TP-Link Wireless MU-MIMO USB Adapter

Внешний USB Wi-Fi адаптер

Основной для выхода в интернет

19

Bluetooth Device (PAN) #2

Bluetooth-соединения

Активен

6 виртуальных интерфейсов:

Индекс

Интерфейс

Назначение

1

Software Loopback Interface

Системный loopback (127.0.0.1 / localhost) — создаётся ОС, используется для внутренней коммуникации процессов

35

Hyper-V Virtual Ethernet Adapter

Виртуальный коммутатор для Docker-контейнеров (проброс портов, связь контейнеров, доступ в интернет)

75

WireGuard Tunnel

VPN-туннель для Amnezia VPN — работает на 3-м уровне OSI, поэтому без MAC-адреса

31

ZeroTier Virtual Port

Виртуальная локальная сеть через интернет — замена корпоративного VPN для доступа к офисной сети

30

Microsoft Wi-Fi Direct Virtual Adapter #5

Служебный адаптер, привязанный к USB Wi-Fi антенне (TP-Link) — используется Windows для Wi-Fi Direct (раздача интернета, Miracast и т.д.)

18

Microsoft Wi-Fi Direct Virtual Adapter #6

Аналогично #5 — второй служебный адаптер от того же физического устройства

Если визуализировать, то картина такая:

Резюмируя: из 10 интерфейсов реально задействованы в повседневной работе 3–4: USB Wi-Fi адаптер как основной канал в интернет, WireGuard для VPN, Docker/Hyper-V для контейнеров, и loopback как неотъемлемая часть любой ОС. Остальные — либо резервные (встроенный Intel Wi-Fi), либо служебные (Wi-Fi Direct адаптеры), либо неиспользуемые (Realtek LAN), либо ситуативные (ZeroTier, Bluetooth).

IPv4 таблица маршрутов

С интерфейсами разобрались, теперь про саму таблицу маршрутизации.

  • Сетевой адрес — куда летит пакет (целевой IP).

  • Маска сети — какая часть адреса должна совпадать:

  • 255.255.255.255 — только точный IP.

  • 255.255.255.0 — совпадают первые 3 октета, последний — любой (весь диапазон x.x.x.0–255).

  • 0.0.0.0 — всё что угодно (маршрут по умолчанию).

  • Адрес шлюза — куда отправить пакет. On-link = напрямую в той же подсети, что и интерфейс. ARP (L2), б��з шлюза (L3). Кто хочет углубиться читайте про ARP маршрутизацию, сети L2 и L3.

  • Интерфейс — через какой сетевой адаптер отправить. Чтобы углубиться читайте про NIC и vNIC.

  • Метрика — приоритет маршрута (чем меньше — тем приоритетнее). Если читают front-end разработчики - это как Z-index в CSS только инвертированно.

  • Шлюз - это "следующий прыжок": устройство (обычно роутер), которому передаётся пакет, если получатель не в той же локальной сети. Он уже сам разберётся, куда отправить дальше. В моем случае 192.168.31.1 это мой wifi роутер.

Amnezia при установке создала виртуальный интерфейс с адресом 10.8.1.1. В выводе из route print он называется:

64...........................WireGuard Tunnel

Правило

Сетевой адрес    Маска сети      Адрес шлюза      Интерфейс     Метрика
0.0.0.0          0.0.0.0         On-link          10.8.1.1      5

Гласит о том что весь трафик будет идти через этот интерфейс (5 самая низкая метрика из всех имеющихся).

Правило

146.103.117.145    255.255.255.255    192.168.31.1    192.168.31.72    24213

Amnezia автоматически добавляет маршрут к IP-адресу VPN-сервера через ваш обычный шлюз, чтобы избежать зацикливания трафика.

Правим таблицу маршрутизации, чтобы работал VPN и доступ по SSH к ноутбуку

Нужно добавить постоянный маршрут который переопределит это правило даже с включенным VPN:

route -p add 192.168.31.197 mask 255.255.255.255 192.168.31.1 metric 1

Это заставит 192.168.31.197 всегда ходить через локальную сеть, минуя VPN. Иными словами по этому маршруту все пакеты будут идти не через интерфейс Amnezia, а через мой роутер. чтобы команда выполнилась нужно запустить cmd с правами администратора.

Флаг -p делает маршрут постоянным (persistent), то есть устойчивым к перезагрузке ПК, он будет храниться в реестре windows:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\PersistentRoutes.

Подробнее можно почитать в документации команды route.

Команда выполнена, проверяем. При включенном VPN что-то по-прежнему блочит доступ, но теперь уже не timeout а connection refuse. У Amnezia есть режим Kill-Switch который включен по умолчанию, возможно он как раз и разрывает соединение. У меня много всякого в правилах фаервола винды и дебажить их через виндовский UI дело неблагодарное. По этому поступим следующим образом.

Сохраняем в файл все правила firewall:

netsh advfirewall firewall show rule name=all > firewall-output.txt

Теперь в файле любым текстовым редактором можем искать ключевые слова: amnezia, интересующий нас IP адрес и тд. Хотелось бы сказать что я сразу увидел проблему и устранил ее простыми действиями, но этого не произошло. Никаких явных правил препятствующих подключению я не вижу.

Тупик

На этом этапе я оказался в неприятной ситуации, так как я не мог подключиться к своему ноутбуку и не понимал в чем проблема. Настоящий удар по самооценке и уверенности в своих профессиональных навыках.

Придется вернуться на несколько шагов назад и попробовать снова.

Раз мы пошли более низкоуровневым путем стоило сразу откатить попытку использовать Split tunneling Amnezia, возможно она влияет на что-то чего я не учитываю. Сделаю это сейчас и вообще отключу эту функцию через UI:

Split tunneling enabled → Site-based split tunneling → disabled

Так же я удалил старые постоянные пути в таблице маршрутизации. Отключаем Amnezia и пытаемся подключиться к ноутбуку.

$ ssh gtosss@192.168.31.197
ssh: connect to host 192.168.31.197 port 22: Connection refused

Теперь нет соединения даже с выключенным VPN. Причем ошибка Connection refused, а не timeout. Если я постучусь на адрес шлюза (к роутеру) я получу такую же ошибку. В другую подсеть, на localhost - то же самое. Только попытка подключиться к 8.8.8.8 кидает Connection timed out

Сделаем трассировку маршрута посмотрим все узлы через которые проходит запрос:

tracert -d 192.168.31.197
$ tracert -d 192.168.31.197
Трассировка маршрута к 192.168.31.197 с максимальным числом прыжков 30
1     1 ms     1 ms     1 ms  192.168.31.1
2  192.168.31.1  сообщает: Заданный протокол недоступен.

Казалось бы запрос долетел до роутера. Но правда в том что утилитам windows - веры нет.

  1. ОС выбирает исходящий интерфейс на основе таблицы маршрутизации (метрики, приоритеты)

  2. Пакет отправляется через интерфейс A (например, виртуальный адаптер, туннель, bridge)

  3. Интерфейс A инкапсулирует/перенаправляет пакет куда-то ещё

  4. Где-то в сети промежуточный узел не может доставить пакет дальше

  5. Этот узел отправляет ICMP-ответ (TTL exceeded / Destination unreachable)

  6. ICMP-ответ возвращается через интерфейс B (может быть другим!)

  7. tracert видит IP источника ICMP-ответа и показывает его как узел

Суть проблемы:
Путь отправки ≠ Путь возврата ответа

Исходящий путь: ПК → [интерфейс X] → узел 1 → узел 2 → ...

Обратный путь: ... → узел 3 → узел 4 → [интерфейс Y] → ПК

tracert видит только источники ICMP-ответов. Они могут приходить с совершенно других узлов, чем те, через которые реально прошел пакет.

В linux мы бы выполнили:

ip route get 192.168.31.197

И узнали бы интерфейс. В Windows поможет только установка сторонних утилит по типу wireshark для действительно достоверного дебага. Но устанавливать пока мы его не будем.

На этом моменте я начал подозревать ZeroTier.

ipconfig

Смотрим ipconfig — нас интересует сетевой интерфейс ZeroTier. Запоминаем его ip.

$ ipconfig
...

Адаптер Ethernet ZeroTier One [8056c2e21c8e1b68]:

   DNS-суффикс подключения . . . . . : 
   Локальный IPv6-адрес канала . . . : fe80::645d:6ce4:1377:93c1%31
       IPv4-адрес. . . . . . . . . . . . : 10.147.19.124
   Маска подсети . . . . . . . . . . : 255.255.255.0
   Основной шлюз. . . . . . . . . : 25.255.255.254

Адаптер беспроводной локальной сети Intel wi-fi:

   DNS-суффикс подключения . . . . . : 
   IPv4-адрес. . . . . . . . . . . . : 192.168.31.202
   Маска подсети . . . . . . . . . . : 255.255.255.0
   Основной шлюз. . . . . . . . . : 192.168.31.1

Адаптер беспроводной локальной сети Беспроводная сеть:

   DNS-суффикс подключения . . . . . : 
   IPv4-адрес. . . . . . . . . . . . : 192.168.31.72
   Маска подсети . . . . . . . . . . : 255.255.255.0
   Основной шлюз. . . . . . . . . : 192.168.31.1

...
route print
Сетевой адрес           Маска сети      Адрес шлюза       Интерфейс  Метрика
          0.0.0.0          0.0.0.0     192.168.31.1   192.168.31.202     35
          0.0.0.0          0.0.0.0   25.255.255.254    10.147.19.124  10000
          0.0.0.0          0.0.0.0     192.168.31.1    192.168.31.72     35
      10.147.19.0    255.255.255.0         On-link     10.147.19.124    257
    10.147.19.124  255.255.255.255         On-link     10.147.19.124    257
    10.147.19.255  255.255.255.255         On-link     10.147.19.124    257
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331
     172.28.208.0    255.255.240.0         On-link      172.28.208.1   5256
     172.28.208.1  255.255.255.255         On-link      172.28.208.1   5256
   172.28.223.255  255.255.255.255         On-link      172.28.208.1   5256
    192.168.31.72  255.255.255.255         On-link     192.168.31.72    291
   192.168.31.202  255.255.255.255         On-link    192.168.31.202    291
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
        224.0.0.0        240.0.0.0         On-link    192.168.31.202    291
        224.0.0.0        240.0.0.0         On-link      172.28.208.1   5256
        224.0.0.0        240.0.0.0         On-link     10.147.19.124    257
        224.0.0.0        240.0.0.0         On-link     192.168.31.72    291
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link    192.168.31.202    291
  255.255.255.255  255.255.255.255         On-link      172.28.208.1   5256
  255.255.255.255  255.255.255.255         On-link     10.147.19.124    257
  255.255.255.255  255.255.255.255         On-link     192.168.31.72    291

Видим что множество правил указывают на интерфейс 10.147.19.124 ZeroTier. Все же необходимо добавить постоянное правило на все маршруты моей домашней локальной сети.

Попробовал так:

route -p add 192.168.31.0 mask 255.255.255.0 192.168.31.1 metric 1 if 29

Кстати, когда я впервые столкнулся с этой командой, мне как программисту показалось что if — это какое-то условие, но это оказывается сокращение от "interface".

Удалил:

route -p delete 192.168.31.0 mask 255.255.255.0 192.168.31.1

Пробую другой интерфейс:

route -p add 192.168.31.0 mask 255.255.255.0 192.168.31.1 metric 1 if 32

29 - это Wi-Fi USB устройство.

32 - это встроенное устройства в системнике для WiFi.

Не помогло ни то, ни другое. Перезагрузил комп.

$ ssh gtosss@192.168.31.197
gtosss@192.168.31.197's password:

Все работает, в чем была проблема — останется загадкой тысячелетия. А вот с включенным VPN: timed out.

Смотрю Таблицу маршрутизации.
===========================================================================
Список интерфейсов
 29...6a b3 51 82 3f b3 ......ZeroTier Virtual Port
  2...........................WireGuard Tunnel
 28...1e 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #5
 17...1c 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #6
 30...dc 21 5c 03 76 6d ......Intel(R) Wi-Fi 6 AX201 160MHz
 27...1c 61 b4 45 ad 50 ......TP-Link Wireless MU-MIMO USB Adapter
 18...e8 48 b8 c8 20 00 ......Bluetooth Device (Personal Area Network) #2
 26...50 eb f6 b0 a7 00 ......Realtek Gaming 2.5GbE Family Controller
  1...........................Software Loopback Interface 1
 61...00 15 5d 01 3a 00 ......Hyper-V Virtual Ethernet Adapter
===========================================================================

IPv4 таблица маршрута
===========================================================================
Активные маршруты:
Сетевой адрес           Маска сети      Адрес шлюза       Интерфейс  Метрика
          0.0.0.0          0.0.0.0   25.255.255.254    10.147.19.124  10000
          0.0.0.0          0.0.0.0     192.168.31.1    192.168.31.72     35
          0.0.0.0          0.0.0.0     192.168.31.1   192.168.31.202     35
          0.0.0.0          0.0.0.0         On-link          10.8.1.1      5
         10.8.1.1  255.255.255.255         On-link          10.8.1.1    261
      10.147.19.0    255.255.255.0         On-link     10.147.19.124    257
      10.147.19.0    255.255.255.0         On-link          10.8.1.1      5
    10.147.19.124  255.255.255.255         On-link     10.147.19.124    257
    10.147.19.124  255.255.255.255         On-link          10.8.1.1      5
    10.147.19.255  255.255.255.255         On-link     10.147.19.124    257
    10.147.19.255  255.255.255.255         On-link          10.8.1.1    261
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  146.103.117.145  255.255.255.255     192.168.31.1    192.168.31.72  24213
      172.17.64.0    255.255.240.0         On-link       172.17.64.1   5256
      172.17.64.0    255.255.240.0         On-link          10.8.1.1      5
      172.17.64.1  255.255.255.255         On-link       172.17.64.1   5256
      172.17.64.1  255.255.255.255         On-link          10.8.1.1      5
    172.17.79.255  255.255.255.255         On-link       172.17.64.1   5256
    172.17.79.255  255.255.255.255         On-link          10.8.1.1    261
     192.168.31.0    255.255.255.0         On-link     192.168.31.72    291
     192.168.31.0    255.255.255.0         On-link    192.168.31.202    291
     192.168.31.0    255.255.255.0         On-link          10.8.1.1      5
    192.168.31.72  255.255.255.255         On-link     192.168.31.72    291
    192.168.31.72  255.255.255.255         On-link          10.8.1.1      5
   192.168.31.202  255.255.255.255         On-link    192.168.31.202    291
   192.168.31.202  255.255.255.255         On-link          10.8.1.1      5
   192.168.31.255  255.255.255.255         On-link     192.168.31.72    291
   192.168.31.255  255.255.255.255         On-link    192.168.31.202    291
   192.168.31.255  255.255.255.255         On-link          10.8.1.1    261
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
        224.0.0.0        240.0.0.0         On-link    192.168.31.202    291
        224.0.0.0        240.0.0.0         On-link       172.17.64.1   5256
        224.0.0.0        240.0.0.0         On-link     192.168.31.72    291
        224.0.0.0        240.0.0.0         On-link     10.147.19.124    257
        224.0.0.0        240.0.0.0         On-link          10.8.1.1    261
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link    192.168.31.202    291
  255.255.255.255  255.255.255.255         On-link       172.17.64.1   5256
  255.255.255.255  255.255.255.255         On-link     192.168.31.72    291
  255.255.255.255  255.255.255.255         On-link     10.147.19.124    257
  255.255.255.255  255.255.255.255         On-link          10.8.1.1    261
===========================================================================

Постоянные маршруты:
  Отсутствует

Так как перезагрузка помогла, я снова решил попробовать:

route -p add 192.168.31.0 mask 255.255.255.0 192.168.31.1 metric 1 if 29

Но я вовремя заметил — какой еще 29? 29 это ZeroTier, а нам нужен WiFi адаптер. Боже будь проклята винда. Как мне управлять таблицей маршрутизации если в любой момент могут поменяться индексы интерфейсов.

Ладно, спокойно. Чтобы не гадать на кофейной гуще, посмотрим актуальные индексы интерфейсов прямо сейчас:

netsh interface ipv4 show interfaces
Инд     Мет         MTU          Состояние               Имя
---  ----------  ----------  ------------  ---------------------------
  1          75  4294967295  connected     Loopback Pseudo-Interface 1
  2           5        1376  connected     AmneziaVPN
 30          35        1500  connected     Intel wi-fi
 29           1        2800  connected     ZeroTier One [8056c2e21c8e1b68]
 27          35        1500  connected     Беспроводная сеть
 28          25        1500  disconnected  Подключение по локальной сети* 2
 17          25        1500  disconnected  Подключение по локальной сети* 14
 26          75        1500  disconnected  Realtek Gaming
 61        5000        1500  connected     vEthernet (Default Switch)
 18          65        1500  disconnected  Сетевое подключение Bluetooth 2

Ну конечно — после перезагрузки интерфейсы перетасовались как карты в колоде.

И вот оно — if 29, в который я слал трафик, это ZeroTier с его MTU 2800 и метрикой 1.

А WiFi-адаптеры, через которые я реально сижу в локалке — это индекс 27 («Беспроводная сеть») и 30 («Intel wi-fi»). AmneziaVPN висит на индексе 2 с метрикой 5 — минимальной среди всех, а значит Windows будет отдавать ему предпочтение для любого маршрута при прочих равных.

В прошлый раз я наугад тыкал в номера, отправляя локальный трафик прямиком в ZeroTier-туннель — поэтому не работало. Ладно, теперь я точно знаю куда целиться. Добавляю маршрут с правильным интерфейсом:

route -p add 192.168.31.0 mask 255.255.255.0 192.168.31.1 metric 1 if 27

Включаю Amnezia. Пробую подключиться к ноутбуку. И — тишина. Снова Connection timed out.

Смотрю в таблицу маршрутизации.
===========================================================================
Список интерфейсов
 29...6a b3 51 82 3f b3 ......ZeroTier Virtual Port
  2...........................WireGuard Tunnel
 28...1e 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #5
 17...1c 61 b4 45 ad 50 ......Microsoft Wi-Fi Direct Virtual Adapter #6
 30...dc 21 5c 03 76 6d ......Intel(R) Wi-Fi 6 AX201 160MHz
 27...1c 61 b4 45 ad 50 ......TP-Link Wireless MU-MIMO USB Adapter
 18...e8 48 b8 c8 20 00 ......Bluetooth Device (Personal Area Network) #2
 26...50 eb f6 b0 a7 00 ......Realtek Gaming 2.5GbE Family Controller
  1...........................Software Loopback Interface 1
 61...00 15 5d 01 3a 00 ......Hyper-V Virtual Ethernet Adapter
===========================================================================

IPv4 таблица маршрута
===========================================================================
Активные маршруты:
Сетевой адрес           Маска сети      Адрес шлюза       Интерфейс  Метрика
          0.0.0.0          0.0.0.0   25.255.255.254    10.147.19.124  10000
          0.0.0.0          0.0.0.0     192.168.31.1    192.168.31.72     35
          0.0.0.0          0.0.0.0     192.168.31.1   192.168.31.202     35
          0.0.0.0          0.0.0.0         On-link          10.8.1.1      5
         10.8.1.1  255.255.255.255         On-link          10.8.1.1    261
      10.147.19.0    255.255.255.0         On-link     10.147.19.124    257
      10.147.19.0    255.255.255.0         On-link          10.8.1.1      5
    10.147.19.124  255.255.255.255         On-link     10.147.19.124    257
    10.147.19.124  255.255.255.255         On-link          10.8.1.1      5
    10.147.19.255  255.255.255.255         On-link     10.147.19.124    257
    10.147.19.255  255.255.255.255         On-link          10.8.1.1    261
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  146.103.117.145  255.255.255.255     192.168.31.1    192.168.31.72  24213
      172.17.64.0    255.255.240.0         On-link       172.17.64.1   5256
      172.17.64.0    255.255.240.0         On-link          10.8.1.1      5
      172.17.64.1  255.255.255.255         On-link       172.17.64.1   5256
      172.17.64.1  255.255.255.255         On-link          10.8.1.1      5
    172.17.79.255  255.255.255.255         On-link       172.17.64.1   5256
    172.17.79.255  255.255.255.255         On-link          10.8.1.1    261
     192.168.31.0    255.255.255.0         On-link     192.168.31.72    291
     192.168.31.0    255.255.255.0         On-link    192.168.31.202    291
     192.168.31.0    255.255.255.0         On-link          10.8.1.1      5
     192.168.31.0    255.255.255.0     192.168.31.1    192.168.31.72     36
    192.168.31.72  255.255.255.255         On-link     192.168.31.72    291
    192.168.31.72  255.255.255.255         On-link          10.8.1.1      5
   192.168.31.202  255.255.255.255         On-link    192.168.31.202    291
   192.168.31.202  255.255.255.255         On-link          10.8.1.1      5
   192.168.31.255  255.255.255.255         On-link     192.168.31.72    291
   192.168.31.255  255.255.255.255         On-link    192.168.31.202    291
   192.168.31.255  255.255.255.255         On-link          10.8.1.1    261
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
        224.0.0.0        240.0.0.0         On-link    192.168.31.202    291
        224.0.0.0        240.0.0.0         On-link       172.17.64.1   5256
        224.0.0.0        240.0.0.0         On-link     192.168.31.72    291
        224.0.0.0        240.0.0.0         On-link     10.147.19.124    257
        224.0.0.0        240.0.0.0         On-link          10.8.1.1    261
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link    192.168.31.202    291
  255.255.255.255  255.255.255.255         On-link       172.17.64.1   5256
  255.255.255.255  255.255.255.255         On-link     192.168.31.72    291
  255.255.255.255  255.255.255.255         On-link     10.147.19.124    257
  255.255.255.255  255.255.255.255         On-link          10.8.1.1    261
===========================================================================
Постоянные маршруты:
  Сетевой адрес            Маска    Адрес шлюза      Метрика
     192.168.31.0    255.255.255.0     192.168.31.1       1

Вижу уже знакомую картину: VPN-клиент при подключении добавил маршрут 192.168.31.0/24 (пишу для краткости в CIDR-нотации) через интерфейс 10.8.1.1 с метрикой 5, которая вроде бы проигрывает моей метрике 1... Но Windows — это Windows. Amnezia при подключении клонирует все обнаруженные локальные маршруты на свой интерфейс, помечая их как On-link. Система видит два конкурирующих маршрута на одну и ту же подсеть — и выбирает VPN, потому что метрика интерфейса AmneziaVPN (5) ниже метрики WiFi-интерфейса (35), и Windows суммирует метрику маршрута с метрикой интерфейса. Мой metric 1 на маршруте превращается в 1 + 35 = 36, а VPN-овский маршрут с metric 5 на интерфейсе с метрикой 5 даёт 5 + 5 = 10. Пакет к 192.168.31.197 улетает в VPN-туннель, заворачивается на VPS-сервер, который понятия не имеет о моей домашней сети, и пакет тихо умирает где-то в этой цепочке.

Но прежде чем решать эту проблему, разберёмся с другой — нестабильные индексы интерфейсов. Команда route add ... if <число> привязана к индексу, который Windows может перетасовать после перезагрузки, обновления драйвера или переподключения адаптера. Я проконсультировался с AI и погуглил. Вместо route можно использовать netsh, который принимает имя интерфейса, например:

netsh interface ipv4 add route 192.168.31.0/24 "Беспроводная сеть" 192.168.31.1 metric=1 store=persistent

Имя интерфейса на русском языке, с пробелами, в кавычках, в командной строке Windows. Каждый символ этой команды причиняет мне физическую боль. В Linux это wlan0 — четыре символа, ASCII, никаких кавычек, никаких сюрпризов. Здесь же я вынужден писать "Беспроводная сеть" и молиться, что Windows не решит в один прекрасный день локализовать это имя ещё раз, или что очередное обновление драйвера не припишет к нему 2 на конце. Но выбор невелик:

  • либо хрупкие числовые индексы, которые тасуются при каждой перезагрузке.

  • либо строковые имена на кириллице, от которых хочется выйти из терминала и из IT.

Выбираю меньшее зло — хотя бы имя я могу переименовать руками во что-то вменяемое и предсказуемое.

netsh interface set interface name="Беспроводная сеть" newname="wifi-native"
netsh interface set interface name="Intel wi-fi" newname="wifi-usb"

Проверяем:

netsh interface ipv4 show interfaces
Инд     Мет         MTU          Состояние               Имя
---  ----------  ----------  ------------  ---------------------------
  1          75  4294967295  connected     Loopback Pseudo-Interface 1
  2           5        1376  connected     AmneziaVPN
 30          35        1500  connected     wifi-usb
 29           1        2800  connected     ZeroTier One [8056c2e21c8e1b68]
 27          35        1500  connected     wifi-native
 28          25        1500  disconnected  Подключение по локальной сети* 2
 17          25        1500  disconnected  Подключение по локальной сети* 14
 26          75        1500  disconnected  Realtek Gaming
 61        5000        1500  connected     vEthernet (Default Switch)
 18          65        1500  disconnected  Сетевое подключение Bluetooth 2

Уже лучше. Теперь добавляем маршрут почеловечески:

netsh interface ipv4 add route 192.168.31.0/24 "wifi-usb" 192.168.31.1 metric=1 store=persistent

Параметр store=persistent — аналог флага -p у route, маршрут сохранится после перезагрузки.

При выключенном VPN — работает, что насчет включенного:

$ ssh root@192.168.31.197
ssh: connect to host 192.168.31.197 port 22: Connection timed out

Консультации с AI и google. К чему пришел — метрика маршрута 1 ничего не решает, потому что Windows суммирует её с метрикой интерфейса. Мой маршрут: 1 (route) + 35 (interface) = 36. VPN-овский маршрут: 5 (route) + 5 (interface) = 10. Десять меньше тридцати шести — VPN побеждает, пакет улетает в туннель, и никакие пляски с metric=1 этого не изменят. Но есть козырь, который бьёт любую метрику: длина префикса. В маршрутизации действует правило Longest prefix match — более специфичный маршрут всегда выигрывает у менее специфичного, вне зависимости от метрик. Маршрут на /32 (конкретный хост) всегда победит маршрут на /24 (подсеть). Вместо того чтобы воевать за всю подсеть 192.168.31.0/24, я могу прописать маршрут конкретно до ноутбука:

Что за длина префикса?

IP-адрес в битах — это строка из 32 символов. «Префикс» значит «то, что стоит в начале».

192.168.31.197 в битах: 11000000.10101000.00011111.11000101.

При /24 (CIDR-нотации) фиксируются первые 24 бита — это и есть префикс (сетевая часть):

 11000000.10101000.00011111 . 11000101
├────── префикс (24) ──────┤ ├─ хост ─┤
    сеть — одна для всех       у каждого свой

При /32

 11000000.10101000.00011111.11000101
├───────── префикс (все 32) ────────┤
хостовая часть — 0 бит

Longest prefix match

Теперь понятно почему правило так называется — «совпадение по самому длинному префиксу». Маршрутизатор сравнивает начало адреса назначения с префиксами всех маршрутов и выбирает тот, где совпало больше бит от начала:

  • /32 — совпали все 32 бита от начала → точнее некуда

  • /24 — совпали первые 24 бита → менее точно

  • /0 — совпало 0 бит → подходит вообще всё (default route)

Прежде чем пробовать что-то новое — уберём за собой. Старый маршрут на /24 всё ещё висит в таблице и только мешает:

netsh interface ipv4 delete route 192.168.31.0/24 "wifi-usb" 192.168.31.1

Воспользуемся PowerShell, чтобы увидеть таблицу интерфейсов и IP адресов:

Get-NetIPAddress | Format-Table InterfaceAlias, IPAddress, PrefixLength, AddressFamily
InterfaceAlias                    IPAddress                    PrefixLength AddressFamily
--------------                    ---------                    ------------ -------------
Сетевое подключение Bluetooth 2   fe80::9ece:c252:79d7:fd2f%18           64          IPv6
vEthernet (Default Switch)        fe80::e04:5b3d:d71b:138a%61            64          IPv6
Подключение по локальной сети* 14 fe80::1045:57d3:4107:948%17            64          IPv6
Подключение по локальной сети* 2  fe80::41ac:2621:d23d:c0a0%28           64          IPv6
ZeroTier One [8056c2e21c8e1b68]   fe80::645d:6ce4:1377:93c1%29           64          IPv6
AmneziaVPN                        fd58:baa6:dead::1                     128          IPv6
Loopback Pseudo-Interface 1       ::1                                   128          IPv6
Сетевое подключение Bluetooth 2   169.254.143.30                         16          IPv4
vEthernet (Default Switch)        172.17.64.1                            20          IPv4
Realtek Gaming                    192.168.1.1                            24          IPv4
Realtek Gaming                    169.254.122.133                        16          IPv4
Подключение по локальной сети* 14 169.254.205.132                        16          IPv4
Подключение по локальной сети* 2  169.254.100.181                        16          IPv4
wifi-native                       192.168.31.72                          24          IPv4
ZeroTier One [8056c2e21c8e1b68]   10.147.19.124                          24          IPv4
wifi-usb                          192.168.31.202                         24          IPv4
AmneziaVPN                        10.8.1.1                               32          IPv4
Loopback Pseudo-Interface 1       127.0.0.1                               8          IPv4

Чтобы избавиться от неопределенности, какой же интерфейс у меня в данный момент обеспечивает связь выключим wifi-native:

netsh interface set interface "wifi-native" disable

Интернет работать не перестал — уже хорошо. Доступы к ноутбуку по локалке работают. Под VPN по-прежнему нет.

Кстати таблица маршрутизации теперь выглядит намного чище, больше нет каких-то непонятных интерфейсов.
===========================================================================
Список интерфейсов
 29...6a b3 51 82 3f b3 ......ZeroTier Virtual Port
  2...........................WireGuard Tunnel
 30...dc 21 5c 03 76 6d ......Intel(R) Wi-Fi 6 AX201 160MHz
 18...e8 48 b8 c8 20 00 ......Bluetooth Device (Personal Area Network) #2
 26...50 eb f6 b0 a7 00 ......Realtek Gaming 2.5GbE Family Controller
  1...........................Software Loopback Interface 1
 61...00 15 5d 01 3a 00 ......Hyper-V Virtual Ethernet Adapter
===========================================================================

IPv4 таблица маршрута
===========================================================================
Активные маршруты:
Сетевой адрес           Маска сети      Адрес шлюза       Интерфейс  Метрика
          0.0.0.0          0.0.0.0   25.255.255.254    10.147.19.124  10000
          0.0.0.0          0.0.0.0     192.168.31.1   192.168.31.202     35
          0.0.0.0          0.0.0.0         On-link          10.8.1.1      5
         10.8.1.1  255.255.255.255         On-link          10.8.1.1    261
      10.147.19.0    255.255.255.0         On-link     10.147.19.124    257
      10.147.19.0    255.255.255.0         On-link          10.8.1.1      5
    10.147.19.124  255.255.255.255         On-link     10.147.19.124    257
    10.147.19.124  255.255.255.255         On-link          10.8.1.1      5
    10.147.19.255  255.255.255.255         On-link     10.147.19.124    257
    10.147.19.255  255.255.255.255         On-link          10.8.1.1    261
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  146.103.117.145  255.255.255.255     192.168.31.1   192.168.31.202  24213
      172.17.64.0    255.255.240.0         On-link       172.17.64.1   5256
      172.17.64.0    255.255.240.0         On-link          10.8.1.1      5
      172.17.64.1  255.255.255.255         On-link       172.17.64.1   5256
      172.17.64.1  255.255.255.255         On-link          10.8.1.1      5
    172.17.79.255  255.255.255.255         On-link       172.17.64.1   5256
    172.17.79.255  255.255.255.255         On-link          10.8.1.1    261
     192.168.31.0    255.255.255.0         On-link    192.168.31.202    291
     192.168.31.0    255.255.255.0         On-link          10.8.1.1      5
   192.168.31.202  255.255.255.255         On-link    192.168.31.202    291
   192.168.31.202  255.255.255.255         On-link          10.8.1.1      5
   192.168.31.255  255.255.255.255         On-link    192.168.31.202    291
   192.168.31.255  255.255.255.255         On-link          10.8.1.1    261
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
        224.0.0.0        240.0.0.0         On-link    192.168.31.202    291
        224.0.0.0        240.0.0.0         On-link       172.17.64.1   5256
        224.0.0.0        240.0.0.0         On-link     10.147.19.124    257
        224.0.0.0        240.0.0.0         On-link          10.8.1.1    261
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link    192.168.31.202    291
  255.255.255.255  255.255.255.255         On-link       172.17.64.1   5256
  255.255.255.255  255.255.255.255         On-link     10.147.19.124    257
  255.255.255.255  255.255.255.255         On-link          10.8.1.1    261
===========================================================================
Постоянные маршруты:
  Отсутствует
Тоже самое с ipconfig

Настройка протокола IP для Windows


Адаптер Ethernet ZeroTier One [8056c2e21c8e1b68]:

   DNS-суффикс подключения . . . . . :
   Локальный IPv6-адрес канала . . . : fe80::645d:6ce4:1377:93c1%29
   IPv4-адрес. . . . . . . . . . . . : 10.147.19.124
   Маска подсети . . . . . . . . . . : 255.255.255.0
   Основной шлюз. . . . . . . . . : 25.255.255.254

Неизвестный адаптер AmneziaVPN:

   DNS-суффикс подключения . . . . . : .
   IPv6-адрес. . . . . . . . . . . . : fd58:baa6:dead::1
   Основной шлюз. . . . . . . . . : ::
                                       0.0.0.0

Адаптер беспроводной локальной сети wifi-usb:

   DNS-суффикс подключения . . . . . :
   IPv4-адрес. . . . . . . . . . . . : 192.168.31.202
   Маска подсети . . . . . . . . . . : 255.255.255.0
   Основной шлюз. . . . . . . . . : 192.168.31.1

Адаптер Ethernet Сетевое подключение Bluetooth 2:

   Состояние среды. . . . . . . . : Среда передачи недоступна.
   DNS-суффикс подключения . . . . . :

Адаптер Ethernet Realtek Gaming:

   Состояние среды. . . . . . . . : Среда передачи недоступна.
   DNS-суффикс подключения . . . . . :

Адаптер Ethernet vEthernet (Default Switch):

   DNS-суффикс подключения . . . . . :
   Локальный IPv6-адрес канала . . . : fe80::e04:5b3d:d71b:138a%61
   IPv4-адрес. . . . . . . . . . . . : 172.17.64.1
   Маска подсети . . . . . . . . . . : 255.255.240.0
   Основной шлюз. . . . . . . . . :

Самое время попробовать разыграть наш козырь — длину префикса.

netsh interface ipv4 add route 192.168.31.197/32 "wifi-usb" 192.168.31.1 metric=1 store=persistent

Теперь если глянуть в route print, можно увидеть новый постоянный маршрут:

Сетевой адрес   Маска               Адрес шлюза      Метрика
192.168.31.197  255.255.255.255     192.168.31.1     1

Соединение не происходит, даже при выключенном VPN. Связано это с тем, что подключение происходит через router, хотя ноутбук и стационарный ПК видят друг друга на уровне сегмента сети L2. По этому выбросим из этой цепочки наш роутер.

Та же самая команда, но не указываем шлюз (gateway):

netsh interface ipv4 add route 192.168.31.197/32 "wifi-usb" metric=1 store=persistent

Теперь виден On-link в постоянных маршрутах при просмотре route print:

===========================================================================
Постоянные маршруты:
  Сетевой адрес            Маска    Адрес шлюза      Метрика
   192.168.31.197  255.255.255.255         On-link        1
===========================================================================

Без VPN подключение есть, с VPN: Connection timed out

Как я выяснил, Amnezia при подключении читает AllowedIPs где-то в конфиге. Если там 0.0.0.0/0 — т.е весь трафик через туннель — клиент сканирует все существующие маршруты и создаёт их дубликаты на VPN-интерфейсе с минимальной метрикой. Включая только что добавленный /32. Так задумано WireGuard, он гарантирует, что ничего не утечёт мимо туннеля.

Статические маршруты бессильны, потому что Amnezia клонирует всё, что видит, с метрикой, которую невозможно перебить без поломки VPN для остального трафика.

Через:

route print | findstr 192.168.31.197

Заметил что Amnezia всегда создает перехватчика для нашего исключения. По этому ничего не остается кроме как прибегнуть к старому способу со split tunneling, который я настроил в GUI Amnezia. И это сработало, с включенным VPN или без него, доступ есть.

Проблема решена. Почему не работало?

Я скормил всю статью (весь свой журнал действий) нейронке в надежде что она объяснит в чем была проблема. Но конкретной причины она мне так и не назвала, тезисно ее ответ примерно такой:

Изначально split tunneling не работал, потому что всё вокруг него было отравлено: в таблице маршрутизации висели persistent-маршруты на неправильные интерфейсы (ZeroTier вместо WiFi), два WiFi-адаптера в одной подсети с одинаковой метрикой создавали неоднозначность выбора пути, а система накопила грязное состояние из остатков предыдущих VPN-сессий и экспериментов. Split tunneling корректно исключал подсеть из туннеля — но пакет, выйдя из-под VPN, попадал в этот хаос и терялся. К моменту повторной попытки ты, сам того не осознавая, устранил все помехи: вычистил мусорные маршруты, отключил дублирующий WiFi-интерфейс, перезагрузил машину — и тот же самый переключатель в GUI Amnezia заработал как ни в чём не бывало.

Как бы там ни было — это первая победа. Хоть мы и навернули кругов, попутно мы немного прибрались и я теперь хотя бы понимаю как работает моя сетевая конфигурация на стационарном ПК.

Итоговая картинка моей сетевой конфигурации теперь выглядит так:

Ну а в следующей статье, мы продолжим реализовывать ту цель о которой я говорил в самом начале — использование своего собственного компа в качестве сервера, чтобы экономить на аренде VPS.


С вами был Тимофей.

Кто я?

Когда-то я был fullstack разработчиком и у меня даже есть публичный WakaTime, сейчас руководитель отдела разработки kkube.

Спасибо всем кто подписывается в телеге — это очень мотивирует делиться своим опытом и мнением.