Ping do 192.0.2.10 mówi tylko, że jeden adres odpowiedział na echo ICMP, i nic więcej. W sieci bez tunelu może się to udać, bo adres może leżeć w lokalnej podsieci; przy zdrowym tunelu może się nie udać, bo serwer odrzuca ICMP, gdy obsługuje HTTPS. Sprawdzenie, którego potrzebuje Twój skrypt, to zapytanie o stan platformy plus test trasy do celu, którego używa aplikacja. Traktuj je jako dwa osobne pola, nigdy jako jedną wartość logiczną.

Co naprawdę dowodzi odpowiedź na echo

ICMP to protokół osiągalności, który nie zna pojęcia interfejsów ani tuneli. Gdy odpowiedź nadchodzi, jądro zgłasza, że host odpowiedział; nie zgłasza, która trasa niosła żądanie, a która niosła odpowiedź. Filtrowanie czyni sygnał jeszcze bardziej zaszumionym, bo zapora blokująca żądania echo nic nie mówi o portach za nią. A profil z dzielonym tunelem może celowo wykluczyć testowany adres, podczas gdy wszystkie inne cele działają.

Tak naprawdę chcesz wiedzieć, czy konkretna usługa jest użyteczna na drodze, którą pokonuje aplikacja. Wybierz host i port, które wywołuje aplikacja, a potem wymagaj odpowiedzi na warstwie aplikacji.

Osiągalność i stan tunelu to różne fakty, a jeden może być prawdziwy, gdy drugi jest fałszywy. Trzymanie ich osobno mówi, czyj jest błąd. Zlanie ich w jedno sprawdzenie daje zgłoszenie, którego nikt nie potrafi skierować.

Pytaj Androida o transport, nie o ping

Android odpowiada na pytanie o stan bezpośrednio przez ConnectivityManager. Możliwości aktywnej sieci niosą flagę transportu VPN, ustawianą, gdy ruch jest kierowany przez interfejs VPN. Wywołanie jest lokalne, tanie i niezależne od tego, czy jakikolwiek zdalny host odpowie.

Ta wersja w Javie zwraca false, zamiast rzucać wyjątek, gdy nie ma aktywnej sieci. Ponieważ czyta aktywną sieć, odzwierciedla profil wybrany przez użytkownika w Ustawieniach.

ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkCapabilities caps = cm.getNetworkCapabilities(cm.getActiveNetwork());
boolean tunnel = caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);

Do powiadomień o zmianach zarejestruj NetworkCallback, zamiast odpytować z timerem. Nie myl tego z VpnService.prepare, które mówi tylko, czy użytkownik udzielił zgody na VPN, a nie czy pakiety płyną. Odwołanie przychodzi przez VpnService.onRevoke, jednak zapomnienie profilu w Ustawieniach nie wywołuje żadnej transmisji.

iOS: nazwy interfejsów to heurystyka, nie kontrakt

Wiele fragmentów kodu iOS sprawdza ustawienia proxy, znajduje słownik __SCOPED__ i szuka kluczy interfejsów, takich jak tap, tun, utun2, ppp czy ipsec. To podejście to konwencja nazewnicza, a nie udokumentowana gwarancja, więc aktualizacja systemu, która zmieni nazwę interfejsu, może je zepsuć. Ma też skłonność do zgłaszania true dla nieaktualnych wpisów, które przeżywają tunel.

Gdy konfiguracja należy do Twojej aplikacji, NEVPNManager daje prawdziwy stan. Opisuje tunel uruchomiony przez Twoją aplikację; przy VPN na aplikację inne aplikacje mogą stać całkowicie poza tym tunelem.

Przeładuj preferencje przed odczytem stanu, bo wartość zmienia się, gdy tunel się podnosi i opada:

let manager = NEVPNManager.shared()
manager.loadFromPreferences { error in
    let up = manager.connection.status == .connected
    print(up)
}

Flaga stanu platformy wciąż nie dowodzi, że ruch dociera do peera. Właśnie tę lukę pokrywa test trasy, i dlatego jedna wartość logiczna nie wystarcza do wsparcia.

Profile Windows udostępniają prawdziwe pole stanu

Windows śledzi profile VPN oddzielnie od adapterów, a Get-VpnConnection udostępnia ConnectionStatus dla każdego znanego profilu. Profile utworzone przez klienta Windows lub pakiet aprowizacji pojawiają się tutaj. To polecenie nie jest uniwersalnym detektorem tuneli.

Odczytaj pole dla nazwanego profilu, dodając -AllUserConnection, gdy profil należy do wszystkich użytkowników:

Get-VpnConnection -Name "Fabrikam" | Select-Object Name, ConnectionStatus, ServerAddress

Klienci innych firm często pozostają niewidoczni dla tego polecenia, nawet gdy ich tunel działa, więc pusty wynik oznacza nieznane, a nie rozłączone. Listy adapterów mylą równie mocno: adapter dostawcy może trwać bezczynnie, a niektóre adaptery istnieją tylko podczas sesji. Dla profilu, którym zarządza Windows, rasdial zgłasza kod wyjścia, na którym można się rozgałęzić. Wszystko to opisuje lokalne przekonanie, a nie osiągalność peera.

Stan plus trasa: sprawdzenie dwuczęściowe

Połączony profil nic nie mówi o tym, dokąd idą pakiety. Dzielony tunel może utrzymywać tunel, wykluczając cel, na którym Ci zależy. Profile always-on pozostają połączone z martwym serwerem, a kill switch celowo blokuje ruch, gdy tunel pada.

Testuj obie warstwy: potwierdź, że transport VPN lub profil jest aktywny, a potem potwierdź, że cel się rozwiązuje i odpowiada tą drogą. W Linuksie zapytaj jądro, którego interfejsu by użyło:

ip route get 192.0.2.10
resolvectl query intranet.example.test

Gdy klient jest poza Twoją kontrolą, zapisz oba wyniki i pozwól wzorcowi wskazać warstwę. Połączono i nieudany test trasy sugeruje dzielony tunel, DNS lub politykę. Rozłączono i działający test trasy oznacza, że ruch niesie inna droga.

Test, który możesz wykonać po kolei

Najpierw zapisz stan platformy, zanim zmienisz jakikolwiek stan sieci. Rozwiąż nazwę hosta i zanotuj rodzinę adresów, bo rekord AAAA może iść inną drogą niż rekord A. Otwórz port usługi i wymagaj odpowiedzi aplikacji, a nie samego uścisku dłoni. Trzymaj każdą obserwację w osobnym polu logu.

Na maszynie z Linuksem, dig i curl, trzy polecenia obejmują rozwiązanie nazwy, trasę i samą usługę. Uruchom je z podniesionym tunelem i ponownie z opuszczonym:

dig +short intranet.example.test
ip route get 198.51.100.20
curl -sS -o /dev/null -w "%{http_code}" --max-time 8 https://intranet.example.test/health

Cztery osobne pola biją jedną wartość logiczną, bo stan, DNS, trasa i polityka zawodzą niezależnie i trafiają do różnych zespołów. Ping w terminalu pozostaje dobrym ręcznym sprawdzeniem. To słaba definicja łączności dla automatyzacji, gdzie API platformy i test trasy odpowiadają na prawdziwe pytanie.

Powiązane artykuły