Në Android 10 e më vonë, një aplikacion që hap /proc/net/tcp merr refuzim aksesi në vend të një tabele socket-esh. Ndërfaqja e VPN-së nuk shqetësohet: paketat vazhdojnë të mbërrijnë, sepse tuneli është një vendim rrugëtimi, jo një leje skedari. Ajo që ndryshoi është përgjigjja ndaj një pyetjeje më të ngushtë: «cila aplikacion zotëron këtë lidhje?» Zëvendësimi është ConnectivityManager.getConnectionOwnerUid, pyetja e mbështetur për çdo lidhje, dhe zgjedhja midis zakonit të vjetër dhe API-së së re varet nga cila nga tre punët ju ka mbetur në të vërtetë: marrja e paketave, atribuimi i një fluksi apo mbledhja e përdorimit.

Dy mënyra për t'iu përgjigjur pyetjes së pronarit

Para API 29, një proces i privilegjuar ose root mund të lexonte tabelat e socket-eve të kernelit, të përputhte katërshen dhe të mësonte UID-në e pronarit. Kjo jepte një inventar të të gjithë pajisjes në një skedar të vetëm. Nga API 29 pamja e sistemit të skedarëve është e kufizuar, dhe rruga e mbështetur është një pyetje për çdo lidhje me protokollin, adresën lokale dhe adresën e largët.

QuestionLegacy socket tablesgetConnectionOwnerUid
Who owns this flow?Scan and match the tupleAsk once per tuple
Device-wide inventory?Yes, when readableNo, one flow at a time
Historical usage?NoNo; that is NetworkStatsManager
Works without root?No on modern releasesYes, for authorized callers

Krahasimi nuk është «i vjetër kundrejt i ri». Janë tre punë të ndryshme që dikur plotësoheshin nga një skedar i lexueshëm dhe tani plotësohen nga tre ndërfaqe të ndryshme me tre kontrata të ndryshme.

Adresa lokale është skaji i aplikacionit

Nënshkrimi i metodës merr një protokoll, një adresë socket lokale dhe një adresë socket të largët. «Lokale» do të thotë ana e aplikacionit në lidhje, jo skaji që në momentin e inspektimit ndodh të jetë burimi i paketës. Një paketë që udhëton nga serveri i largët përsëri te aplikacioni e ka burimin dhe destinacionin të kthyera në raport me atë përkufizim.

ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
    OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);

Ky gabim drejtimi është arsyeja më e zakonshme që një pyetje funksionale kthen përgjigjen e gabuar, ose asnjë. Regjistro të dy skajet para thirrjes dhe konfirmo çiftin kundrejt lidhjes që aplikacioni hapi vërtet. Edhe familja e adresave ka rëndësi: një adresë e hartuar nga IPv4 dhe një adresë native IPv6 janë tuple të ndryshme, si dhe flukset TCP e UDP në të njëjtat porta.

Autorizimi dhe rezultatet e panjohura janë pjesë e kontratës

Pyetja është e kufizuar te thirrësit e autorizuar, përfshirë aplikacionin aktiv të VPN-së për përdoruesin përkatës. Një aplikacion monitorimi i palidhur nuk mund të supozojë se mund të numërojë lidhjet e një profili tjetër, dhe një thirrje e paautorizuar mund të hedhë një përjashtim sigurie në vend që të kthejë një gabim miqësor. Trajto të dyja rezultatet në mënyrë të qartë.

Një pronar që mungon nuk është emër pakete. Fluksi mund të jetë mbyllur midis paketës dhe pyetjes, tuple-i mund të jetë i paplotë, ose thjesht mund të mos i lejohet thirrësit ta dijë. Ruajtja e përgjigjes së parë të suksesshme dhe ripërdorimi i saj më vonë i atribuon një lidhje të re një aplikacioni të vjetër, gjë që është më e keqe sesa të raportosh të panjohur.

Kur atribuimi dështon, trafiku prapëseprapë ka nevojë për një vendim: bllokoje aty ku politika e kërkon, lejo vetëm një shtrirje që e kupton, ose zbulo boshllëkun. Ai plan rezervë i përket dizajnit, jo një komenti.

Kontabiliteti është një pyetje tjetër

NetworkStatsManager raporton përdorimin sipas rregullave të veta të aksesit. Mund të thotë sa ka transferuar një UID gjatë një periudhe; nuk mund të thotë pronarin e një pakete të gjallë arbitrare. Aftësitë e rrjetit përshkruajnë vetitë e një rrjeti, jo një drejtori socket-esh. Përzierja e të trejave prodhon panele që duken konsistente dhe nuk janë.

Për rastin e thjeshtë të vendosjes se cilat aplikacione përdorin tunelin, listat e mbështetura të aplikacioneve të lejuara dhe të ndaluara të Android-it tashmë e shprehin politikën pa asnjë scraping. Ruaj atribuimin për çdo fluks për rastet që kanë vërtet nevojë, dhe parashiko buxhet për një implementim të mirëmbajtur që trajton së bashku drejtimin, lejet dhe gjendjet e panjohura.

Zgjidh mjetin sipas punës, pastaj provo skajet

Nëse kërkesa është zgjedhja e tunelit, përdor listën e platformës. Nëse është atribuim i drejtpërdrejtë, përdor pyetjen e pronarit dhe trajto çdo tuple pa përgjigje si të panjohur. Nëse janë totalet historike, përdor stats API. Pastaj provo tre skajet që thyejnë implementimet naive: një paketë në drejtim të kundërt, një fluks që mbyllet para pyetjes dhe një thirrës që nuk është VPN-ja aktive.

Asnjë nga këto nuk kërkon çaktivizimin e SELinux, rootimin e telefonit ose bërjen e tabelave të kernelit të lexueshme globalisht. Kufizimi është pika: platforma e zhvendosi atribuimin pas një kontrate, që përgjigjja të jetë e disponueshme për komponentin që i nevojitet në mënyrë legjitime, dhe për askënd tjetër.

Artikuj të ngjashëm