Две вещи сообщают как одну неисправность: ноутбук перешёл в другую сеть Wi-Fi или кабель включили, пока Wi-Fi продолжал работать. Клиент по-прежнему говорит «подключено», значок выглядит здоровым, а туннель ничего не передаёт. Под поверхностью могут сдвинуться только три части состояния - связь, локальный адрес, маршрут по умолчанию - и то, какая сдвинулась, определяет, восстановится туннель сам или понадобится переподключение. Я проверяю их именно в этом порядке, потому что смена настроек учётной записи ни разу не исправила ни одну из них.

Связь, адрес и маршрут движутся независимо

Роуминг между точками доступа одной сети - обычно событие L2. Радио переассоциируется, интерфейс сохраняет адрес и шлюз, и ничего, от чего зависит туннель, не меняется, поэтому прогулка по большому офису иногда проходит незамеченной. Подключение к другому SSID - не это: старый интерфейс может упасть, DHCP выдаёт новый адрес, новый шлюз и новые резолверы, а внешний поток, который использовал туннель, перестаёт существовать.

Ethernet добавляет третью форму. Wi-Fi никогда не падает, поэтому событие связи вообще не срабатывает, но проводной интерфейс появляется со своим адресом и часто выигрывает маршрут по умолчанию по метрике. Туннель продолжает идти по пути, который уже не предпочтителен, или клиент держит свой сокет привязанным к той беспроводной сети, где начал. Из браузера оба выглядят одинаково: страницы замирают в тот момент, когда кабель щёлкает.

Поэтому первый вопрос не в том, изменился ли Wi-Fi. А в том, изменился ли адрес, к которому вы привязаны, или маршрут до конечной точки, пока туннель работал.

Внешний сокет привязан к адресу, который только что исчез

Каждый туннель - это внешний поток: локальный адрес и порт разговаривают с адресом и портом сервера. В Linux это UDP-сокет, привязанный к старому источнику; когда интерфейс, держащий адрес, удаляется, отправки либо падают с EADDRNOTAVAIL, либо уходят через новый интерфейс с источником, которого сервер никогда не видел.

Удалённая сторона держит свою привязку. SA IKEv2 без MOBIKE идентифицируется парой адресов, а OpenVPN сессия привязана к адресу партнёра, который она выучила, а сопоставление NAT принадлежит частному адресу, порту и публичному адресу, которые его создали. Перейдите за другой NAT, и каждый ответ уходит на сопоставление, которого больше нет. На вашей машине ничего не настроено неправильно; пятёрка указывает на сеть, которую вы покинули.

Прочитайте состояние, прежде чем строить теории:

  • ss -unp показывает локальный адрес и порт, которые каждый сокет туннеля действительно держит.
  • ip route get 203.0.113.10 печатает адрес источника и устройство, которые ядро использовало бы для конечной точки прямо сейчас.
  • wg show wg0 endpoints, swanctl --list-sas или журнал клиента показывает адрес партнёра, с которым удалённая сторона думает, что говорит.

Если адрес сокета и поиск маршрута не совпадают, вы нашли разрыв, и никакая смена учётных данных его не затронет.

Что каждый протокол делает с новым адресом источника

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

TunnelRecovery behaviourFailure signature
WireGuardUpdates the peer endpoint when an authenticated packet arrives from a new address; no handshake needed if traffic continues.Handshake current, no return traffic; wg show still lists the old endpoint.
IKEv2/IPsecMOBIKE (RFC 4555) moves the SA to the new address; without it the responder discards packets from an unknown source.DPD or keepalive timeouts, then a full rekey or a dead SA.
OpenVPN over UDP--float accepts a packet from a new source mid-session; otherwise the session stays tied to the original peer address.Idle until ping-restart fires, then a visible reconnect.
OpenVPN over TCPThe tunnel is a byte stream, so a changed source address breaks it outright.Immediate reset and a new connection attempt.

