ਗ਼ਲਤ ਧਾਰਨਾ ਇਹ ਹੈ ਕਿ VpnService ਐਪ ਸਿਸਟਮ ਦਾ ਸਵਿੱਚ ਘੁਮਾਉਂਦੀ ਹੈ ਅਤੇ ਉਸ ਤੋਂ ਬਾਅਦ ਫ਼ੋਨ ਸੁਰੱਖਿਅਤ ਰਹਿੰਦਾ ਹੈ। ਅਸਲ ਵਿੱਚ ਜੋ ਹੁੰਦਾ ਹੈ ਉਹ ਵਧੇਰੇ ਸੰਕੀਰਣ ਹੈ: ਐਪ ਸਹਿਮਤੀ ਮੰਗਦੀ ਹੈ, ਇੱਕ ਇੰਟਰਫ਼ੇਸ ਬਣਾਉਂਦੀ ਹੈ, ਫ਼ਾਈਲ ਡਿਸਕ੍ਰਿਪਟਰ ਰਾਹੀਂ ਪੈਕਟ ਪੜ੍ਹਦੀ ਅਤੇ ਲਿਖਦੀ ਹੈ, ਅਤੇ ਰੁਕਣ ’ਤੇ ਇੰਟਰਫ਼ੇਸ ਵਾਪਸ ਦਿੰਦੀ ਹੈ। ਇੱਕ ਸਮੇਂ ਸਿਰਫ਼ ਇੱਕ ਹੀ ਅਜਿਹੀ ਸੁਰੰਗ ਜੀਵਤ ਰਹਿ ਸਕਦੀ ਹੈ, ਅਤੇ ਸਿਸਟਮ ਬਿਨਾਂ ਪੁੱਛੇ ਉਹ ਲੈ ਸਕਦਾ ਹੈ। ਲੋਕ ਪ੍ਰੋਟੋਕਾਲ ’ਤੇ ਜੋ ਉਲਝਣ ਭਰਿਆ ਵਿਵਹਾਰ ਲਾਉਂਦੇ ਹਨ, ਉਸ ਦਾ ਵੱਡਾ ਹਿੱਸਾ ਇਸੇ ਮਾਲਕੀ ਮਾਡਲ ਤੋਂ ਆਉਂਦਾ ਹੈ।

ਹਰ ਜੀਵਨ ਚੱਕਰ ਤਬਦੀਲੀ ਨੂੰ ਕਿਨਾਰੇ ਦਾ ਕੇਸ ਨਹੀਂ, ਡਿਜ਼ਾਈਨ ਦਾ ਹਿੱਸਾ ਮੰਨੋ।

ਭਰਮ: ਐਪ ਫ਼ੋਨ ਦਾ VPN ਚਾਲੂ ਕਰਦੀ ਹੈ

VpnService.prepare() ਨਾਲ ਪ੍ਰਵਾਹ ਸ਼ੁਰੂ ਹੁੰਦਾ ਹੈ, ਜੋ ਇੱਕ Intent ਵਾਪਸ ਕਰਦਾ ਹੈ ਜਿਸ ਨੂੰ ਵਰਤੋਂਕਾਰ ਨੂੰ ਸਵੀਕਾਰ ਕਰਨਾ ਪੈਂਦਾ ਹੈ, ਅਤੇ establish() ਨਾਲ ਅੱਗੇ ਵਧਦਾ ਹੈ, ਜੋ ਬਾਅਦ ਵਿੱਚ ਵੀ ਐਪ ਵੱਲੋਂ ਕੰਟਰੋਲ ਨਾ ਕੀਤੇ ਕਾਰਨਾਂ ਕਰਕੇ ਫੇਲ੍ਹ ਹੋ ਸਕਦਾ ਹੈ। ਦੂਜੀ ਸੁਰੰਗ ਸਥਾਪਿਤ ਕਰਨ ਨਾਲ ਪਹਿਲਾ ਇੰਟਰਫ਼ੇਸ ਨਿਸ਼ਕ੍ਰਿਯ ਹੋ ਜਾਂਦਾ ਹੈ ਅਤੇ ਸਿਸਟਮ ਸੂਚਨਾ ਬਦਲ ਜਾਂਦੀ ਹੈ। ਉਸ ਕ੍ਰਮ ਵਿੱਚ ਕਿਤੇ ਵੀ ਐਪ ਕੋਲ ਪੂਰੇ ਯੰਤਰ ਦਾ ਸਵਿੱਚ ਨਹੀਂ ਹੁੰਦਾ; ਉਸ ਕੋਲ ਦਿੱਤਾ ਗਿਆ ਡਿਸਕ੍ਰਿਪਟਰ ਅਤੇ ਉਸ ’ਤੇ ਆਉਣ ਵਾਲੇ ਪੈਕਟ ਹੁੰਦੇ ਹਨ। ਸਥਾਈ ਸੂਚਨਾ ਵੀ ਐਪ ਦੇ ਡਿਜ਼ਾਈਨ ਦੀ ਨਹੀਂ, ਸਿਸਟਮ ਦੀ ਹੈ।

