Si të përjashtosh një nënrrjet nga tuneli VPN Android
VpnService nuk mund të përjashtojë një rrugë, prandaj shton komplementin: tetë prefikse të gjeneruara për një /8, plus kontrollet IPv6, DNS dhe kërkimi që kapin pjesën tjetër.
VpnService i Android nuk ka rrugë përjashtimi, dhe asnjë sasi leximi API nuk prodhon një të tillë. Builder.addRoute() shton gjithmonë vetëm destinacione në tunel, prandaj mbajtja e një segmenti LAN lokal do të thotë që ai segment nuk hyn kurrë në listën e rrugëve. Ajo që shtoni në vend të kësaj është komplementi i segmentit, i shprehur si prefikse të zakonshme. Puna është aritmetikë, dhe dështon në disa vende të parashikueshme.
Kaloni kontrollet më poshtë sipas radhës. Secila supozon se e mëparshmja qëndroi, prandaj ndaloni në dështimin e parë në vend që të patchoni simptomat më poshtë.
Filloni nga ajo që pretendon tuneli
Kalimi i 0.0.0.0/0 te addRoute() i thotë Android se çdo destinacion IPv4 i përket tunelit. Prandaj kaq shumë klientë duken të paaftë për tunelim të ndarë: pretendojnë të gjithë hapësirën e adresave dhe pastaj përpiqen të zbresin prej saj. Asgjë në ndërtues nuk zbret. Një rrugë më specifike për rrjetin që dëshironit ta mbani lokal bën të kundërtën e asaj që njerëzit presin, sepse fiton prefiksi më i gjatë që përputhet dhe ai rrjet përfundon brenda tunelit.
Lista e rrugëve është e gjithë politika. Nuk ka veto për çdo destinacion pas saj, dhe referenca Builder nuk rendit asnjë metodë që do ta jepte.
Gjeneroni komplementin nga aritmetika e prefikseve
Komplementi i një prefiksi të përjashtuar është bashkësia e vëllezërve të tij në rrugën drejt rrënjës së pemës së adresave. Për çdo gjatësi nga 1 deri në gjatësinë e përjashtuar, merrni bllokun e asaj gjatësie që përmban prefiksin tuaj, ktheni bitin menjëherë nën prefiks dhe nxirrni rezultatin. Tingëllon abstrakte derisa ta ekzekutoni.
Përjashtimi i 10.0.0.0/8 jep tetë rrugë: 128.0.0.0/1, 64.0.0.0/2, 32.0.0.0/3, 16.0.0.0/4, 0.0.0.0/5, 12.0.0.0/6, 8.0.0.0/7, 11.0.0.0/8. Asnjëra nuk përmban 10.0.0.0/8, dhe së bashku mbulojnë gjithçka tjetër.
Tetë rreshta gjenerojnë atë listë për çdo prefiks:
import ipaddress
def complement(addr, length):
base = int(ipaddress.IPv4Address(addr))
out = []
for k in range(1, length + 1):
block = base & (0xFFFFFFFF << (32 - k))
sibling = block ^ (1 << (32 - k))
out.append(f"{ipaddress.IPv4Address(sibling)}/{k}")
return out
print(complement("10.0.0.0", 8))
Numri i rrugëve është i barabartë me gjatësinë e prefiksit, dhe ky është numri që duhet ndjekur. Një përjashtim i vetëm /21 kushton 21 rrugë dhe mbetet i lexueshëm. Dhjetë përjashtime mund të kushtojnë disa qindra, çka zakonisht do të thotë se duhet ndryshuar dizajni i rrjetit, jo gjeneratori.
Kontrolloni familjen e adresave dhe shtrirjen e tunelit
Rrugët IPv4 nuk bëjnë asgjë për IPv6. Nëse tuneli pretendon një adresë IPv6, një prefiks LAN IPv6 ka nevojë për komplementin e vet, të gjeneruar me të njëjtën aritmetikë mbi 128 bit. Një shkak i zakonshëm që përjashtimi funksionon në letër ndërsa pajisja lokale mbetet e paarritshme është ky: hosti u arrit përmes IPv6, dhe vetëm IPv4 ishte prerë. Kontrolloni të dyja familjet para se të konkludoni se matematika është e gabuar.
Shtrirja është gjysma tjetër e kontrollit. Android gjurmon rrugëtimin për rrjet dhe për aplikacion, prandaj i njëjti prefiks mund të shkojë përmes tunelit për një aplikacion dhe drejtpërdrejt për një tjetër, në varësi të mënyrës si është deklaruar VPN.
Vendosni rregullat DNS dhe për aplikacion aty ku u përkasin
Përjashtimet e rrugëve nuk e ndryshojnë zgjidhësin. Një emër hosti lokal mund të përgjigjet ende nga serveri DNS i tunelit ndërsa adresa e tij rrugëtohet lokalisht, dhe mospërputhja shfaqet si një emër që zgjidhet në diçka që LAN nuk mund ta arrijë. Vendosni politikën e zgjidhësit me qëllim, me një domen kërkimi ose një rregull DNS të ndarë. Mos supozoni se rrugët e vendosën atë për ju.
addDisallowedApplication() mban një aplikacion jashtë tunelit; nuk mban një destinacion jashtë për aplikacionet që mbeten brenda. protect() lejon një socket që hapni të anashkalojë tunelin, dhe kështu një tunel shmang kapjen e transportit të vet. Asnjëra nuk e zëvendëson komplementin.
Verifikoni me një kërkim, jo me listën tuaj
Pasi tuneli të jetë ngritur, pyesni pajisjen se ku shkon vërtet një adresë në vend që të rilexoni listën që ndërtuat. Në një ndërtim që sjell iproute2, adb shell ip route get 10.1.2.3 emërton ndërfaqen që zgjodhi kerneli. Ekzekutoni të njëjtin komandë për një adresë publike dhe konfirmoni se emërton tunelin.
Dy kontrolle të tjera mbyllin ciklin. Zgjidhni fillimisht një emër lokal, pastaj ekzekutoni adb shell ip route get mbi adresën e zgjidhur dhe kërkoni një ndërfaqe që nuk është tuneli, sepse një adb shell ping -c 1 host.lan i suksesshëm provon arritshmërinë dhe jo rrugën. Përsëritni testin e familjes së adresave mbi IPv6 nëse tuneli pretendon një. Testoni në nivelin e API që shpërndani, sepse mënyra si rrjetet VPN ekspozohen ndaj tabelës së rrugëtimit ka ndryshuar midis versioneve. Një listë rrugësh që duket e saktë në letër dhe një kërkim që zgjedh ndërfaqen e gabuar janë të meta të ndryshme, dhe vetëm e dyta arrin te përdoruesit.
Nëse lista e përjashtimeve vazhdon të rritet, ndaloni gjenerimin e rrugëve dhe rinumeroni rrjetin e largët ose ngushtoni tunelin. Gjeneratori është një anashkalim për API-në që mungon, jo një mjet dizajni.