Android VPN атрибуција: getConnectionOwnerUid наспрам /proc/net
Android 10 скрива /proc/net од апликација. VPN и даље прима пакете, али атрибуција прелази на getConnectionOwnerUid, са својим правилима за tuple и дозволе.
На Android-у 10 и новијем апликација која отвори /proc/net/tcp добија одбијен приступ уместо табеле сокета. VPN интерфејс то не занима: пакети и даље стижу, јер је тунел одлука о рутирању, а не дозвола за датотеку. Променио се одговор на уже питање: „која апликација поседује ову везу?“ Замена је ConnectivityManager.getConnectionOwnerUid, подржани упит по вези, а избор између старе навике и новог API-ја зависи од тога који од три посла заправо имате: примање пакета, атрибуцију тока или сабирање потрошње.
Два начина да одговорите на питање о власнику
Пре API 29 привилеговани или root процес могао је да чита кернелове табеле сокета, упари четворку и сазна 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 |
Поређење није „старо против новог“. То су три различита посла која је некад задовољавала једна читљива датотека, а сада их задовољавају три различита интерфејса са три различита уговора.
Локална адреса је крајња тачка апликације
Потпис методе прима протокол, локалну адресу сокета и удаљену адресу сокета. „Локално“ значи страну апликације у вези, а не онај крај који се у тренутку провере случајно нађе као извор пакета. Пакет који путује од удаљеног сервера назад ка апликацији има извор и одредиште обрнуте у односу на ту дефиницију.
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
int uid = cm.getConnectionOwnerUid(
OsConstants.IPPROTO_TCP, appLocalAddress, appRemoteAddress);Та грешка у смеру најчешћи је разлог зашто исправан упит врати погрешан одговор или никакав. Забележите оба краја пре позива и проверите пар према вези коју је апликација заиста отворила. Породица адреса је такође важна: адреса представљена кроз IPv4 и изворна IPv6 адреса су различите четворке, као и TCP и UDP токови на истим портовима.
Овлашћење и непознати резултати део су уговора
Упит је ограничен на овлашћене позиваоце, укључујући активну VPN апликацију за одговарајућег корисника. Неповезана апликација за надзор не може да претпостави да може да наброји везе другог профила, а неовлашћени позив може да баци безбедносни изузетак уместо пријатне грешке. Оба исхода решавајте експлицитно.
Недостајући власник није назив пакета. Ток се могао затворити између пакета и упита, четворка може бити непотпуна или позиваоцу једноставно није дозвољено да зна. Кеширање првог успешног одговора и његово касније коришћење приписује нову везу старој апликацији, што је горе од пријаве непознатог.
Када атрибуција не успе, саобраћај и даље тражи одлуку: блокирајте га где политика то захтева, дозволите само обим који разумете или покажите празнину. Тај резервни пут припада дизајну, не коментару.
Обрачун је друго питање
NetworkStatsManager извештава о потрошњи по сопственим правилима приступа. Може вам рећи колико је UID пренео у периоду; не може рећи власника произвољног живог пакета. Мрежне могућности описују својства мреже, не именик сокета. Мешање троје даје табле које изгледају доследно и нису.
За једноставан случај одлучивања које апликације користе тунел, подржане листе дозвољених и забрањених апликација на Android-у већ изражавају политику без икаквог стругања. Сачувајте атрибуцију по току за случајеве којима заиста треба, и планирајте буџет за одрживу имплементацију која заједно решава смер, дозволе и непозната стања.
Изаберите алат према послу, па тестирајте ивице
Ако је захтев избор тунела, користите листу платформе. Ако је реч о атрибуцији уживо, користите упит власника и сваку четворку без одговора третирајте као непознату. Ако су историјски збирови, користите stats API. Затим тестирајте три ивице које ломе наивне имплементације: пакет у обрнутом смеру, ток који се затвори пре упита и позиваоца који није активни VPN.
Ништа од овога не захтева искључивање SELinux-а, root телефона или глобално читљиве кернел табеле. Ограничење је поента: платформа је преместила атрибуцију иза уговора како би одговор био доступан компоненти којој легитимно треба, и никоме другом.