ਇੰਟਰਫ਼ੇਸ ਖੋਹਿਆ ਨਹੀਂ ਜਾਂਦਾ ਸਗੋਂ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ, ਇਸ ਲਈ ਕੋਈ ਹੋਰ ਕਲਾਇੰਟ ਕਦੇ ਵੀ ਥਾਂ ਲੈ ਸਕਦਾ ਹੈ। ਐਪ ਇਹ ਰਿਟਰਨ ਮੁੱਲ ਰਾਹੀਂ ਨਹੀਂ, ਕਾਲਬੈਕ ਰਾਹੀਂ ਜਾਣਦੀ ਹੈ।

ਐਪ ਨੂੰ ਜ਼ਬਰਦਸਤੀ ਰੋਕਣਾ ਸੂਚਨਾ ਪੈਨਲ ਵਿੱਚ ਦਿਖਣ ਦਾ ਕਾਰਨ ਵੀ ਇਹੀ ਹੈ: ਸਿਸਟਮ ਦੱਸਦਾ ਹੈ ਕਿ ਉਸ ਨੇ ਕੀ ਦਿੱਤਾ, ਇਹ ਨਹੀਂ ਕਿ ਐਪ ਨੇ ਕੀ ਦਿਖਾਉਣਾ ਚੁਣਿਆ।

ਭਰਮ: ਸਹਿਮਤੀ ਇੱਕ ਵਾਰ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ

ਜਦੋਂ ਸਿਸਟਮ ਸੁਰੰਗ ਕਿਸੇ ਹੋਰ ਕਲਾਇੰਟ ਨੂੰ ਸੌਂਪਦਾ ਹੈ, ਤਾਂ ਉਹ ਉਸ binder ’ਤੇ ਰੱਦ ਕਰਨ ਦਾ ਲੈਣ-ਦੇਣ ਭੇਜਦਾ ਹੈ ਜੋ ਬੇਸ ਕਲਾਸ onBind() ਤੋਂ ਵਾਪਸ ਕਰਦੀ ਹੈ। ਜੋ ਐਪ ਉਸ binder ਨੂੰ ਆਪਣੇ ਨਾਲ ਬਦਲਦੀ ਹੈ, ਉਸ ਨੂੰ ਰੱਦ ਕਰਨ ਦਾ ਲੈਣ-ਦੇਣ ਆਪ ਅੱਗੇ ਭੇਜਣਾ ਪੈਂਦਾ ਹੈ, ਨਹੀਂ ਤਾਂ VpnService.onRevoke() ਕਦੇ ਸਰਗਰਮ ਨਹੀਂ ਹੁੰਦਾ ਅਤੇ ਸੇਵਾ ਉਸ ਡਿਸਕ੍ਰਿਪਟਰ ਵਿੱਚ ਲਿਖਦੀ ਰਹਿੰਦੀ ਹੈ ਜੋ ਹੁਣ ਮੌਜੂਦ ਨਹੀਂ। ਵਰਤੋਂਕਾਰ ਵੀ ਮਨਜ਼ੂਰੀ ਵਾਪਸ ਲੈ ਸਕਦਾ ਹੈ, ਅਤੇ ਸਿਸਟਮ ਰੀਸਟਾਰਟ ਜਾਂ ਹਮੇਸ਼ਾ-ਚਾਲੂ ਮੁੜ ਜੁੜਨ ਦੌਰਾਨ ਸੇਵਾ ਰੋਕ ਸਕਦਾ ਹੈ।

