W jednej chwili laptop jest w Wi-Fi biura, w następnej jest podłączony do telefonu, a wskaźnik tunelu znów jest zielony, zanim skończysz przełączać okna. Zielone światło informuje tylko, że tunel połączył się ponownie; to, co polityka routingu i blokowania robiła w tym czasie, to inne pytanie. Ta polityka to zbiór warunków dopasowania skompilowanych przy ostatniej instalacji, i nazywa interfejs, adres oraz rodzinę adresów, które przełączenie właśnie usunęło. Ten sam przełącznik daje więc trzy wyniki, które wyglądają identycznie: blokowanie trwa, polityka blokuje własne odtworzenie, albo otwiera się ścieżka, której nic nie obejmuje.

Nic na ekranie nie rozdziela tych trzech stanów, więc pytaj, do jakich identyfikatorów przypięto reguły, a nie jaki kolor pokazuje wskaźnik. W Linuksie reguła może nazwać interfejs albo ipset wypełniony z niego; w Androidzie VpnService można powiedzieć przez setUnderlyingNetworks, których sieci bazowych ma przestrzegać. Każde przypięcie wskazuje łącze, które zaraz zostanie zastąpione, i każde trzeba potem ocenić od nowa.

Co przełączenie naprawdę przepisuje

Gdy stare łącze znika, jądro usuwa jego adresy, wycofuje trasy, które przez nie prowadziły, i odbudowuje wybór adresu źródłowego z tego, co zostało. Domyślna trasa przesuwa się na nową bramę, a indeks interfejsu, do którego odwoływały się stare reguły, zniknął albo został przetworzony dla innego urządzenia. Resolvery na łącze też są odświeżane, choć nie w tej samej chwili co trasy. Wszystko to dzieje się pod klientem VPN, więc klient, który obserwuje tylko stan własnego tunelu, niczego z tego nie widzi.

Kłopot w tym, że reguła koduje konkretny identyfikator zamiast intencji, która za nim stoi. Reguła, która wyrzuca wszystko, co nie wychodzi przez interfejs tunelu, koduje nazwę interfejsu; reguła, która zezwala na punkt końcowy, koduje adres, który nowa sieć może kierować gdzie indziej. Gdy identyfikator znika, reguła nie staje się widocznie błędna: albo przestaje pasować do czegokolwiek, albo zaczyna pasować do niewłaściwej rzeczy.

Odbudowa zewnętrznego tunelu bez wybijania dziury

Transport zewnętrzny był związany ze starym adresem źródłowym, więc musi otworzyć nowe gniazdo z nowego. Gdy punkt końcowy jest nazwą hosta, a nie dosłownym adresem, wyszukiwanie musi się udać, dopóki blokada jeszcze obowiązuje. To jest pułapka kolejności: polityka wystarczająco surowa, by wyrzucić wszystko poza punktem końcowym, wyrzuci też wyszukiwanie potrzebne, by go znaleźć, chyba że rozwiązanie następuje przed podniesieniem blokady albo jest przenoszone przez wciąż żywy tunel. Oba porządki mogą działać, ale tylko jeśli klient wie, w którym jest.

Klienci różnią się tu w sposób, który ma znaczenie przy diagnozie. Niektóre najpierw rozwiązują, a potem instalują reguły, więc przełączenie kosztuje widoczną przerwę i potem samo się odtwarza; inne trzymają blokadę i polegają na ocalałym tunelu, by przeniósł wyszukiwanie, co zawodzi całkowicie, gdy tunel umarł razem z łączem. Dodanie szerokiej bezpośredniej trasy domyślnej dla odtworzenia łączności zawsze przepuszcza test i zawsze zostawia wyciek, któremu zapobiegałeś.

Trasa wciąż wskazująca starą bramę daje to samo zablokowane odtworzenie z innej przyczyny, więc przeczytaj tablicę, zanim obwinisz klienta. Poniższe polecenia nazywają interfejs i adres źródłowy, których jądro naprawdę by użyło, i to rozstrzyga w jednej linii, czy stara ścieżka jest jeszcze zainstalowana.

ip route get 1.1.1.1
ip -6 route get 2606:4700:4700::1111

Gdy nowe łącze przynosi IPv6, a reguły nie

