Androidissa tauluun main lisätty reitti näyttää jokaisessa listauksessa oikealta eikä silti kuljeta liikennettä. Syy on siinä, että taulu main on yksi vaihtoehto monien joukossa, eikä sitä kysytä ensimmäisenä. Androidin verkkopalvelu rakentaa politiikkasäännöt, jotka valitsevat reititystaulun tiedolla, jota kohdeosoite ei sisällä — sovelluksen uid, paketin merkintä, rajapinta, jolta se saapui — ja kohdehaku tapahtuu vasta sen jälkeen, sen taulun sisällä, jonka ne säännöt valitsivat.

Kolme päätöstä kiinteässä järjestyksessä

Lähtevä paketti tekee kolme erillistä päätöstä. Ensiksi politiikkasääntö päättää, mikä reititystaulu on voimassa. Toiseksi taulun sisäinen reitti päättää seuraavan hypyn ja lähtevän rajapinnan. Kolmanneksi netfilterin koukut päättävät, selviääkö paketti, muutetaanko sitä vai ohjataanko se uudelleen.

Järjestys on tärkeä, koska jokainen vaihe voi vastata vain omaan kysymykseensä. Palomuurisääntö, joka hyväksyy paketin, ei valitse taulua, ja reitti, joka lisätään tauluun, jota mikään sääntö ei valitse, on tehoton. Suuri osa Androidin VPN:iin liittyvästä sekaannuksesta syntyy siitä, että korjataan yksi kolmesta eikä havaita muutosta, koska vika oli toisessa.

StageSelectorWhat it cannot decide
Policy ruleuid range, mark, incoming interfaceWhich route exists inside the table
Route lookupDestination prefix, longest matchWhether the packet is allowed out
Netfilter hookChain position, match conditionsWhich table was selected

Merkinnät ovat pakattu kenttä, eivät tarra, jonka omistat

Android pakkaa useita tosiasioita samaan merkintäarvoon: mikä verkko valittiin, valitsiko sovellus verkon nimenomaisesti, onko socket suojattu VPN:ltä ja käyttöoikeuksiin liittyvät bitit. AOSP:n fwmark-otsake määrittelee tämän asettelun nykyiselle puulle, ja asettelu on alustan sisäinen asia, joka muuttuu julkaisujen välillä.

Siksi kokonaisen merkintäarvon kirjoittaminen komennolla iptables -j MARK --set-mark on Androidissa vaarallista. Se ei lisää tunnistetta; se korvaa verkon valinnan, jonka järjestelmä on jo tehnyt. Sen jälkeen paketti osuu eri sääntöihin, mikä voi näyttää siltä, että VPN alkoi toimia, tai siltä, että asiaankuulumaton sovellus menetti yhteyden, riippuen siitä, mitkä bitit ylikirjoitettiin.

Jos merkintöihin on pakko koskea, lue ensin nykyinen arvo ja käytä maskia, jotta vain ymmärtämäsi bitit muuttuvat:

ip rule show
ip route show table all | head -40
ip route get 10.20.4.11

Yhteysmerkintä on erillinen objekti pakettimerkinnästä, eikä kumpikaan ole reitti. Merkinnän palauttaminen vastauspaketteihin on eri vaihe kuin taulun valinta lähdössä, ja siksi yksisuuntaiset korjaukset tuottavat yhteyksiä, jotka avautuvat ja jäävät sitten jumiin.

Kuka omistaa säännöt ja taulut

Androidin verkkopalvelu netd luo säännöt ja verkkokohtaiset taulut. AOSP RouteController on paikka, jossa ne säännöt kootaan VPN:ille, fyysisille verkoille ja uid-alueille, ja sen elinkaari on sidottu verkkotapahtumiin eikä asetustiedostoon.

Seuraa kaksi asiaa. Ensiksi, yhdestä puhelimesta löytämäsi prioriteetit ja taulunumerot ovat buildin sisäisiä yksityiskohtia, eivät rajapinta: samannäköiset numerot toisessa Android-versiossa voivat tarkoittaa täysin muuta. Toiseksi tila rakennetaan uudelleen, kun verkot muuttuvat, joten tänään root-kuoresta lisätty sääntö voi olla poissa seuraavan Wi-Fi-siirtymän jälkeen.

Tämä katoaminen raportoidaan usein niin, että järjestelmä jättää reitin huomiotta. Tosiasiassa sääntö, joka valitsi taulun, ei ole enää olemassa, ja taulun sisäinen reitti on nyt paketin näkökulmasta tavoittamaton. Tarkista sääntöluettelo, ei reittiluetteloa, kun toimiva kokoonpano lakkaa toimimasta uudelleenyhdistämisen jälkeen.

Koukkujen järjestystä koskeviin kysymyksiin ei ole yleispätevää vastausta

Kysymykseen siitä, ajetaanko iptablesia ennen VPN-reititystä, ei voi vastata nimeämättä paketin polkua. Paikallisesti luotu paketti kulkee output-koukun kautta, jossa merkinnän muutos laukaisee uudelleenreititystarkistuksen — toinen haku, ei ensimmäisen jälkikäteinen muokkaus. Tetheröidyltä asiakkaalta saapuva paketti kulkee prerouting-polkua ja edelleenlähetetään sen sijaan, ja ketjut, jotka sen näkevät, ovat eri ketjuja.

Sama sääntö voi siis olla tehokas sovelluksen liikenteelle ja näkymätön tether-liikenteelle, ja nollassa pysyvä laskuri kertoo, minkä polun paketti otti, ei sitä, onko sääntö väärä. Käytä laskureita polun selvittämiseen ennen kuin muutat mitään vastausehtoa.

Tämä on myös vaihe, jossa politiikkareitityksen virhe muuttuu vaikeasti nähtäväksi. Reititys tauluun, joka on olemassa mutta ei sisällä kohdetta, tuottaa verkko tavoittamaton -virheen, joka näyttää palomuurin pudotukselta, kun taas palomuurin pudotus tuottaa aikakatkaisun, joka näyttää reitityksen mustalta aukolta.

Tee diagnoosi järjestelmän sisällä tai jätä se rauhaan

Valtuutettua tarkastelua varten selvitä neljä tosiasiaa ennen kuin kosket mihinkään: sovelluksen uid ja profiili, verkko, jonka Android valitsi sille, sisällyttääkö VPN ylipäätään sen sovelluksen, ja esiintyykö ongelma molemmissa osoiteperheissä. Sovelluskohtainen poissulkeminen selittää hyvin monet VPN ei toimi -raportit ilman mitään reititysvikaa.

Lue sitten säännöt, maskit ja taulut, jotka todella ovat voimassa, ja pidä verkonvaihto havaintoikkunan sisällä. Jos käyttäytyminen muuttuu uudelleenyhdistämisen yli, katsot hallittua elinkaarta, et puuttuvaa reittiä.

Tavallisiin vaatimuksiin käytä tuettuja säätimiä: sovelluskohtainen sisällytys ja poissulkeminen VPN-sovelluksessa, ja alustan omaa verkonvalintaa kaikelle, mikä tarvitsee tietyn polun. Jos etuoikeutettu integraatio todella joutuu tekemään yhteistyötä reitityskoneiston kanssa, kohdista se täsmälleen sen Android-version toteutukseen, jota tuet, ja ylläpidä sen elinkaarta komponentin kautta, joka sen omistaa. Alustan ketjujen tyhjentäminen tai korkean prioriteetin säännön lisääminen muuttaa diagnoosin toiseksi verkkohallinnaksi, ja puhelin käyttäytyy sen mukaisesti.

Aiheeseen liittyvät artikkelit