ਇਸ ਨੂੰ ਸੰਭਾਲਣਾ ਲਾਗ ਦੀ ਇੱਕ ਲਾਈਨ ਨਹੀਂ, ਠੋਸ ਕੰਮ ਹੈ: ਡਿਸਕ੍ਰਿਪਟਰ ਪੜ੍ਹਨਾ ਬੰਦ ਕਰੋ, ਉਹ ਬੰਦ ਕਰੋ, ਜੁੜਿਆ ਫ਼ਲੈਗ ਸਾਫ਼ ਕਰੋ ਅਤੇ ਵਰਤੋਂਕਾਰ ਨੂੰ ਦੱਸੋ ਕਿ ਉਹ ਕਿਹੜੀ ਹਾਲਤ ਵਿੱਚ ਹੈ। ਫਿਰ ਫ਼ੈਸਲਾ ਕਰੋ ਕਿ ਐਪ ਨੂੰ ਮੁੜ ਸਥਾਪਿਤ ਕਰਨਾ ਹੈ, ਮੁੜ ਪੁੱਛਣਾ ਹੈ ਜਾਂ ਉਡੀਕ ਕਰਨੀ ਹੈ, ਕਿਉਂਕਿ ਹਮੇਸ਼ਾ-ਚਾਲੂ ਸੰਰਚਨਾ ਵਿੱਚ ਸਿਸਟਮ ਸੇਵਾ ਆਪੇ ਵਾਪਸ ਲਿਆ ਸਕਦਾ ਹੈ।

ਜੋ ਐਪ ਰੱਦ ਕਰਨ ਨੂੰ ਹਾਲਤ ਨਹੀਂ ਸਗੋਂ ਅਪਵਾਦ ਮੰਨਦੀ ਹੈ, ਉਹ ਜੁੜਿਆ ਹੋਣ ਦੀ ਰਿਪੋਰਟ ਦਿੰਦੀ ਰਹੇਗੀ ਜਦਕਿ ਉਸ ਦੁਆਰਾ ਲਿਖਿਆ ਹਰ ਪੈਕਟ ਸੁੱਟਿਆ ਜਾਂਦਾ ਹੈ, ਅਤੇ ਗੋਪਨੀਯਤਾ ਸਾਧਨ ਲਈ ਇਹ ਸਭ ਤੋਂ ਭੈੜਾ ਫੇਲ੍ਹ ਹੋਣ ਦਾ ਢੰਗ ਹੈ।

ਭਰਮ: ਇੰਟਰਫ਼ੇਸ ਤੁਹਾਡੇ ਲਈ ਟ੍ਰੈਫ਼ਿਕ ਛਾਂਟਦਾ ਹੈ

ਜੋ ਆਉਂਦਾ ਹੈ ਉਹ ਕੱਚਾ IP ਹੈ। ਫੜਨਾ ਜਾਂ ਛਾਂਟਣਾ ਭਾਵ IP, TCP, UDP ਅਤੇ IPv6 ਹੈਡਰ ਪਾਰਸ ਕਰਨਾ, ਪ੍ਰਵਾਹ ਟ੍ਰੈਕ ਕਰਨਾ ਅਤੇ ਜਵਾਬ ਡਿਸਕ੍ਰਿਪਟਰ ਵਿੱਚ ਵਾਪਸ ਲਿਖਣਾ, ਜੋ ਕੈਪਚਰ ਐਪ ਨੂੰ ਸਿਸਟਮ ਸਹੂਲਤ ਨਹੀਂ ਸਗੋਂ ਛੋਟਾ ਨੈੱਟਵਰਕ ਸਟੈਕ ਬਣਾ ਦਿੰਦਾ ਹੈ। protect() ਇਸ ਲਈ ਹੈ ਕਿ ਐਪ ਦਾ ਆਪਣਾ ਟ੍ਰਾਂਸਪੋਰਟ ਸਾਕਟ ਆਪਣੇ ਆਪ ਨੂੰ ਫੜਨ ਦੀ ਥਾਂ ਆਪਣੀ ਸੁਰੰਗ ਬਚਾ ਲਵੇ, ਅਤੇ ਇਹ ਸੁਰੰਗ ਉੱਠਣ ਤੋਂ ਬਾਅਦ ਬਣੇ ਹਰ ਸਾਕਟ ’ਤੇ ਜਾਂਚਣ ਯੋਗ ਬੂਲੀਅਨ ਵਾਪਸ ਕਰਦਾ ਹੈ।

