Android VPN maršrutizavimas: politikos taisyklės prieš lentelę main
Android pasirenka maršrutų lentelę pagal uid ir žymių taisykles prieš bet kokią paskirties paiešką, todėl į main įrašytas maršrutas gali būti niekada netikrintas.
Maršrutas, įrašytas į Android lentelę main, visuose sąrašuose atrodo teisingai ir vis tiek neperduoda srauto. Priežastis ta, kad lentelė main yra vienas iš kelių variantų ir ji nėra klausiama pirmoji. Android tinklo tarnyba kuria politikos taisykles, kurios pasirenka maršrutų lentelę pagal informaciją, kurios paskirties adresas neturi — programos uid, paketo žymė, sąsaja, kuria jis atėjo — o paskirties paieška vyksta vėliau, tos lentelės, kurią pasirinko tos taisyklės, viduje.
Trys sprendimai fiksuota tvarka
Išėjęs paketas priima tris atskirus sprendimus. Pirma, politikos taisyklė nustato, kuri maršrutų lentelė galioja. Antra, maršrutas toje lentelėje nustato kitą šuolį ir išėjimo sąsają. Trečia, netfilter kabliukai nustato, ar paketas išlieka, yra keičiamas ar peradresuojamas.
Tvarka svarbi, nes kiekvienas etapas gali atsakyti tik į savo klausimą. Ugniasienės taisyklė, kuri priima paketą, nepasirenka lentelės, o maršrutas, įrašytas į lentelę, kurios nepasirenka nė viena taisyklė, yra neveikus. Didelė dalis painiavos dėl Android VPN kyla iš to, kad pataisoma viena iš trijų ir nepastebima jokio pokyčio, nes gedimas buvo kitoje.
| Stage | Selector | What it cannot decide |
|---|---|---|
| Policy rule | uid range, mark, incoming interface | Which route exists inside the table |
| Route lookup | Destination prefix, longest match | Whether the packet is allowed out |
| Netfilter hook | Chain position, match conditions | Which table was selected |
Žymės yra supakuotas laukas, o ne jūsų nuosava etiketė
Android supakuoja kelis faktus į tą pačią žymės reikšmę: kuris tinklas buvo pasirinktas, ar programa aiškiai pasirinko tinklą, ar lizdas apsaugotas nuo VPN, ir su leidimais susiję bitai. AOSP fwmark antraštė apibrėžia tą išdėstymą dabartiniam medžiui, o išdėstymas yra platformos vidinė detalė, kuri keičiasi tarp leidimų.
Todėl Android sistemoje pavojinga rašyti visą žymės reikšmę su iptables -j MARK --set-mark. Tai neprideda žymos; tai pakeičia tinklo pasirinkimą, kurį sistema jau atliko. Tada paketas atitinka kitas taisykles, o tai gali atrodyti taip, lyg VPN pradėjo veikti, arba lyg nesusijusi programa prarado ryšį, priklausomai nuo to, kurie bitai buvo perrašyti.
Jei vis dėlto reikia liesti žymes, pirmiausia perskaitykite dabartinę reikšmę ir naudokite kaukę, kad būtų keičiami tik tie bitai, kuriuos suprantate:
ip rule show
ip route show table all | head -40
ip route get 10.20.4.11Ryšio žymė yra atskiras objektas nuo paketo žymės, ir nė viena iš jų nėra maršrutas. Žymės atkūrimas atsakymo paketuose yra atskiras žingsnis nuo lentelės pasirinkimo išėjimo metu, todėl vienkryptės pataisos sukuria ryšius, kurie atsidaro ir paskui pakimba.
Kam priklauso taisyklės ir lentelės
Android tinklo tarnyba netd kuria taisykles ir lenteles kiekvienam tinklui. AOSP RouteController yra vieta, kur tos taisyklės surenkamos VPN, fiziniams tinklams ir uid intervalams, o jos gyvavimo ciklas susietas su tinklo įvykiais, o ne su konfigūracijos failu.
Iš to kyla dvi pasekmės. Pirma, prioritetai ir lentelių numeriai, kuriuos randate viename telefone, yra kompiliavimo vidinės detalės, o ne sąsaja: vienodai atrodantys numeriai kitoje Android versijoje gali reikšti visai ką kita. Antra, pasikeitus tinklams būsena sukuriama iš naujo, todėl šiandien iš root shell įterpta taisyklė gali būti dingusi po kito Wi-Fi perjungimo.
Šis dingimas dažnai pranešamas kaip sistema ignoruoja maršrutą. Iš tikrųjų įvyko tai, kad taisyklė, kuri pasirinko lentelę, nebeegzistuoja, o maršrutas lentelės viduje dabar nepasiekiamas paketo požiūriu. Patikrinkite taisyklių sąrašą, o ne maršrutų sąrašą, kai veikianti konfigūracija nustoja veikti po prisijungimo iš naujo.
Kabliukų tvarkos klausimai neturi universalaus atsakymo
Klausimo, ar iptables veikia prieš VPN maršrutizavimą, negalima atsakyti neįvardijus paketo kelio. Vietoje sugeneruotas paketas praeina output kabliuką, kur žymės pakeitimas sukelia pakartotinio maršrutizavimo patikrą — antra paieška, o ne pirmosios retrospektyvus keitimas. Paketas, atėjęs iš tether kliento, praeina prerouting kelią ir yra persiunčiamas, o jį matančios grandinės yra kitos.
Taigi ta pati taisyklė gali būti veiksminga programos srautui ir nematoma tether srautui, o nuliuose liekantis skaitiklis pasako, kokį kelią paketas pasirinko, o ne ar taisyklė neteisinga. Naudokite skaitiklius keliui nustatyti prieš keisdami bet kokią atitikimo sąlygą.
Tai ir etapas, kai politikos maršrutizavimo klaida tampa sunkiai pastebima. Maršrutizavimas į lentelę, kuri egzistuoja, bet neturi paskirties, duoda tinklą nepasiekiamas, kuris atrodo kaip ugniasienės numetimas, o ugniasienės numetimas duoda laiko limitą, kuris atrodo kaip maršrutizavimo juodoji skylė.
Diagnozuokite sistemos viduje arba palikite ją ramybėje
Autorizuotai apžiūrai prieš ką nors liesdami nustatykite keturis faktus: programos uid ir profilį, tinklą, kurį Android jai pasirinko, ar VPN apskritai apima tą programą, ir ar problema egzistuoja abiem adresų šeimoms. Išskyrimas pagal programą paaiškina labai daug pranešimų VPN neveikia be jokio maršrutizavimo gedimo.
Tada perskaitykite taisykles, kaukes ir lenteles, kurios iš tikrųjų galioja, ir laikykite tinklo perjungimą stebėjimo lange. Jei elgsena keičiasi per prisijungimą iš naujo, matote valdomą gyvavimo ciklą, o ne trūkstamą maršrutą.
Įprastiems reikalavimams naudokite palaikomas valdymo priemones: įtraukimas ir išskyrimas pagal programą VPN programoje, ir pačios platformos tinklo pasirinkimą viskam, kam reikia konkretaus kelio. Jei privilegijuota integracija tikrai turi bendradarbiauti su maršrutizavimo mechanizmu, taikykitės į tiksliai tos Android versijos, kurią palaikote, įgyvendinimą ir palaikykite jos gyvavimo ciklą per komponentą, kuriam ji priklauso. Platformos grandinių išvalymas ar aukšto prioriteto taisyklės įterpimas diagnozę paverčia antruoju tinklo tvarkytuvu, ir telefonas elgsis atitinkamai.