Android VPN хуваарилалт: getConnectionOwnerUid ба /proc/net
Android 10 нь /proc/net-ийг аппуудаас нуудаг. VPN пакетуудыг хүлээн авсаар байгаа ч хуваарилалт нь өөрийн tuple болон зөвшөөрлийн дүрэмтэй getConnectionOwnerUid рүү шилждэг.
Android 10 ба түүнээс хойшхи хувилбарт /proc/net/tcp нээсэн апп socket хүснэгтийн оронд хандалт татгалзсан хариу авдаг. VPN интерфэйст хамаагүй: пакетууд ирсээр байна, учир нь туннель бол маршрутын шийдвэр, файлын зөвшөөрөл биш. Өөрчлөгдсөн нь илүү нарийн асуултын хариулт: «энэ холболтыг аль апп эзэмших вэ?» Орлуулагч нь ConnectivityManager.getConnectionOwnerUid, холболт тус бүрийн дэмжигдсэн асуулт, харин хуучин дадал ба шинэ API-ийн хоорондын сонголт нь танд үнэхээр гурван ажлын аль нь байгаагаас хамаарна: пакет хүлээн авах, урсгалыг хуваарилах эсвэл хэрэглээг нэгтгэх.
Эзэмшигчийн асуултад хоёр хариулт
API 29-өөс өмнө эрх бүхий эсвэл root процесс цөмийн socket хүснэгтүүдийг уншиж, дөрвийг тааруулж, эзэмшигч UID-г мэдэж болдог байв. Энэ нь бүх төхөөрөмжийн жагсаалтыг нэг файлд өгдөг байсан. API 29-өөс файлын системийн харагдац хязгаарлагдмал бөгөөд дэмжигдсэн зам нь протокол, локал хаяг, алсын хаягтай холболт тус бүрийн асуулт юм.
| Question | Legacy socket tables | getConnectionOwnerUid |
|---|---|---|
| Who owns this flow? | Scan and match the tuple | Ask once per tuple |
| Device-wide inventory? | Yes, when readable | No, one flow at a time |
| Historical usage? | No | No; that is NetworkStatsManager |
| Works without root? | No on modern releases | Yes, for authorized callers |
Харьцуулалт нь «хуучин ба шинэ» биш. Эдгээр нь өмнө нэг уншигдах файлаар хангагддаг байсан, одоо гурван өөр гэрээ бүхий гурван өөр интерфэйсээр хангагддаг гурван өөр ажил юм.
Локал хаяг бол аппын төгсгөл
Аргын гарын үсэг протокол, локал socket хаяг, алсын socket хаягыг авдаг. «Локал» гэдэг нь холболт дахь аппын тал, шалгах мөчид пакетын эх сурвалж болсон төгсгөл биш. Алсын серверээс апп руу буцаж буй пакетын эх сурвалж, очих газар энэ тодорхойлолтод харьцуулахад эсрэг байна.
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);Энэ чиглэлийн алдаа нь ажиллаж буй асуулт буруу хариу өгөх, эсвэл огт өгөхгүй байх хамгийн түгээмэл шалтгаан юм. Дуудлагын өмнө хоёр төгсгөлийг тэмдэглэж, хосыг апп үнэхээр нээсэн холболттой тулгана уу. Хаягийн гэр бүл ч чухал: IPv4-ээр буулгасан хаяг ба уугуул IPv6 хаяг нь өөр дөрөв, мөн нэг порт дээрх TCP ба UDP урсгалууд ч мөн адил.
Эрх олголт ба үл мэдэгдэх үр дүн гэрээний нэг хэсэг
Асуулт нь эрх бүхий дуудагчдад хязгаарлагдана, үүнд холбогдох хэрэглэгчийн идэвхтэй VPN апп орно. Хамааралгүй хяналтын апп өөр профайлын холболтыг тоолж чадна гэж үзэж болохгүй, эрхгүй дуудлага найрсаг алдааны оронд аюулгүй байдлын үл хамаарах зүйл шидэж болно. Хоёр үр дүнг тодорхой зохицуулна уу.
Байхгүй эзэмшигч нь багцын нэр биш. Урсгал пакет ба асуултын хооронд хаагдаж болсон, tuple бүрэн бус байж болох, эсвэл дуудагчид мэдэхийг зөвшөөрөөгүй байж болно. Эхний амжилттай хариуг кэшлээд дараа дахин ашиглах нь шинэ холболтыг хуучин апп-д хамааруулдаг бөгөөд энэ нь үл мэдэгдэх гэж мэдээлэхээс дор.
Хуваарилалт бүтэлгүйтэхэд трафик шийдвэр шаардсаар байна: бодлого шаардсан газарт хоригло, зөвхөн ойлгосон хүрээг зөвшөөр, эсвэл цоорхойг харуул. Тэр нөөц зам нь дизайнд хамаарах, тайлбарт биш.
Нягтлан бодох бүртгэл өөр асуулт
NetworkStatsManager хэрэглээг өөрийн хандалтын дүрмээр мэдээлдэг. Аль UID тодорхой хугацаанд хэр их дамжуулсныг хэлж чадна; дурын амьд пакетын эзэмшигчийг хэлж чадахгүй. Сүлжээний боломжууд сүлжээний шинж чанарыг тодорхойлдог, socket-ийн лавлах биш. Гурвыг холих нь тогтвортой харагдах боловч тийм биш хяналтын самбар үүсгэдэг.
Аль апп туннель ашигладагыг шийдэх энгийн тохиолдолд Android-ийн дэмжигдсэн зөвшөөрөгдсөн ба хориглосон апп жагсаалтууд ямар ч scrapingгүйгээр бодлогыг илэрхийлдэг. Урсгал тус бүрийн хуваарилалтыг үнэхээр шаардлагатай тохиолдолд үлдээж, чиглэл, зөвшөөрөл, үл мэдэгдэх төлвийг хамт зохицуулдаг арчлагдсан хэрэгжүүлэлтэд төсөв төлөвлөөрэй.
Ажлын дагуу хэрэгслээ сонгоод, дараа нь ирмэгүүдийг шалга
Шаардлага нь туннель сонголт бол платформын жагсаалтыг ашигла. Шууд хуваарилалт бол эзэмшигчийн асуултыг ашиглаж, хариугүй дөрөв бүрийг үл мэдэгдэх гэж үз. Түүхэн нийлбэр бол stats API ашигла. Дараа нь энгийн хэрэгжүүлэлтийг эвддэг гурван ирмэгийг шалга: эсрэг чиглэлийн пакет, асуултаас өмнө хаагдах урсгал, идэвхтэй VPN биш дуудагч.
Эдгээрийн аль нь ч SELinux-ийг унтраах, утсыг root хийх, эсвэл цөмийн хүснэгтийг дэлхий даяар уншигдахуйц болгохыг шаарддаггүй. Хязгаарлалт нь гол нь: платформ хуваарилалтыг гэрээний ард шилжүүлснээр хариу нь хууль ёсоор шаардлагатай бүрэлдэхүүнд л хүрнэ, өөр хэнд ч биш.