Android VPN работи с IPv6, но браузърът все още избира IPv4
Проследете четирите етапа, на които частен адрес IPv6 изчезва: резолвер, декларация на VpnService, проверка на кандидатите в браузъра и доставка на маршрута.
VPN е включен, частният уеб интерфейс отговаря по IPv6 от лаптоп, а телефонът с Android все още отваря същата страница по IPv4 или отказва да я зареди изобщо. Записът AAAA съществува. Тунелът съобщава адрес IPv6. Нищо в клиента не изглежда сбъркано. Изходът се решава от четири отделни решения: кой резолвер е отговорил, какво е декларирал VpnService към Android, кое семейство адреси браузърът е бил готов да опита и дали пакетът може да направи пътуването в двете посоки. Минете през тях в този ред, вместо да добавяте маршрут по подразбиране и да се надявате, че симптомът ще се премести.
Стъпка 1: докажете кой резолвер е отговорил на заявката AAAA
Android няма единен път за DNS. VPN може да изпрати DNS сървър за своята мрежа, системата може да използва Private DNS за имената на хостове, за които прецени, че се отнасят, а Chrome може да пусне собствения си криптиран резолвер от chrome://settings/security. На телефон, където тунелът изпраща 10.61.0.1, но Private DNS сочи към публичен доставчик, името във вашата частна зона не се разрешава от машината, която притежава зоната. Браузърът получава отговор от резолвер без правомощия за това име и го третира като липсващо, а текстът на грешката никога не споменава DNS.
Попитайте резолвера на тунела директно, преди да промените каквото и да е друго. Първите две команди показват кои DNS сървъри Android е прикачил към активната мрежа и дали Private DNS е в автоматичен или строг режим; третата се изпълнява от всеки клиент вътре в тунела, не от телефона.
adb shell dumpsys connectivity | grep -A3 "DnsAddresses"
adb shell settings get global private_dns_mode
nslookup -type=AAAA nas.lan 10.61.0.1
Стъпка 2: прочетете какво всъщност е декларирал VpnService
Страната на Android е изрична, а не изведена. VpnService.Builder добавя адреси с addAddress, маршрути с addRoute, DNS сървъри с addDnsServer и може да ограничи целия тунел до едно семейство адреси с allowFamily. Конструктор, който е извикал allowFamily(AF_INET) и после е добавил маршрут IPv6, е казал на системата две противоречиви неща и именно ограничението на семейството остава. Маршрут, покриващ fd00:61::/64, съчетан с адрес на интерфейс в друг префикс, се проваля по подобна причина: адресът съществува, но не е on-link за този маршрут.
Четете декларацията, вместо да се доверявате на превключвателя в приложението. dumpsys netd отпечатва адресите и маршрутите, прикачени към интерфейса tun, а LinkProperties за всяка мрежа в dumpsys connectivity показва списъка с DNS до семействата, които мрежата твърди.
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"
Ако интерфейсът tun има адрес IPv6, но нито един маршрут не съвпада с префикса на услугата, доставката на IPv6 вече е счупена, преди браузър да се намеси. Това е различна грешка от браузър, който отказва да опита, и изисква различно поправяне.
Стъпка 3: браузърът решава дали изобщо да опита IPv6
Chromium не използва всеки получен запис AAAA. Неговият резолвер на хостове носи проверки за достижимост на IPv6 и филтриране на кандидати, които могат да отхвърлят или понижат приоритета на IPv6, когато мрежата бъде преценена като неспособна да го носи, а изходният код на резолвера показва тази проверка заедно с условията около нея. Логиката зависи от версията и флаговете — точно затова два телефона на един и същ тунел могат да се държат различно. След като кандидатите съществуват, Happy Eyeballs провежда състезание между семействата за всяка връзка, така че път IPv6, който отговаря бавно, все още може да загуби от IPv4, който отговаря бързо.
Наблюдавайте решението, вместо да го извеждате. Сесия, записана през chrome://net-export и възпроизведена в прозореца за преглед на netlog, показва всяко разрешаване и избраното семейство; chrome://net-internals/#dns показва кешираните резултати. Разрешаване, което връща само записи A за име, което има AAAA във вашия собствен резолвер, сочи право към този етап.
Стъпка 4: проверете дали пакетът може да направи пътуването в двете посоки
Изборът на адрес не е доставка. Android поддържа таблици за маршрутизация и правила за политика за всяка мрежа, които избират таблица по fwmark, така че маршрут, видим в основната таблица, не е автоматично маршрутът, който използва сокетът. Четенето на правилата и искането към ядрото да разреши дестинация за адрес на източника разделя двете.
adb shell ip -6 rule show
adb shell ip -6 route get fd00:61::20 from fd00:61::10
Именно изходът на route get отговаря на въпроса. Ако посочва tun0, а пакетите все още загиват, преминете към MTU на тунела и препращането на IPv6 на шлюза, а не обратно към телефона.
Защо добавянето на ::/0 обикновено влошава нещата
Добавянето на ::/0 променя претенцията на тунела от един префикс към всяка дестинация IPv6. На телефона това може да удовлетвори проверка за достижимост, защото тестов адрес извън вашия префикс сега изглежда маршрутизируем. То не създава капацитет IPv6 нагоре по веригата на шлюза, а много домашни шлюзове изобщо нямат работещ изходящ канал IPv6. Резултатът е черна дупка за публичния IPv6: имена, които преди се връщаха към IPv4, сега висят, а частната страница може да изглежда по-добре само защото проверката измерва нещо друго.
Има и цена за политиката. С ::/0 в тунела целият трафик IPv6 излиза през VPN, включително трафик, който собственикът на мрежата никога не е приемал да поема. Отнасяйте се към това като към решение за внедряване с посочен собственик, а не като към стъпка за отстраняване на грешки, която предприемате в 1 часа сутринта.
Редът на работа, който слага край на това
Потвърдете, че отговорът AAAA идва от резолвера, който държи зоната, прочетете състоянието на VpnService и netd за интерфейса tun, запишете траса net-export, за да видите дали Chromium е отхвърлил кандидата, после тествайте пътуването в двете посоки с ip -6 route get. Поправете слоя, който всъщност се е провалил, и не пипайте политиката за разделяне. Ако частните имена се нуждаят от различни отговори от публичните, точно за това е split tunneling.
Записвате сглобката на телефона, версията на браузъра и резолвера, който сте запитали. Тези три факта превръщат "IPv6 is broken" в нещо, което следващият човек може да възпроизведе.