ਬਿਲਡਰ ਦੀਆਂ ਮਨਜ਼ੂਰ ਅਤੇ ਵਰਜਿਤ ਐਪਲੀਕੇਸ਼ਨ ਸੂਚੀਆਂ ਤੈਅ ਕਰਦੀਆਂ ਹਨ ਕਿ ਕਿਸ ਦਾ ਟ੍ਰੈਫ਼ਿਕ ਇੰਟਰਫ਼ੇਸ ਵਿੱਚ ਦਾਖਲ ਹੁੰਦਾ ਹੈ। ਉਹ ਇੰਟਰਫ਼ੇਸ ਵੱਲੋਂ ਢੋਏ IP ਪੈਕਟਾਂ ਤੋਂ ਬਾਹਰ ਪੇਲੋਡ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਦਿੰਦੀਆਂ, ਅਤੇ ਕੋਈ API ਕਿਸੇ ਹੋਰ ਕਲਾਇੰਟ ਦੀ ਸੁਰੰਗ ਜ਼ਾਹਰ ਨਹੀਂ ਕਰਦਾ ਜਾਂ ਸਿਸਟਮ ਦੇ VPN ਪਰੋਫ਼ਾਈਲ ਸੂਚੀਬੱਧ ਕਰਦਾ ਹੈ। ਨੈੱਟਵਰਕ ਸਮਰੱਥਾਵਾਂ ਕਹਿ ਸਕਦੀਆਂ ਹਨ ਕਿ ਕੋਈ ਨੈੱਟਵਰਕ VPN ਟਰਾਂਸਪੋਰਟ ਹੈ, ਪਰ ਇਹ ਨਹੀਂ ਕਿ ਸੁਰੰਗ ਕਿਸ ਦੀ ਹੈ।

ਇਸੇ ਲਈ ਹੋਰ ਐਪਾਂ ਬਾਰੇ ਹਾਲਤ ਦੇ ਸਵਾਲਾਂ ਨੂੰ ਵਿਰੋਧਾਭਾਸੀ ਜਵਾਬ ਮਿਲਦੇ ਹਨ: ਜਾਣਕਾਰੀ ਤੁਹਾਡੀ ਪ੍ਰਕਿਰਿਆ ਨੂੰ ਜ਼ਾਹਰ ਹੀ ਨਹੀਂ ਕੀਤੀ ਜਾਂਦੀ।

ਜੀਵਨ ਚੱਕਰ ਅਸਲ ਵਿੱਚ ਕੀ ਮੰਗਦਾ ਹੈ

ਉਹ ਹਾਲਤਾਂ ਟ੍ਰੈਕ ਕਰੋ ਜੋ ਤੁਸੀਂ ਕੰਟਰੋਲ ਕਰਦੇ ਹੋ: ਤਿਆਰ, ਸਥਾਪਿਤ, ਰੱਦ, ਰੁਕਿਆ। ਮੁੜ ਜੁੜਨਾ ਤੋੜਨਾ ਅਤੇ ਫਿਰ ਸਥਾਪਿਤ ਕਰਨਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ, ਡਿਸਕ੍ਰਿਪਟਰ ਅਤੇ ਟ੍ਰਾਂਸਪੋਰਟ ਸਾਕਟ ਲਈ ਇੱਕੋ ਮਾਲਕ ਨਾਲ, ਕਿਉਂਕਿ ਸਥਾਪਿਤ ਕਰਨ ਲਈ ਮੁਕਾਬਲਾ ਕਰਦੇ ਦੋ ਹਿੱਸੇ ਇੱਕੋ ਉਪਲਬਧ ਥਾਂ ਲਈ ਲੜਨਗੇ। ਆਧੁਨਿਕ Android ’ਤੇ ਬੈਕਗਰਾਊਂਡ ਸ਼ੁਰੂਆਤ ਸੀਮਤ ਹਨ, ਇਸ ਲਈ ਬੂਟ ਪ੍ਰਸਾਰਣ ਕੋਈ ਗਾਰੰਟੀ ਨਹੀਂ; API ਪੱਧਰ ਜਿੱਥੇ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਉੱਥੇ ਇਸ ਦੀ ਸੂਚਨਾ ਸਮੇਤ ਫ਼ੋਰਗਰਾਊਂਡ ਸੇਵਾ ਵਰਤੋ।

