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 ਪ੍ਰਕਿਰਿਆ kernel ਦੀਆਂ 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 ਪਤਾ ਵੱਖਰੇ tuple ਹਨ, ਅਤੇ ਉਹੀ ਪੋਰਟਾਂ 'ਤੇ TCP ਤੇ UDP ਫ਼ਲੋ ਵੀ।
ਅਧਿਕਾਰ ਅਤੇ ਅਣਜਾਣ ਨਤੀਜੇ ਇਕਰਾਰਨਾਮੇ ਦਾ ਹਿੱਸਾ ਹਨ
ਕਿਊਰੀ ਅਧਿਕਾਰਤ ਕਾਲਰਾਂ ਤੱਕ ਸੀਮਿਤ ਹੈ, ਜਿਸ ਵਿੱਚ ਸੰਬੰਧਿਤ ਉਪਭੋਗਤਾ ਦੀ ਸਰਗਰਮ VPN ਐਪ ਵੀ ਸ਼ਾਮਲ ਹੈ। ਅਸੰਬੰਧਿਤ ਨਿਗਰਾਨੀ ਐਪ ਇਹ ਨਹੀਂ ਮੰਨ ਸਕਦੀ ਕਿ ਉਹ ਕਿਸੇ ਹੋਰ ਪ੍ਰੋਫ਼ਾਈਲ ਦੇ ਕਨੈਕਸ਼ਨ ਗਿਣ ਸਕਦੀ ਹੈ, ਅਤੇ ਗੈਰ-ਅਧਿਕਾਰਤ ਕਾਲ ਦੋਸਤਾਨਾ ਗ਼ਲਤੀ ਦੀ ਥਾਂ ਸੁਰੱਖਿਆ ਅਪਵਾਦ ਸੁੱਟ ਸਕਦੀ ਹੈ। ਦੋਵੇਂ ਨਤੀਜੇ ਸਪਸ਼ਟ ਰੂਪ ਵਿੱਚ ਸੰਭਾਲੋ।
ਗੁੰਮ ਮਾਲਕ ਪੈਕੇਜ ਨਾਮ ਨਹੀਂ ਹੈ। ਫ਼ਲੋ ਪੈਕੇਟ ਅਤੇ ਕਿਊਰੀ ਵਿਚਕਾਰ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ, tuple ਅਧੂਰਾ ਹੋ ਸਕਦਾ ਹੈ, ਜਾਂ ਕਾਲਰ ਨੂੰ ਜਾਣਨ ਦੀ ਇਜਾਜ਼ਤ ਹੀ ਨਾ ਹੋਵੇ। ਪਹਿਲਾ ਸਫਲ ਜਵਾਬ ਕੈਸ਼ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਮੁੜ ਵਰਤਣਾ ਨਵੇਂ ਕਨੈਕਸ਼ਨ ਨੂੰ ਪੁਰਾਣੀ ਐਪ ਨਾਲ ਜੋੜ ਦਿੰਦਾ ਹੈ, ਜੋ ਅਣਜਾਣ ਦੱਸਣ ਨਾਲੋਂ ਮਾੜਾ ਹੈ।
ਜਦੋਂ ਐਟ੍ਰਿਬਿਊਸ਼ਨ ਫੇਲ ਹੁੰਦਾ ਹੈ, ਟਰੈਫ਼ਿਕ ਨੂੰ ਫਿਰ ਵੀ ਫ਼ੈਸਲਾ ਚਾਹੀਦਾ ਹੈ: ਨੀਤੀ ਜਿੱਥੇ ਮੰਗੇ ਉੱਥੇ ਇਸ ਨੂੰ ਬਲਾਕ ਕਰੋ, ਸਿਰਫ਼ ਉਹ ਘੇਰਾ ਮਨਜ਼ੂਰ ਕਰੋ ਜੋ ਤੁਸੀਂ ਸਮਝਦੇ ਹੋ, ਜਾਂ ਖਾਲੀ ਥਾਂ ਦਿਖਾਓ। ਉਹ ਬਦਲ ਡਿਜ਼ਾਈਨ ਦਾ ਹਿੱਸਾ ਹੈ, ਟਿੱਪਣੀ ਦਾ ਨਹੀਂ।
ਲੇਖਾ ਇੱਕ ਹੋਰ ਸਵਾਲ ਹੈ
NetworkStatsManager ਆਪਣੇ ਪਹੁੰਚ ਨਿਯਮਾਂ ਅਨੁਸਾਰ ਵਰਤੋਂ ਦੀ ਰਿਪੋਰਟ ਕਰਦਾ ਹੈ। ਇਹ ਦੱਸ ਸਕਦਾ ਹੈ ਕਿ ਕਿਸੇ UID ਨੇ ਸਮੇਂ ਦੌਰਾਨ ਕਿੰਨਾ ਭੇਜਿਆ; ਇਹ ਕਿਸੇ ਵੀ ਜੀਵਤ ਪੈਕੇਟ ਦਾ ਮਾਲਕ ਨਹੀਂ ਦੱਸ ਸਕਦਾ। ਨੈੱਟਵਰਕ ਸਮਰੱਥਾਵਾਂ ਨੈੱਟਵਰਕ ਦੇ ਗੁਣ ਵਰਣਨ ਕਰਦੀਆਂ ਹਨ, socket ਦੀ ਸੂਚੀ ਨਹੀਂ। ਤਿੰਨੇ ਮਿਲਾਉਣ ਨਾਲ ਅਜਿਹੇ ਡੈਸ਼ਬੋਰਡ ਬਣਦੇ ਹਨ ਜੋ ਸੰਗਤ ਦਿਸਦੇ ਹਨ ਪਰ ਨਹੀਂ ਹੁੰਦੇ।
ਇਹ ਤੈਅ ਕਰਨ ਦੇ ਸਧਾਰਨ ਮਾਮਲੇ ਲਈ ਕਿ ਕਿਹੜੀਆਂ ਐਪਾਂ ਟਨਲ ਵਰਤਦੀਆਂ ਹਨ, Android ਦੀਆਂ ਸਮਰਥਿਤ ਮਨਜ਼ੂਰ ਅਤੇ ਵਰਜਿਤ ਐਪ ਸੂਚੀਆਂ ਕਿਸੇ ਸਕ੍ਰੈਪਿੰਗ ਤੋਂ ਬਿਨਾਂ ਹੀ ਨੀਤੀ ਪ੍ਰਗਟ ਕਰਦੀਆਂ ਹਨ। ਪ੍ਰਤੀ-ਫ਼ਲੋ ਐਟ੍ਰਿਬਿਊਸ਼ਨ ਉਹਨਾਂ ਮਾਮਲਿਆਂ ਲਈ ਰੱਖੋ ਜਿਨ੍ਹਾਂ ਨੂੰ ਸੱਚਮੁੱਚ ਇਸ ਦੀ ਲੋੜ ਹੈ, ਅਤੇ ਦਿਸ਼ਾ, ਇਜਾਜ਼ਤਾਂ ਤੇ ਅਣਜਾਣ ਹਾਲਤਾਂ ਨੂੰ ਇਕੱਠਿਆਂ ਸੰਭਾਲਣ ਵਾਲੇ ਸੰਭਾਲੇ ਹੋਏ ਅਮਲ ਲਈ ਬਜਟ ਰੱਖੋ।
ਕੰਮ ਮੁਤਾਬਕ ਸਾਧਨ ਚੁਣੋ, ਫਿਰ ਕਿਨਾਰੇ ਜਾਂਚੋ
ਜੇ ਲੋੜ ਟਨਲ ਚੋਣ ਹੈ, ਤਾਂ ਪਲੇਟਫ਼ਾਰਮ ਸੂਚੀ ਵਰਤੋ। ਜੇ ਲਾਈਵ ਐਟ੍ਰਿਬਿਊਸ਼ਨ ਹੈ, ਤਾਂ ਮਾਲਕ ਕਿਊਰੀ ਵਰਤੋ ਅਤੇ ਹਰ ਅਣ-ਜਵਾਬ tuple ਨੂੰ ਅਣਜਾਣ ਮੰਨੋ। ਜੇ ਇਤਿਹਾਸਕ ਜੋੜ ਹਨ, ਤਾਂ stats API ਵਰਤੋ। ਫਿਰ ਉਹ ਤਿੰਨ ਕਿਨਾਰੇ ਜਾਂਚੋ ਜੋ ਭੋਲੇ ਅਮਲ ਤੋੜਦੇ ਹਨ: ਉਲਟ ਦਿਸ਼ਾ ਦਾ ਪੈਕੇਟ, ਕਿਊਰੀ ਤੋਂ ਪਹਿਲਾਂ ਬੰਦ ਹੋਣ ਵਾਲਾ ਫ਼ਲੋ, ਅਤੇ ਅਜਿਹਾ ਕਾਲਰ ਜੋ ਸਰਗਰਮ VPN ਨਹੀਂ ਹੈ।
ਇਹਨਾਂ ਵਿੱਚੋਂ ਕੁਝ ਵੀ SELinux ਬੰਦ ਕਰਨ, ਫ਼ੋਨ root ਕਰਨ ਜਾਂ kernel ਟੇਬਲਾਂ ਨੂੰ ਦੁਨੀਆ ਭਰ ਲਈ ਪੜ੍ਹਨ ਯੋਗ ਬਣਾਉਣ ਦੀ ਮੰਗ ਨਹੀਂ ਕਰਦਾ। ਸੀਮਾ ਹੀ ਗੱਲ ਹੈ: ਪਲੇਟਫ਼ਾਰਮ ਨੇ ਐਟ੍ਰਿਬਿਊਸ਼ਨ ਨੂੰ ਇਕਰਾਰਨਾਮੇ ਪਿੱਛੇ ਕਰ ਦਿੱਤਾ ਤਾਂ ਜੋ ਜਵਾਬ ਉਸ ਹਿੱਸੇ ਨੂੰ ਮਿਲੇ ਜਿਸ ਨੂੰ ਕਾਨੂੰਨੀ ਤੌਰ 'ਤੇ ਇਸ ਦੀ ਲੋੜ ਹੈ, ਕਿਸੇ ਹੋਰ ਨੂੰ ਨਹੀਂ।