Dlaczego VPN pada, gdy zmienia się Wi-Fi albo wpinany jest Ethernet
'Nowy SSID, roaming między punktami dostępu i wpięty kabel łamią tunel w trzech różnych miejscach. Sprawdź adres źródłowy, potem trasę, potem protokół.'
Dwie rzeczy są zgłaszane jako jedna awaria: laptop przeszedł do innej sieci Wi-Fi albo wpięto kabel, podczas gdy Wi-Fi dalej działało. Klient nadal twierdzi, że jest połączony, ikona wygląda zdrowo, a tunel nic nie przenosi. Pod spodem mogą przesunąć się tylko trzy kawałki stanu - połączenie, adres lokalny, trasa domyślna - i to, który się przesunął, decyduje, czy tunel odbuduje się sam, czy potrzebuje ponownego połączenia. Sprawdzam je w tej kolejności, bo zmiana ustawień konta nigdy nie naprawiła żadnego z nich.
Połączenie, adres i trasa przesuwają się niezależnie
Roaming między punktami dostępu w tej samej sieci to zwykle zdarzenie L2. Radio kojarzy się ponownie, interfejs zachowuje adres i bramę, i nic, od czego zależy tunel, się nie zmienia, dlatego przejście przez duże biuro czasem pozostaje niezauważone. Dołączenie do innego SSID tym nie jest: stary interfejs może zniknąć, DHCP przydziela nowy adres, nową bramę i nowe resolvery, a zewnętrzny przepływ, którego używał tunel, przestaje istnieć.
Ethernet dodaje trzecią postać. Wi-Fi nigdy nie pada, więc żadne zdarzenie łącza nie zostaje wywołane, ale interfejs przewodowy pojawia się z własnym adresem i często wygrywa trasę domyślną po metryce. Tunel działa dalej po ścieżce, która nie jest już preferowana, albo klient trzyma swój socket przypięty do sieci bezprzewodowej, w której zaczął. Z punktu widzenia przeglądarki oba wyglądają tak samo: strony zacinają się w chwili, gdy kabel się zatrzaśnie.
Pierwsze pytanie nie brzmi więc, czy Wi-Fi się zmieniło. Brzmi, czy zmienił się adres, do którego jesteś przypisany, albo trasa do punktu końcowego, gdy tunel był aktywny.
Zewnętrzny socket jest przypięty do adresu, który właśnie zniknął
Każdy tunel to zewnętrzny przepływ: lokalny adres i port rozmawiają z adresem i portem serwera. W Linuxie to socket UDP związany ze starym źródłem; gdy interfejs trzymający adres zostaje usunięty, wysyłki albo kończą się błędem EADDRNOTAVAIL, albo wychodzą przez nowy interfejs ze źródłem, którego serwer nigdy nie widział.
Druga strona trzyma własne przypięcie. SA IKEv2 bez MOBIKE jest identyfikowana parą adresów, a OpenVPN sesja jest związana z adresem peera, którego się nauczyła, a mapowanie NAT należy do prywatnego adresu, portu i adresu publicznego, które je utworzyły. Przenieś się za inny NAT, a każda odpowiedź idzie do mapowania, którego już nie ma. Na twojej maszynie nic nie jest źle skonfigurowane; piątka wskazuje na sieć, którą opuściłeś.
Przeczytaj stan, zanim zaczniesz teoretyzować:
ss -unppokazuje lokalny adres i port, które każdy socket tunelu naprawdę trzyma.ip route get 203.0.113.10wypisuje adres źródłowy i urządzenie, których jądro użyłoby teraz do punktu końcowego.wg show wg0 endpoints,swanctl --list-sasalbo log klienta pokazuje adres peera, z którym druga strona uważa, że rozmawia.
Jeśli adres socketu i wyszukanie trasy się nie zgadzają, znalazłeś pęknięcie, i żadna zmiana poświadczeń go nie dotknie.
Co robi każdy protokół z nowym adresem źródłowym
Klienci przyswajają zmianę w różnym stopniu, a tabela jest tym, z czym porównuję konfigurację klienta, zamiast zgadywać z zachowania przy ponownym łączeniu.
| Tunnel | Recovery behaviour | Failure signature |
|---|---|---|
| WireGuard | Updates 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/IPsec | MOBIKE (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 TCP | The tunnel is a byte stream, so a changed source address breaks it outright. | Immediate reset and a new connection attempt. |
Reguła roamingu WireGuarda działa tylko w jedną stronę: klient musi najpierw wysłać z nowego adresu. Socket wciąż związany ze starym interfejsem nigdy tego nie robi, dlatego tunel może wyglądać na żywy, podczas gdy jego licznik uzgadniania się starzeje. opis protokołu podaje dokładnie warunek aktualizacji punktu końcowego i warto go przeczytać przed zmianą konfiguracji.
MOBIKE jest negocjowany, a nie zakładany. Jeśli serwer go nie oferuje, klient musi ustanowić połączenie od nowa, i to jest fakt, który potwierdzasz z listy SA albo logu, a nie wnioskujesz z kręcącego się kółka.
O ścieżce decyduje preferencja trasy, nie ikona Wi-Fi
Gdy oba interfejsy są podniesione, jądro wybiera według metryki i długości prefiksu. ip route show default wymienia kandydatów, a ip route get 203.0.113.10 rozstrzyga rzeczywistą decyzję, łącznie z adresem źródłowym. Przewodowa trasa domyślna z metryką 100 i bezprzewodowa z 600 znaczą, że punkt końcowy przesuwa się w chwili, gdy kabel się ułoży, podczas gdy każda aplikacja, która wcześniej otworzyła socket, zachowuje swoje stare źródło.
Windows robi to samo z automatycznymi metrykami interfejsów, stronniczymi według szybkości łącza. Get-NetRoute -DestinationPrefix 0.0.0.0/0 sortuje kandydatów, a Find-NetRoute -RemoteIPAddress 203.0.113.10 zwraca interfejs i źródło, które wybrałby stos. Klient, który wiąże swój zewnętrzny socket z jednym interfejsem, nadal go używa po odwróceniu metryki; to decyzja o wiązaniu, a nie błąd routingu.
Android czyni podział widocznym: ConnectivityManager zgłasza dostępne sieci i osobną domyślną, a aplikacja VPN, która wiąże socket z obiektem Network, trzyma to wiązanie, dopóki nie zwiąże ponownie. W macOS scutil --nwi wypisuje interfejs podstawowy i kolejność, której użyłby system.
DNS, MTU i IPv6 przesuwają się wraz z podłączeniem
Nowe podłączenie przynosi nowe resolvery. Z systemd-resolved DNS jest na łącze, resolvectl status pokazuje, które łącze odpowiada na nazwę, a sieć gościnna, która rozdaje własny resolver, może zostawić DNS wypchnięty przez tunel nieużywanym, dopóki łącze znów nie będzie preferowane. Portal przechwytujący pogarsza sprawę: na pierwsze żądanie HTTPS odpowiada portal, a nie punkt końcowy, i klient zapisuje martwy serwer.
MTU ścieżki też się zmienia. Ethernet i Wi-Fi niosą zwykle 1500 bajtów, PPPoE 1492, a łącza mobilne często mniej. Tunel, który dziedziczy mniejsze MTU, zatyka się na dużych pakietach, podczas gdy małe żądania przechodzą, co czyta się jako na wpół zepsute połączenie. ping -M do -s 1472 203.0.113.10 wysyła pakiet 1500 bajtów z ustawionym DF; cisza oznacza, że ścieżka jest mniejsza, niż zakładałeś.
IPv6 to druga połowa. Sieć, która rozdaje nowy prefiks, zmienia źródło, którego użyłby klient dwustosowy, a tunel tylko v4 zostawia ruch v6 poza sobą, dopóki polityka nie nadąży. ip -6 route show default i ip -6 addr show odpowiadają, czy nowe łącze ma w ogóle ścieżkę v6.
Odtwórz przejście, zamiast je opisywać
Wybierz jedno nieszkodliwe żądanie i uruchom te same trzy polecenia po obu stronach zmiany: ip -br addr, ip route show default, ip route get 203.0.113.10. Potem obserwuj, czy tunel nadal wysyła pakiety - tcpdump -ni any udp port 51820 dla WireGuarda, odpowiedni port dla wszystkiego innego. Pakiety wychodzące ze starego źródła oznaczają problem z wiązaniem. Pakiety z nowego źródła bez odpowiedzi oznaczają drugą stronę albo NAT po drodze.
Zanotuj, które zdarzenie zbiegło się z pierwszą awarią: spadek łącza, zmiana adresu albo zmiana trasy domyślnej. Wskazują one na różnych odpowiedzialnych - klienta, którego trzeba związać od nowa, adres, który trzeba uzyskać ponownie, albo trasę należącą do pliku konfiguracyjnego, a nie do stałej reguły obejścia.
Zanim nazwiesz to naprawionym, potwierdź, że blok bezpośredniego ruchu nadal się trzyma podczas przerwy i że nazwy rozwiązują się przez nowe podłączenie. Jeśli klient po przełączeniu trzyma stary punkt końcowy, najpierw popraw ustawienie roamingu albo float. Jeśli roamuje poprawnie i nadal nie dostaje odpowiedzi, zajrzyj na tożsamość peera na serwerze i NAT na ścieżce, i zachowaj oba konteksty sieciowe w zapisie, żeby następna osoba mogła je porównać.