ਸਿਰਫ਼ ਅੰਤਿਮ ਹਾਲਤ ਨਹੀਂ, ਤਬਦੀਲੀ ਲਾਗ ਕਰੋ, ਅਤੇ ਹਰ ਰਾਹ ਜਾਂਚ ਸਕਣ ਜਿੰਨੀ ਛੋਟੀ ਹਾਲਤ ਮਸ਼ੀਨ ਰੱਖੋ। ਜਿਸ ਹਾਲਤ ਤੱਕ ਤੁਸੀਂ ਜਾਂਚ ਵਿੱਚ ਨਹੀਂ ਪਹੁੰਚ ਸਕਦੇ, ਉਹ ਹਾਲਤ ਲਾਗ ਤੋਂ ਬਿਨਾਂ ਖੇਤਰ ਵਿੱਚ ਮਿਲੇਗੀ।

ਯੰਤਰ ’ਤੇ ਜੀਵਨ ਚੱਕਰ ਜਾਂਚੋ

ਇਮਿਊਲੇਟਰ ਜੁੜਾਅ ਨਕਲੀ ਕਰ ਸਕਦੇ ਹਨ, ਪਰ ਸਹਿਮਤੀ ਅਤੇ ਰੱਦ ਕਰਨ ਦਾ ਰਾਹ ਭਰੋਸੇਯੋਗ ਢੰਗ ਨਾਲ ਨਹੀਂ, ਇਸ ਲਈ ਇਹ ਥਾਂ ਚੋਰੀ ਕਰਨ ਲਈ ਦੂਜਾ VPN ਕਲਾਇੰਟ ਸਥਾਪਿਤ ਕੀਤੇ ਅਸਲੀ ਯੰਤਰ ’ਤੇ ਚਲਾਓ।

adb shell dumpsys connectivity | grep -i -A3 vpn
adb shell dumpsys activity services | grep -i -A2 vpnservice
adb logcat -s VpnService:V AndroidRuntime:E
adb shell am force-stop com.example.vpnapp

ਸੁਰੰਗ ਸ਼ੁਰੂ ਕਰੋ, ਸੂਚਨਾ ਅਤੇ ਇੰਟਰਫ਼ੇਸ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ, ਫਿਰ ਦੂਜਾ ਕਲਾਇੰਟ ਜੋੜੋ ਅਤੇ ਦੇਖੋ ਕਿ ਰੱਦ ਕਰਨ ਦਾ ਕਾਲਬੈਕ ਚੱਲਦਾ ਹੈ ਅਤੇ ਹਾਲਤ ਸਾਫ਼ ਹੁੰਦੀ ਹੈ। ਐਪ ਨੂੰ ਜ਼ਬਰਦਸਤੀ ਰੋਕੋ ਅਤੇ ਜਾਂਚੋ ਕਿ ਕੀ ਕੁਝ ਅਜੇ ਵੀ ਜੀਵਤ ਡਿਸਕ੍ਰਿਪਟਰ ਦੀ ਰਿਪੋਰਟ ਕਰਦਾ ਹੈ।

ਹਮੇਸ਼ਾ-ਚਾਲੂ ਰੀਸਟਾਰਟ ਤੋਂ ਬਾਅਦ ਕ੍ਰਮ ਦੁਹਰਾਓ, ਕਿਉਂਕਿ ਉਹ ਰਾਹ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਸ਼ੁਰੂ ਕੀਤੇ ਜੋੜ ਤੋਂ ਵੱਖਰਾ ਹੈ। ਤੁਸੀਂ ਹਰਾ ਚਿੰਨ੍ਹ ਨਹੀਂ ਲੱਭ ਰਹੇ, ਸਗੋਂ ਇਹ ਸਬੂਤ ਲੱਭ ਰਹੇ ਹੋ ਕਿ ਐਪ ਨੇ ਉਸ ਡਿਸਕ੍ਰਿਪਟਰ ਦੀ ਵਰਤੋਂ ਬੰਦ ਕਰ ਦਿੱਤੀ ਜੋ ਹੁਣ ਉਸ ਦਾ ਨਹੀਂ ਸੀ।

ਸੰਬੰਧਿਤ ਲੇਖ