Pse Android VpnService kap një pjesë të trafikut dhe jo të gjithin
Rrugët, zërat DNS dhe shtrirja për aplikacion vendosin cilat paketa arrijnë te pajisja tun, pse zhduken pajisjet lokale dhe çfarë refuzon ndërtuesi.
Asgjë në VpnService nuk e kap trafikun vetë. Ai i kërkon sistemit një ndërfaqe tun, i jep asaj ndërfaqeje një grup adresash dhe rrugësh, dhe nga ai moment bërthama kopjon çdo paketë që përputhet me ato rrugë në një përshkrues skedari që aplikacioni mund ta lexojë. Kodi i aplikacionit nuk i sheh kurrë paketat që rrugët nuk i zgjodhën, prandaj shtrirja e një tuneli është pyetje e tabelës së rrugëtimit përpara se të jetë pyetje programimi. Për këtë arsye i njëjti implementim shërbimi mund të gëlltisë çdo rrjedhë në një telefon dhe vetëm një pjesë në një tjetër, dhe për këtë arsye shtimi i një rruge ndonjëherë rregullon një tunel që dukej i prishur. Merrni atë që keni deklaruar, minus gjithçka që ndërtuesi refuzoi në heshtje.
Rrugët vendosin cilat paketa vijnë
Builder.addRoute(prefix, prefixLength) instalon një prefiks në tabelën e rrugëtimit të rrjetit VPN. Sistemi e trajton atë rrjet si të parazgjedhur për aplikacionet brenda shtrirjes, prandaj zërat e tij shihen përpara rrugës së parazgjedhur të rrjetit fizik dhe një prefiks që përputhet mjafton për të devijuar një rrjedhë. Prandaj një rrugë për 0.0.0.0/0 merr IPv4 të plotë, duke përfshirë printerin, objektivin cast dhe faqen e administrimit të ruterit.
Klientët që duan atë mbulim pa fshirë zërin fizik të parazgjedhur përdorin në vend të tij çiftin 0.0.0.0/1 dhe 128.0.0.0/1. Dy rrugë më specifike mposhtin një rrugë të parazgjedhur, bashkë mbulojnë të gjithë hapësirën e adresave, dhe zëri i parazgjedhur i telefonit mbetet në tabelë për soketet që janë ende të lidhura me rrjetin fizik.
Adresat dhe zërat DNS vijnë nga i njëjti ndërtues dhe përgjigjen një pyetjeje tjetër. addAddress i jep ndërfaqes një adresë me gjatësi prefiksi, dhe addDnsServer instalon një zgjidhës që aplikacionet brenda shtrirjes do ta pyesin përmes ndërfaqes. Të dyja familjet mund të rrinë në një ndërfaqe, prandaj një grup rrugësh vetëm IPv4 pranë një adrese IPv6 është një konfigurim që lexohet saktë dhe gjithsesi rrjedh. Nëse rrugëtoni një familje në të cilën ndërfaqja nuk ka adresë, bërthama nuk ka adresë burimi për ato paketa dhe ato nuk shfaqen kurrë te përshkruesi.
Çfarë kthen establish()
establish() kthen një ParcelFileDescriptor, ose null kur aplikacioni nuk është i autorizuar. Null është një gjendje pëlqimi dhe jo një gabim rrjeti: VpnService.prepare() duhet të ketë kthyer tashmë null, ose përdoruesi duhet të ketë miratuar dialogun e sistemit përpara thirrjes. Pëlqimi mund të tërhiqet ndërsa shërbimi punon, dhe ndërfaqja mbyllet nën këmbët tuaja pa asnjë kthim thirrjeje në ciklin tuaj të leximit.
Përshkruesi nuk bllokon përveç nëse thoni ndryshe, prandaj një lexim kthehet menjëherë pa të dhëna në vend që ta parkojë fillin. Një cikël i shkruar për një soket bllokues djeg një bërthamë, dhe një cikël që e trajton një lexim bosh si fatal e shqyen tunelin në një sekondë boshe. Builder.setBlocking(true) e ndryshon atë sjellje, dhe çmimi është një fill që pret brenda leximit.
Argumentet e rrugës dhe adresës validohen si vlera LinkAddress, dhe destinacionet multicast si 224.0.0.0/4 refuzohen menjëherë. Një ndërfaqe tun pikë-për-pikë nuk ka as domen transmetimi, prandaj zbulimi multicast përmes saj kërkon një dizajn tjetër dhe jo një rrugë më shumë. Referenca VpnService.Builder është lista që duhet kontrolluar përpara se të konkludoni që një thirrje u injorua.
Shtrirja për aplikacion ngushton grupin, jo tunelin
Nga API 21 ndërtuesi pranon addAllowedApplication dhe addDisallowedApplication, dhe të dyja listat përjashtojnë njëra-tjetrën brenda një ndërtuesi. Një listë e lejuar e bën tunelin ekzistues për ato paketa ndërsa gjithçka tjetër ruan rrjetin fizik; një listë e ndaluar kap gjithçka përveç paketave të emërtuara, çka një klient e ofron si tunelim të ndarë. Përpara API 21 nuk ka fare mekanizëm platforme, dhe sjellja për aplikacion vinte nga klientë të palëve të treta që filtronin sipas UID brenda përcjellësit të tyre. Dallimi ka rëndësi gjatë korrigjimit, sepse një tunel për aplikacion me listë të lejuar prej një pakete pothuajse nuk prodhon trafik dhe kjo është sjellje e saktë, jo një rrugë e prishur.
Cilado qoftë shtrirja, soketi që aplikacioni juaj hap drejt serverit VPN nuk duhet të udhëtojë nëpër tunelin që po ndërton. VpnService.protect(socket) e lidh atë soket me rrjetin themelor që paketat e tij të kalojnë pajisjen tun. Nëse e kaloni thirrjen, shtrëngimi i duarve gëlltitet nga ndërfaqja që duhej ta ngrinte.
VpnService.setUnderlyingNetworks e mbyll ciklin duke i thënë sistemit cili rrjet fizik e mbart tunelin. Ai vlerë përcakton si VPN-i raporton lidhshmërinë te aplikacionet e tjera, dhe një vlerë null ose e vjetër është shkak i zakonshëm i një tuneli të lidhur që pjesa tjetër e telefonit e trajton si jashtë linje. Përditësojeni kur ndryshon rrjeti themelor, jo vetëm në nisje.
Shumat e kontrollit dhe MTU: ku një rrugë e saktë dështon gjithsesi
Pasi paketat mbërrijnë, dy detaje në nivel pakete vendosin nëse diçka funksionon nga fillimi në fund. I pari është adresa e burimit: me disa adresa ndërfaqeje bërthama mund të lëshojë paketa që mbartin të parën, prandaj një përcjellës që rishkruan kryet duhet të rregullojë adresën dhe shumën e kontrollit që e mbulon.
I dyti është shtrirja e shumës së kontrollit. Kur aplikacioni ndërton vetë paketa TCP ose UDP, shuma e kontrollit mbulon një pseudo-krye që mban adresën e burimit, adresën e destinacionit, numrin e protokollit dhe gjatësinë e transportit, dhe heqja e cilësdo prej tyre jep paketa që mbërrijnë dhe hidhen. Ai dështim duket si një skadim kohe pas një përgjigjeje që nuk vjen kurrë, çka shumicën i kthen te rrugët. setMtu fikson MTU-në e ndërfaqes, dhe çdo lexim kthen saktësisht një paketë IP të plotë, prandaj një bufer i shkruar për një rrjedhë bajtësh do të copëtojë analizën tuaj, jo paketën.
Një raund verifikimi që i ndan shtresat
Për të gjetur ku shtrirja shkoi keq, provoni shtresat me radhë. Pyetni pajisjen cilat rrugë mban vërtet rrjeti VPN, pastaj kontrolloni nëse një rrjedhë drejt një adrese të njohur shfaqet si lexim te përshkruesi, pastaj kontrolloni nëse paketa që lëshon përcjellësi juaj është e formuar mirë. Një problem rruge nuk tregon asgjë te përshkruesi, ndërsa një problem shume kontrolli tregon një paketë që mbërrin dhe zhduket.
Nëse asgjë nuk arrin te përshkruesi, i dyshuari është grupi i rrugëve dhe jo lexuesi: konfirmoni prefikset, konfirmoni se ka një adresë në të njëjtën familje, dhe konfirmoni se aplikacioni është brenda shtrirjes që vendosët. Nëse paketat arrijnë te përshkruesi por asgjë nuk kthehet, inspektoni protect() dhe vlerën e rrjetit themelor përpara se të prekni përsëri një rrugë. Nëse ana e largët raporton paketa të keqformuara, shuma e kontrollit dhe MTU-ja janë vendet ku duhet parë. Një provë për shtresë kursen një pasdite hamendjesh.