VPN na Androidzie działa z IPv6, ale przeglądarka nadal wybiera IPv4
Prześledź cztery etapy, na których ginie prywatny adres IPv6: resolver, deklaracja VpnService, sprawdzanie kandydatów w przeglądarce i dostarczenie trasy.
VPN działa, prywatny interfejs webowy odpowiada przez IPv6 z laptopa, a telefon z Androidem nadal otwiera tę samą stronę przez IPv4 albo w ogóle odmawia jej wczytania. Rekord AAAA istnieje. Tunel zgłasza adres IPv6. Nic w kliencie nie wygląda źle. Wynik zależy od czterech osobnych decyzji: który resolver odpowiedział, co VpnService zadeklarował Androidowi, którą rodzinę adresów przeglądarka była gotowa wypróbować i czy pakiet może odbyć podróż tam i z powrotem. Przejdź je w tej kolejności, zamiast dodawać trasę domyślną i liczyć, że objaw się przesunie.
Krok 1: udowodnij, który resolver odpowiedział na zapytanie AAAA
Android nie ma jednej ścieżki DNS. VPN może wepchnąć serwer DNS dla swojej sieci, system może używać Private DNS dla nazw hostów, które uzna za kwalifikujące się, a Chrome może uruchamiać własny szyfrowany resolver spod chrome://settings/security. Na telefonie, gdzie tunel wepchnął 10.61.0.1, ale Private DNS wskazuje publicznego dostawcę, nazwa w twojej strefie prywatnej nie jest rozwiązywana przez maszynę, która tę strefę posiada. Przeglądarka dostaje odpowiedź od resolvera bez uprawnień do tej nazwy i traktuje ją jako brakującą, a tekst błędu nigdy nie wspomina DNS.
Zapytaj resolver tunelu bezpośrednio, zanim cokolwiek innego zmienisz. Pierwsze dwie komendy pokazują, jakie serwery DNS Android przypisał do aktywnej sieci i czy Private DNS jest w trybie automatycznym czy ścisłym; trzecia uruchamia się z dowolnego klienta wewnątrz tunelu, nie z telefonu.
adb shell dumpsys connectivity | grep -A3 "DnsAddresses"
adb shell settings get global private_dns_mode
nslookup -type=AAAA nas.lan 10.61.0.1
Krok 2: przeczytaj, co VpnService faktycznie zadeklarował
Strona Androida jest jawna, a nie wywnioskowana. VpnService.Builder dodaje adresy przez addAddress, trasy przez addRoute, serwery DNS przez addDnsServer i może ograniczyć cały tunel do jednej rodziny adresów przez allowFamily. Builder, który wywołał allowFamily(AF_INET), a potem dodał trasę IPv6, powiedział systemowi dwie sprzeczne rzeczy, a system zachowuje ograniczenie rodziny. Trasa obejmująca fd00:61::/64 w połączeniu z adresem interfejsu w innym prefiksie zawodzi z podobnego powodu: adres istnieje, ale nie jest on-link dla tej trasy.
Czytaj deklarację, zamiast ufać przełącznikowi w aplikacji. dumpsys netd wypisuje adresy i trasy przypisane do interfejsu tun, a LinkProperties dla każdej sieci wewnątrz dumpsys connectivity pokazuje listę DNS obok rodzin, które sieć deklaruje.
adb shell ip -6 addr show tun0
adb shell ip -6 route show table all | grep tun0
adb shell dumpsys connectivity | grep -E "LinkAddresses|Routes"
Jeśli interfejs tun ma adres IPv6, ale żadna trasa nie pasuje do prefiksu usługi, dostarczanie IPv6 jest już zepsute, zanim w ogóle pojawi się przeglądarka. To inny błąd niż przeglądarka, która odmawia próby, i wymaga innej poprawki.
Krok 3: przeglądarka decyduje, czy w ogóle próbować IPv6
Chromium nie używa każdego otrzymanego rekordu AAAA. Jego resolver hostów ma testy osiągalności IPv6 i filtrowanie kandydatów, które mogą odrzucić IPv6 lub obniżyć jego priorytet, gdy sieć zostanie uznana za niezdolną do jego przenoszenia, a kod źródłowy resolvera pokazuje ten test wraz z otaczającymi go warunkami. Logika zależy od wersji i flag, i właśnie dlatego dwa telefony w tym samym tunelu mogą zachowywać się różnie. Gdy kandydaci istnieją, Happy Eyeballs każe rodzinom ścigać się dla każdego połączenia, więc wolno odpowiadająca ścieżka IPv6 może nadal przegrać z szybko odpowiadającym IPv4.
Obserwuj decyzję, zamiast ją wnioskować. Sesja nagrana przez chrome://net-export i odtworzona w przeglądarce netlog pokazuje każde rozwiązanie i wybraną rodzinę; chrome://net-internals/#dns pokazuje wyniki z pamięci podręcznej. Rozwiązanie, które zwraca tylko rekordy A dla nazwy mającej AAAA w twoim własnym resolverze, wskazuje wprost na ten etap.
Krok 4: sprawdź, czy pakiet może odbyć podróż tam i z powrotem
Wybór adresu to nie dostarczenie. Android trzyma tablice routingu i reguły polityki dla każdej sieci, które wybierają tablicę po fwmark, więc trasa widoczna w tablicy głównej nie jest automatycznie tą, której używa gniazdo. Czytanie reguł i proszenie jądra o rozwiązanie celu dla adresu źródłowego rozdziela te dwie rzeczy.
adb shell ip -6 rule show
adb shell ip -6 route get fd00:61::20 from fd00:61::10
To wynik route get odpowiada na pytanie. Jeśli wskazuje tun0, a pakiety nadal giną, przejdź do MTU tunelu i przekazywania IPv6 na bramie, zamiast wracać do telefonu.
Dlaczego dodanie ::/0 zwykle pogarsza sprawę
Dodanie ::/0 zmienia roszczenie tunelu z jednego prefiksu na każde miejsce docelowe IPv6. Na telefonie może to spełnić test osiągalności, bo adres testowy spoza twojego prefiksu wygląda teraz na routowalny. Nie tworzy to przepustowości IPv6 w górę na bramie, a wiele domowych bram nie ma w ogóle działającego łącza w górę IPv6. Wynikiem jest czarna dziura dla publicznego IPv6: nazwy, które wcześniej wracały do IPv4, teraz wiszą, a prywatna strona może wyglądać lepiej tylko dlatego, że test mierzy coś innego.
Jest też koszt polityki. Z ::/0 w tunelu cały ruch IPv6 wychodzi przez VPN, łącznie z ruchem, którego właściciel sieci nigdy nie zgodził się przenosić. Traktuj to jako decyzję wdrożeniową z nazwanym właścicielem, a nie krok debugowania podejmowany o 1 w nocy.
Kolejność pracy, która to kończy
Potwierdź, że odpowiedź AAAA pochodzi z resolvera, który trzyma strefę, odczytaj stan VpnService i netd dla interfejsu tun, zrób zrzut net-export, by zobaczyć, czy Chromium odrzucił kandydata, a potem przetestuj podróż tam i z powrotem przez ip -6 route get. Napraw warstwę, która naprawdę zawiodła, i zostaw politykę podziału w spokoju. Jeśli prywatne nazwy potrzebują innych odpowiedzi niż publiczne, właśnie do tego służy split tunneling.
Zapisz build telefonu, wersję przeglądarki i resolver, o który pytałeś. Te trzy fakty zamieniają "IPv6 is broken" w coś, co następna osoba może odtworzyć.