Android VpnService ਜੁੜਦਾ ਹੈ ਪਰ ਕੋਈ ਪੈਕੇਟ ਨੈੱਟਵਰਕ ਤੱਕ ਨਹੀਂ ਪਹੁੰਚਦਾ
ਟਨਲ ਚਾਲੂ ਹੈ ਅਤੇ ਪੇਜ ਅਜੇ ਵੀ ਫੇਲ ਹੁੰਦੇ ਹਨ: VPN ਸਰਵਰ ਨੂੰ ਦੋਸ਼ ਦੇਣ ਤੋਂ ਪਹਿਲਾਂ ਪੜ੍ਹਨ ਮੋਡ, ਸਾਕਟ ਸੁਰੱਖਿਆ, TCP ਸਹਾਇਤਾ ਅਤੇ ਰੂਟ ਸੂਚੀ ਜਾਂਚੋ।
ਟਨਲ ਉੱਪਰ ਆਉਂਦਾ ਹੈ, ਚਾਬੀ ਦਾ ਆਈਕਨ ਦਿਸਦਾ ਹੈ, ਅਤੇ ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਹਰ ਬੇਨਤੀ ਅਜੇ ਵੀ ਸਮਾਂ ਖਤਮ ਹੋ ਕੇ ਫੇਲ ਹੁੰਦੀ ਹੈ। VpnService ਐਪ ਵਿੱਚ ਇਹ ਸੰਜੋਗ ਆਮ ਤੌਰ 'ਤੇ ਦੱਸਦਾ ਹੈ ਕਿ ਪੜ੍ਹਨ ਵਾਲਾ ਲੂਪ ਜੀਵਤ ਹੈ ਅਤੇ ਆਉਟਪੁੱਟ ਅੱਧਾ ਟੁੱਟਿਆ ਹੋਇਆ ਹੈ, ਇਹ ਨਹੀਂ ਕਿ ਸਰਵਰ ਨੇ ਹੈਂਡਸ਼ੇਕ ਨੂੰ ਰੱਦ ਕੀਤਾ। Android ਨੇ ਪਹਿਲਾਂ ਹੀ ਇੰਟਰਫੇਸ ਬਣਾਇਆ, ਐਪ ਦਾ ਟ੍ਰੈਫਿਕ ਉਸ ਵਿੱਚ ਭੇਜਿਆ ਅਤੇ ਤੁਹਾਡੀ ਪ੍ਰਕਿਰਿਆ ਨੂੰ ਫਾਈਲ ਡਿਸਕ੍ਰਿਪਟਰ ਦਿੱਤਾ। ਉਸ ਡਿਸਕ੍ਰਿਪਟਰ ਤੋਂ ਬਾਅਦ ਸਭ ਕੁਝ ਤੁਹਾਡਾ ਕੋਡ ਹੈ, ਅਤੇ ਇੱਕ ਛੁੱਟੀ ਹੋਈ ਕਾਲ ਪੂਰਾ ਸਟ੍ਰੀਮ ਨਿਗਲਣ ਲਈ ਕਾਫੀ ਹੈ।
ਸਿਸਟਮ ਕੀ ਦਿੰਦਾ ਹੈ ਅਤੇ ਕੀ ਨਹੀਂ
establish() tun ਇੰਟਰਫੇਸ ਲਈ ParcelFileDescriptor ਵਾਪਸ ਕਰਦਾ ਹੈ। ਸਿਸਟਮ ਬਾਹਰ ਜਾਣ ਵਾਲੇ IP ਪੈਕੇਟ ਉਸ ਵਿੱਚ ਲਿਖਦਾ ਹੈ ਅਤੇ ਉਮੀਦ ਕਰਦਾ ਹੈ ਕਿ ਤੁਹਾਡੀ ਪ੍ਰਕਿਰਿਆ ਉਹਨਾਂ ਨੂੰ ਪੜ੍ਹੇ, ਤੈਅ ਕਰੇ ਕਿ ਉਹ ਕਿੱਥੇ ਜਾਂਦੇ ਹਨ ਅਤੇ ਆਮ ਸਾਕਟ ਰਾਹੀਂ ਭੇਜੇ। ਹੇਠਾਂ ਕਰਨਲ ਫਾਰਵਰਡਿੰਗ ਨਹੀਂ ਹੈ, ਇਸ ਲਈ ਜਦੋਂ ਕੋਈ ਨਹੀਂ ਪੜ੍ਹਦਾ ਤਾਂ ਪੈਕੇਟ ਸੁੱਟ ਦਿੱਤੇ ਜਾਂਦੇ ਹਨ ਅਤੇ ਇੰਟਰਫੇਸ ਦੇ ਕਾਊਂਟਰ ਕਦੇ ਨਹੀਂ ਹਿੱਲਦੇ।
ਅੰਦਾਜ਼ੇ ਦੀ ਥਾਂ ਗਿਣਤੀ ਨਾਲ ਸ਼ੁਰੂ ਕਰੋ। ਹਰ ਸਫਲ ਪੜ੍ਹਤ 'ਤੇ ਕਾਊਂਟਰ ਵਧਾਓ ਅਤੇ ਪਹਿਲੇ ਕੁਝ ਪੈਕੇਟਾਂ ਦਾ ਮੰਜ਼ਿਲ ਅਤੇ ਪ੍ਰੋਟੋਕੋਲ ਲੌਗ ਕਰੋ। ਜੇ ਟ੍ਰੈਫਿਕ ਬਣਦੇ ਸਮੇਂ ਕਾਊਂਟਰ ਜ਼ੀਰੋ ਰਹਿੰਦਾ ਹੈ, ਤਾਂ ਗੜਬੜ ਤੁਹਾਡੇ ਫਾਰਵਰਡਿੰਗ ਕੋਡ ਤੋਂ ਉੱਪਰ ਹੈ, ਜੋ ਖੋਜ ਨੂੰ ਬਿਲਡਰ ਸੰਰਚਨਾ ਅਤੇ ਪੜ੍ਹਨ ਮੋਡ ਤੱਕ ਸੀਮਿਤ ਕਰਦਾ ਹੈ। ਜੇ ਕਾਊਂਟਰ ਹਿੱਲਦਾ ਹੈ ਅਤੇ ਬ੍ਰਾਊਜ਼ਰ ਫਿਰ ਵੀ ਫੇਲ ਹੁੰਦਾ ਹੈ, ਤਾਂ ਗੜਬੜ ਭੇਜਣ ਜਾਂ ਵਾਪਸ ਆਉਣ ਵਾਲੇ ਰਾਹ ਵਿੱਚ ਹੈ।
ਬਲਾਕਿੰਗ ਪੜ੍ਹਤ ਤੈਅ ਕਰਦੀ ਹੈ ਕਿ ਲੂਪ ਹਿੱਲਦਾ ਹੈ ਜਾਂ ਨਹੀਂ
setBlocking(true) ਡਿਸਕ੍ਰਿਪਟਰ ਨੂੰ ਬਲਾਕਿੰਗ ਮੋਡ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਅਤੇ API 21 ਤੋਂ ਹੈ। ਪੁਰਾਣੇ ਸੰਸਕਰਣਾਂ ਵਿੱਚ ਹੱਲ ਛੋਟਾ JNI ਸਹਾਇਕ ਹੈ, ਜੋ ਕੱਚੇ ਡਿਸਕ੍ਰਿਪਟਰ 'ਤੇ fcntl ਨਾਲ O_NONBLOCK ਹਟਾਉਂਦਾ ਹੈ। ਮੋਡ ਮਹੱਤਵਪੂਰਨ ਹੈ ਕਿਉਂਕਿ ਇਹ ਤੈਅ ਕਰਦਾ ਹੈ ਕਿ ਬਿਨਾਂ ਉਡੀਕ ਰਹੇ ਪੈਕੇਟ ਦੀ ਪੜ੍ਹਤ ਕੀ ਕਰ ਸਕਦੀ ਹੈ।
ਨਾਨ-ਬਲਾਕਿੰਗ ਮੋਡ ਵਿੱਚ ਉਹ ਪੜ੍ਹਤ ਤੁਰੰਤ ਰਿਣਾਤਮਕ ਮੁੱਲ ਨਾਲ ਵਾਪਸ ਆਉਂਦੀ ਹੈ, ਅਤੇ ਨਤੀਜੇ ਨੂੰ ਅਣਡਿੱਠ ਕਰਨ ਵਾਲਾ ਲੂਪ ਕੋਈ ਟ੍ਰੈਫਿਕ ਹਿਲਾਏ ਬਿਨਾਂ ਕੋਰ ਘੁਮਾਉਂਦਾ ਹੈ। ਬਲਾਕਿੰਗ ਮੋਡ ਵਿੱਚ ਪੜ੍ਹਤ ਉਡੀਕਦੀ ਹੈ, ਜੋ ਫਾਰਵਰਡਿੰਗ ਥ੍ਰੈਡ ਚਾਹੁੰਦਾ ਹੈ, ਪਰ ਫਿਰ ਥ੍ਰੈਡ ਨੂੰ ਰੋਕਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ। ਡਿਸਕ੍ਰਿਪਟਰ ਬੰਦ ਕਰਨਾ ਪੜ੍ਹਤ ਨੂੰ ਫੇਲ ਕਰਨ ਦਾ ਸਮਰਥਿਤ ਤਰੀਕਾ ਹੈ ਤਾਂ ਜੋ ਲੂਪ ਬਾਹਰ ਨਿਕਲ ਸਕੇ। ਪ੍ਰਕਿਰਿਆ ਮਾਰਨਾ ਜਾਂ ਥ੍ਰੈਡ ਰੋਕਣਾ ਅਗਲੀ ਸ਼ੁਰੂਆਤ ਨੂੰ ਇੰਟਰਫੇਸ ਨਾਲ ਨਾ ਮਿਲਦੇ ਡਿਸਕ੍ਰਿਪਟਰ ਨਾਲ ਛੱਡ ਸਕਦਾ ਹੈ।
ਹਰ ਕਾਲ ਵਿੱਚ ਇੰਟਰਫੇਸ ਦੇ MTU ਆਕਾਰ ਦੇ ਬਫਰ ਵਿੱਚ ਇੱਕ ਪੈਕੇਟ ਪੜ੍ਹੋ, ਅਤੇ ਜ਼ੀਰੋ ਜਾਂ ਰਿਣਾਤਮਕ ਵਾਪਸੀ ਨੂੰ ਖਾਲੀ ਪੈਕੇਟ ਨਹੀਂ, ਗਲਤੀ ਮੰਨੋ।
ਪਹਿਲੀ ਭੇਜਣ ਤੋਂ ਪਹਿਲਾਂ protect(), ਬਾਅਦ ਵਿੱਚ ਨਹੀਂ
ਇਨਕੈਪਸੂਲੇਟਿਡ ਪੈਕੇਟ ਢੋਣ ਵਾਲੇ ਹਰ ਸਾਕਟ ਨੂੰ ਪਹਿਲਾਂ ਸੁਰੱਖਿਅਤ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ। ਅਸੁਰੱਖਿਅਤ ਸਾਕਟ ਉਹੀ ਰੂਟਿੰਗ ਨਿਯਮ ਮੰਨਦਾ ਹੈ ਜੋ ਤੁਸੀਂ ਹੁਣੇ ਲਗਾਏ, ਇਸ ਲਈ ਉਸ ਦੇ ਪੈਕੇਟ ਟਨਲ ਵਿੱਚ ਵਾਪਸ ਜਾਂਦੇ ਹਨ ਅਤੇ ਤੁਹਾਡਾ ਆਪਣਾ ਪੜ੍ਹਨ ਵਾਲਾ ਲੂਪ ਉਹਨਾਂ ਨੂੰ ਦੁਬਾਰਾ ਚੁੱਕਦਾ ਹੈ। ਫਿਰ ਟਨਲ ਆਪਣਾ ਆਉਟਪੁੱਟ ਬੇਅੰਤ ਫਾਰਵਰਡ ਕਰਦਾ ਹੈ, ਅਤੇ ਬਾਹਰੋਂ ਇਹ ਖੁੱਲ੍ਹਦੇ ਪਰ ਕਦੇ ਜਵਾਬ ਨਾ ਦੇਣ ਵਾਲੇ ਕਨੈਕਸ਼ਨ ਵਰਗਾ ਦਿਸਦਾ ਹੈ।
ਕ੍ਰਮ protect, ਫਿਰ connect ਜਾਂ bind, ਫਿਰ send ਹੈ। connect ਤੋਂ ਬਾਅਦ protect ਕਾਲ ਕਰਨ ਨਾਲ ਪਿਛਲਾ ਰੂਟ ਫੈਸਲਾ ਰਹਿ ਸਕਦਾ ਹੈ, ਇਸ ਲਈ ਕਾਲ true ਵਾਪਸ ਦੇਣ 'ਤੇ ਵੀ ਸਾਕਟ ਗਲਤ ਰਾਹ ਵਰਤਦਾ ਰਹਿੰਦਾ ਹੈ। ਵਾਪਸ ਮਿਲਣ ਵਾਲਾ ਬੂਲੀਅਨ ਜਾਂਚੋ ਅਤੇ false ਹੋਣ 'ਤੇ ਉੱਚੀ ਆਵਾਜ਼ ਵਿੱਚ ਫੇਲ ਹੋਵੋ, ਕੰਮ ਨਾ ਕਰ ਸਕਣ ਵਾਲੇ send ਵਿੱਚ ਵੜਨ ਦੀ ਥਾਂ।
protect() ਕਦੇ ਨਾ ਛੋਹੇ ਸਾਕਟ 'ਤੇ sendto ਤੋਂ ਆਉਣ ਵਾਲੀ ਇਜਾਜ਼ਤ ਗਲਤੀ ਇਸ ਗਲਤੀ ਦੀ ਆਮ ਪਛਾਣ ਹੈ।
UDP ਨਮੂਨਾ HTTPS ਨਹੀਂ ਢੋਂਦਾ
ਜੋ ਫਾਰਵਰਡਿੰਗ ਨਮੂਨਾ ਜ਼ਿਆਦਾਤਰ ਟਿਊਟੋਰਿਅਲ ਕਾਪੀ ਕਰਦੇ ਹਨ ਉਹ ਸਿਰਫ UDP ਸੰਭਾਲਦਾ ਹੈ। TCP ਨੂੰ ਹੈਂਡਸ਼ੇਕ, ਕ੍ਰਮ ਸੰਖਿਆਵਾਂ, ਪੁਸ਼ਟੀਆਂ ਅਤੇ ਦੁਬਾਰਾ ਭੇਜਣ ਦੀ ਲੋੜ ਹੈ, ਅਤੇ tun ਡਿਸਕ੍ਰਿਪਟਰ ਤੇ ਸਾਕਟ ਵਿਚਕਾਰ ਪੇਲੋਡ ਕਾਪੀ ਕਰਨ ਵਾਲਾ ਲੂਪ ਇਹਨਾਂ ਵਿੱਚੋਂ ਕੁਝ ਵੀ ਨਹੀਂ ਦਿੰਦਾ। ਇਸ ਲਈ UDP DNS ਪੁੱਛਗਿੱਛ ਪਾਸ ਹੋ ਸਕਦੀ ਹੈ ਜਦੋਂ ਕਿ ਹਰ HTTPS ਬੇਨਤੀ ਅਟਕ ਜਾਂਦੀ ਹੈ। ਜਾਂ ਤਾਂ ਵਰਤੋਂਕਾਰ ਥਾਂ ਵਿੱਚ TCP ਸਟੈਕ ਚਲਾਓ ਜਾਂ ਡਿਵਾਈਸ 'ਤੇ TCP ਖਤਮ ਕਰਕੇ ਸਟ੍ਰੀਮ ਫਾਰਵਰਡ ਕਰਨ ਵਾਲੀ ਸਥਾਨਕ ਪ੍ਰਾਕਸੀ ਨੂੰ ਕਨੈਕਸ਼ਨ ਦਿਓ।
ਕੁਝ ਵੀ ਦੁਬਾਰਾ ਲਿਖਣ ਤੋਂ ਪਹਿਲਾਂ ਵੰਡ ਦੀ ਜਾਂਚ ਕਰੋ: ਇੱਕ UDP ਪੁੱਛਗਿੱਛ ਭੇਜੋ ਅਤੇ ਉਸੇ ਹੋਸਟ 'ਤੇ ਇੱਕ TCP ਕਨੈਕਸ਼ਨ ਖੋਲ੍ਹੋ। ਜੇ UDP ਰਾਹ ਚੱਲਦਾ ਹੈ ਅਤੇ TCP ਰਾਹ ਪਹਿਲੇ SYN 'ਤੇ ਅਟਕਦਾ ਹੈ, ਤਾਂ ਸਮੱਸਿਆ ਫਾਰਵਰਡਿੰਗ ਕੋਡ ਵਿੱਚ ਹੈ, ਸਰਵਰ ਵਿੱਚ ਨਹੀਂ। ਉਹ ਇੱਕ ਤੁਲਨਾ ਬੇਕਾਰ ਸਰਵਰ ਲੌਗ ਪੜ੍ਹਨ ਵਿੱਚ ਲੱਗਣ ਵਾਲਾ ਬਹੁਤ ਸਮਾਂ ਬਚਾਉਂਦੀ ਹੈ।
ਰੂਟ ਸੂਚੀ ਅਤੇ ਪ੍ਰਤੀ-ਐਪ ਫਿਲਟਰ ਦਿਸਣ ਵਾਲੀ ਚੀਜ਼ ਸੀਮਿਤ ਕਰਦੇ ਹਨ
addAddress, addRoute ਅਤੇ addDns ਤੈਅ ਕਰਦੇ ਹਨ ਕਿ ਸਿਸਟਮ ਟਨਲ ਵਿੱਚ ਕੀ ਭੇਜਦਾ ਹੈ। ਰੂਟ ਸੂਚੀ ਤੋਂ ਬਾਹਰ ਦਾ ਮੰਜ਼ਿਲ ਕਦੇ ਤੁਹਾਡੇ ਡਿਸਕ੍ਰਿਪਟਰ ਤੱਕ ਨਹੀਂ ਪਹੁੰਚਦਾ, ਇਸ ਲਈ ਕਿੰਨੀ ਵੀ ਫਾਰਵਰਡਿੰਗ ਲਾਜਿਕ ਇਸਨੂੰ ਠੀਕ ਨਹੀਂ ਕਰੇਗੀ। ਤੁਸੀਂ ਕਰਦੇ builder ਕਾਲ ਲੌਗ ਕਰੋ ਅਤੇ ਐਪ ਜਿਨ੍ਹਾਂ ਪਤਿਆਂ 'ਤੇ ਸੱਚਮੁੱਚ ਪਹੁੰਚਣਾ ਚਾਹੁੰਦੀ ਹੈ ਉਹਨਾਂ ਨਾਲ ਤੁਲਨਾ ਕਰੋ।
ਪ੍ਰਤੀ-ਐਪ ਚੋਣ ਦੀ ਆਪਣੀ ਹੇਠਲੀ ਸੀਮਾ ਹੈ: addAllowedApplication ਅਤੇ addDisallowedApplication ਨੂੰ API 21 ਚਾਹੀਦਾ ਹੈ, ਅਤੇ ਪੁਰਾਣੇ ਸੰਸਕਰਣਾਂ ਵਿੱਚ ਉਹ ਢੰਗ ਹੀ ਨਹੀਂ। ਪੈਕੇਟ ਅਨੁਸਾਰ ਫਿਲਟਰ ਕਰਨ ਵਾਲਾ ਡਿਜ਼ਾਈਨ ਉੱਥੇ ਚੱਲ ਹੀ ਨਹੀਂ ਸਕਦਾ।
ਦੁਬਾਰਾ ਸਥਾਪਨਾ ਪੁਰਾਣੇ ਡਿਸਕ੍ਰਿਪਟਰ ਛੱਡ ਜਾਂਦੀ ਹੈ
establish() ਦੁਬਾਰਾ ਕਾਲ ਕਰਨ 'ਤੇ ਨਵਾਂ ਡਿਸਕ੍ਰਿਪਟਰ ਆਉਂਦਾ ਹੈ ਅਤੇ ਪਿਛਲਾ ਇੰਟਰਫੇਸ ਬੰਦ ਹੁੰਦਾ ਹੈ। ਪੁਰਾਣਾ ਡਿਸਕ੍ਰਿਪਟਰ ਹੁਣ ਅਵੈਧ ਹੈ, ਇਸ ਲਈ ਉਸ 'ਤੇ ਅਜੇ ਬਲਾਕ ਥ੍ਰੈਡ ਨੂੰ ਗਲਤੀ ਮਿਲਦੀ ਹੈ, ਅਤੇ ਪੁਰਾਣੇ ਰਾਹ ਲਈ ਬਣੇ ਸਾਕਟ ਬਦਲਣੇ ਪੈ ਸਕਦੇ ਹਨ। onRevoke ਉਸ ਟਨਲ ਲਈ ਕਾਲਬੈਕ ਹੈ ਜੋ ਵਰਤੋਂਕਾਰ ਜਾਂ ਸਿਸਟਮ ਨੇ ਲੈ ਲਿਆ। ਜੀਵਨ ਚੱਕਰ ਇੱਕ ਮਾਲਕ ਕੋਲ ਰੱਖਣਾ, ਜੋ ਦੁਬਾਰਾ ਸਥਾਪਨਾ ਤੋਂ ਪਹਿਲਾਂ ਪਾਠਕ ਨੂੰ ਰੋਕਦਾ ਹੈ, ਜੁੜੇ-ਪਰ-ਮੁਰਦਾ ਹਾਲਤਾਂ ਬਚਾਉਂਦਾ ਹੈ।
ਹਰ ਗਲਤੀ ਨੂੰ ਉਸ ਦੇ ਪੜਾਅ ਅਨੁਸਾਰ ਪੜ੍ਹੋ। recvfrom ਤੋਂ ਕਨੈਕਸ਼ਨ ਰੀਸੈਟ ਦਾ ਮਤਲਬ ਹੈ ਕਿ ਦੂਰ ਦਾ ਸਿਰਾ ਬੰਦ ਹੋ ਗਿਆ ਜਦੋਂ ਤੁਹਾਡਾ ਕੋਡ ਅਜੇ ਪੜ੍ਹ ਰਿਹਾ ਸੀ। ਖਰਾਬ ਪਤੇ ਦੀ ਗਲਤੀ ਹੈਡਰ ਪਾਰਸਿੰਗ ਜਾਂ ਆਫਸੈਟ ਬੱਗ ਵੱਲ ਇਸ਼ਾਰਾ ਕਰਦੀ ਹੈ, ਨੈੱਟਵਰਕ ਵੱਲ ਨਹੀਂ।
ਕੰਮ ਦਾ ਕ੍ਰਮ: ਬਲਾਕਿੰਗ ਮੋਡ ਚਾਲੂ, ਪ੍ਰਤੀ ਪੜ੍ਹਤ ਇੱਕ ਪੈਕੇਟ, ਹੈਡਰ ਪਾਰਸ ਹੋਇਆ, ਸਾਕਟ ਸੁਰੱਖਿਅਤ, ਪੇਲੋਡ ਭੇਜਿਆ, ਹਸਤਾਂਤਰਣ 'ਤੇ ਸਾਫ ਬੰਦ, ਅਤੇ ਮੰਜ਼ਿਲ ਢਕਣ ਵਾਲੀ ਰੂਟ ਸੂਚੀ।