Sieci komórkowe i gościnne często przydzielają globalny prefiks IPv6, nawet gdy przewodowy LAN biura nigdy tego nie robił. Polityka napisana tylko jako reguły IPv4, domyślna forma większości ręcznie tworzonych przepisów iptables i nftables, nie obejmuje z tego nic. Tunel pozostaje połączony, aplikacje z osiągalnością IPv6 wychodzą poza niego, a wskaźnik nie może pokazać różnicy, bo tunel naprawdę działa. Przypadek lustrzany jest równie częsty: zestaw reguł tylko dla IPv6 nic nie robi w sieci, która nie oferuje v6.

Porównaj, co oferuje łącze, z tym, co wymienia polityka, po obu stronach przełączenia. Te polecenia drukują te same fakty, z którymi pracuje klient:

ip -4 route show default
ip -6 route show default
sudo nft list ruleset | grep -c 'ip6 '

Jeśli drugie polecenie drukuje trasę domyślną, a trzecie zwraca zero, nowe łącze może wyprowadzić maszynę przez IPv6 bez żadnej reguły, która by tego pilnowała. Uruchom wszystkie trzy ponownie po przełączeniu, bo interesującą liczbą jest różnica między oboma uruchomieniami. Jeśli drugie nic nie drukuje, zachodzi przypadek odwrotny i każda polityka ciężka od v6 jest tam tylko ozdobą.

Resolver zmienia ręce w połowie sesji

W nowoczesnych systemach resolvery są przypisane do łącz, więc nowe łącze przychodzi z nowym zestawem resolverów i być może innym widokiem split-DNS. systemd-resolved trzyma po jednym zakresie na łącze i wybiera między nimi według trasy, a macOS czyta resolvery z zakresem z magazynu dynamicznego i respektuje kolejność interfejsów. Klient, który instaluje własny resolver, konkuruje z resolverem łącza, a o zwycięzcy decydują reguły priorytetu, których nikt nie obserwuje. Wtedy rozwiązywanie nazw może się zepsuć, podczas gdy filtrowanie pakietów robi dokładnie to, do czego je napisano.

Czytaj resolver, który jest aktywny, a nie ten skonfigurowany. Na hoście systemd podpolecenie status pokazuje, z którego łącza przyszedł każdy zakres i czy obowiązuje nazwa private-DNS:

resolvectl status --no-pager
resolvectl query intranet.example.com

Jeśli zapytanie wychodzi przez łącze fizyczne, a nie przez tunel, klient przegrał konkurencję priorytetów i żadne dostrojenie zapory nie naprawi nazewnictwa. Porównaj ścieżkę zapytania po obu stronach przełączenia, by zobaczyć, która się przesunęła. Nazwa, która rozwiązuje się na prywatny adres, którego nowa sieć nie potrafi trasować, to trzeci przypadek, i objawia się przekroczeniem czasu, a nie błędem.

Przećwicz przełączenie i prowadź zapis

Odtwórz zmianę celowo, zamiast na nią czekać. Podnieś tunel na pierwszym łączu, rozpocznij długotrwały transfer i powtarzane wyszukiwanie, potem przełącz łącze i zobacz, które przetrwa. Zanotuj odstęp między zniknięciem starego łącza a zgłoszeniem przez tunel, że jest połączony, bo w tym oknie polityka albo się utrzymała, albo nie. Wykonaj sekwencję także w drugą stronę, żeby wynik nie był jednostronny.

Wyjątki wymagają własnego przejścia, bo obejście uzasadnione w starej sieci nie jest automatycznie uzasadnione w nowej. Drukarka, NAS albo portal przechwytujący w domowym LAN nie mają odpowiednika w sieci komórkowej, a wyjątek, który do nich docierał, staje się regułą bez odpowiednika.

Zapisz nazwy interfejsów, oferowane rodziny, obowiązujący resolver i długość przerwy dla każdego kierunku. Ponowne połączenie dowodzi, że transport się odtworzył, a nie że blokada wytrzymała w czasie przerwy, i to są osobne twierdzenia do zgłoszenia. Z tym zapisem następne przełączenie porównuje się ze znanym stanem, a nie z pamięcią.

Powiązane artykuły