Правило роуминга WireGuard работает только в одну сторону: клиент должен первым отправить с нового адреса. Сокет, всё ещё привязанный к старому интерфейсу, никогда этого не делает, поэтому туннель может выглядеть живым, пока его таймер рукопожатия стареет. описание протокола точно указывает условие обновления конечной точки, и его стоит прочитать до изменения конфигурации.

MOBIKE согласуется, а не предполагается. Если сервер его не предлагает, клиент должен установить соединение заново, и это факт, который вы подтверждаете по списку SA или журналу, а не выводите из крутящегося колёсика.

Путь определяет приоритет маршрута, а не значок Wi-Fi

Когда оба интерфейса подняты, ядро выбирает по метрике и длине префикса. ip route show default перечисляет кандидатов, а ip route get 203.0.113.10 разрешает настоящее решение, включая адрес источника. Проводной маршрут по умолчанию с метрикой 100 и беспроводной с 600 означают, что конечная точка смещается в момент, когда кабель садится, а каждое приложение, открывшее сокет раньше, сохраняет свой старый источник.

Windows делает то же самое с автоматическими метриками интерфейсов, смещёнными по скорости связи. Get-NetRoute -DestinationPrefix 0.0.0.0/0 сортирует кандидатов, а Find-NetRoute -RemoteIPAddress 203.0.113.10 возвращает интерфейс и источник, которые выбрал бы стек. Клиент, привязывающий свой внешний сокет к одному интерфейсу, продолжает им пользоваться после переворота метрики; это решение о привязке, а не ошибка маршрутизации.

Android делает разделение видимым: ConnectivityManager сообщает доступные сети и отдельный маршрут по умолчанию, а VPN-приложение, привязывающее сокет к объекту Network, держит эту привязку, пока не перепривяжет. В macOS scutil --nwi печатает основной интерфейс и порядок, который использовала бы система.

DNS, MTU и IPv6 движутся вместе с подключением

Новое подключение приносит новые резолверы. С systemd-resolved DNS задаётся для каждой связи, resolvectl status показывает, какая связь отвечает на имя, а гостевая сеть, раздающая свой резолвер, может оставить протолкнутый туннелем DNS неиспользованным, пока связь снова не станет предпочтительной. Пленённый портал ухудшает дело: на первый запрос HTTPS отвечает портал, а не конечная точка, и клиент записывает мёртвый сервер.

MTU пути тоже меняется. Ethernet и Wi-Fi обычно несут 1500 байт, PPPoE 1492, а мобильные связи часто меньше. Туннель, унаследовавший меньший MTU, застревает на больших пакетах, пока мелкие запросы проходят, и это читается как наполовину сломанное соединение. ping -M do -s 1472 203.0.113.10 отправляет пакет в 1500 байт с установленным DF; тишина означает, что путь меньше, чем вы предполагали.

IPv6 - вторая половина. Сеть, выдающая новый префикс, меняет источник, который использовал бы клиент с двумя стеками, а туннель только для v4 оставляет трафик v6 снаружи, пока политика не догонит. ip -6 route show default и ip -6 addr show отвечают, есть ли у новой связи вообще путь v6.

Воспроизведите переход, а не описывайте его

Выберите один безобидный запрос и выполните те же три команды по обе стороны изменения: ip -br addr, ip route show default, ip route get 203.0.113.10. Затем смотрите, выпускает ли туннель пакеты - tcpdump -ni any udp port 51820 для WireGuard, соответствующий порт для всего остального. Пакеты, уходящие из старого источника, означают проблему привязки. Пакеты из нового источника без ответа означают удалённую сторону или NAT посередине.

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

Прежде чем назвать это исправленным, подтвердите, что блок прямого трафика всё ещё держится во время разрыва и что имена разрешаются через новое подключение. Если клиент держит старую конечную точку после переключения, сначала поправьте настройку роуминга или float. Если он роумится правильно и всё равно не получает ответа, посмотрите на идентичность партнёра на сервере и NAT на пути, и сохраните оба сетевых контекста в записи, чтобы следующий человек мог их сравнить.

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