Android VpnService વિશેની ચાર ધારણાઓએ મને એક વખત અઠવાડિયાનો મોટો ભાગ ખર્ચાવ્યો, અને તેમાંથી એક પણ નેટવર્ક પ્રોટોકોલ વિશે ન હતી. એપ કહેતી હતી જોડાયેલું છે, ચાવીનું ચિહ્ન સ્ટેટસ બારમાં બેઠું હતું, અને ટ્રાફિક તો પણ સામાન્ય રૂટ દ્વારા જ બહાર જતો હતો. હું ધારતો રહ્યો કે ટનલ મારી છે જ્યાં સુધી હું તેને બંધ ન કરું, કે મેં ઉમેરેલા રૂટ એ જ રૂટ છે જે મને મળે છે, અને કે stopSelf બોલાવવાથી ઇન્ટરફેસ પણ સાથે નીચે જશે. સેવા બરાબર દસ્તાવેજીકૃત થયા મુજબ જ વર્તતી હતી. તૂટેલો ભાગ મારું માનસિક મોડેલ હતું.

મિથ 1: ટનલ ત્યાં સુધી ઊભી રહે છે જ્યાં સુધી તમે તેને બંધ ન કરો

Android એક સમયે એક VPN ઇન્ટરફેસ રાખે છે. બીજું સ્થાપિત કરો અને પ્લેટફોર્મ તેને કતારમાં મૂકતું નથી, તે તમારું નિષ્ક્રિય કરે છે અને તમારી સેવા પર onRevoke() બોલાવે છે. જો તમારો કોડ ફક્ત બટન દબાવવા પર બધું તોડે છે, તો એક કબજો પાછળ એક ડેસ્ક્રિપ્ટર અને એક રીડર થ્રેડ છોડી જાય છે, અને આગલી શરૂઆત બંનેનો વારસો મેળવે છે.

VpnService સંદર્ભ સ્પષ્ટ કહે છે કે prepare() null પરત કરે છે જ્યારે એપ પાસે પહેલેથી સંમતિ હોય, અને Intent જ્યારે વપરાશકર્તાએ હજી મંજૂરી આપવાની હોય. તે સંમતિ ફક્ત ત્યારે જ પહોંચે જ્યારે તમે ઇરાદો startActivityForResult() દ્વારા પહોંચાડો. આ હસ્તાંતરણ છોડી દો અને establish() null પરત કરે છે, જે મંજૂરીની સમસ્યા નહીં પણ શાંત નિષ્ફળતા તરીકે વંચાય છે.

Always-on VPN એક એવો માલિક ઉમેરે છે જેને તમે નિયંત્રિત કરતા નથી. સિસ્ટમ બૂટ પછી કે ક્રેશ પછી ટનલ પાછી લાવી શકે છે, અને તે વપરાશકર્તાએ જાતે શરૂ કરેલી VPN એપને પાછળ કરી દે છે. onRevoke() એવી રીતે બનાવો કે તે તમારા સામાન્ય બંધ જેટલા જ સંસાધનો બંધ કરે, અને તેને કોર્નર કેસ નહીં પણ મુખ્ય સ્ટોપ માર્ગ તરીકે ગણો. વપરાશકર્તાઓ VPN એપ બદલે છે; તમારા કોડને તે ટકીવું પડશે.

મિથ 2: addRoute બરાબર તે જ પકડે છે જે તમે સૂચિબદ્ધ કર્યું છે

રૂટ નક્કી કરે છે કે કયા પેકેટ તમારા ડેસ્ક્રિપ્ટર સુધી પહોંચે છે, અને વ્યાપની ભૂલ તે ગુસ્સે કરતી સ્થિતિ ઉત્પન્ન કરે છે જ્યાં થોડો ટ્રાફિક ટનલમાંથી જાય છે અને થોડો નહીં. addRoute("0.0.0.0", 0) બધું IPv4 લે છે, એટલે હવે દરેક પેકેટ તમારી પાસે આવે છે અને તેને ફોરવર્ડ કરવું કે ડ્રોપ કરવું પડે છે. એક જ હોસ્ટ માટે /32 લગભગ કંઈ જ લેતું નથી, અને બાકીનું બધું એવું વર્તે છે જાણે તમારું VPN ક્યારેય ઇન્સ્ટોલ જ થયું ન હોય.

કુટુંબો અલગ જ ગણાય છે. ફક્ત IPv4 રૂટ IPv6 ને અંતર્ગત નેટવર્ક પર છોડી દે છે, તેથી દ્વિ-સ્ટેક હોસ્ટ ટનલની અંદર સંપૂર્ણ જોડાયેલું દેખાતું હોવા છતાં બહાર નામ ઉકેલી અને જોડાઈ શકે છે.

DNS એ જ તર્ક અનુસરે છે. addDnsServer() સાથે ઉમેરાયેલા સર્વર તે એપ પાસે જાય છે જે ટનલ રિઝોલ્વર વાપરે છે, જ્યારે પોતાનું એન્ક્રિપ્ટેડ DNS એન્ડપોઇન્ટ ધરાવતી કે હોસ્ટનામ પર સેટ કરેલું Private DNS ધરાવતી એપ તેમને સંપૂર્ણ અવગણે છે. જ્યારે નામ એક એપ માટે નિષ્ફળ જાય અને બીજા માટે કામ કરે, ત્યારે એક પણ રૂટને અડકતા પહેલાં રિઝોલ્વર માર્ગ તપાસો.

મિથ 3: એપ પ્રમાણેના નિયમો એ સ્વિચ છે જેને તમે બંને બાજુ ફેરવી શકો

addDisallowedApplication() અને addAllowedApplication() બે મોડ છે, બે ફિલ્ટર નહીં. બિલ્ડર પ્રતિ ટનલ એક મોડેલ સ્વીકારે છે, તેથી જે એપ ત્રણ પેકેજ સિવાય બધું ઇચ્છે છે તે પ્રતિબંધિત યાદી વાપરે છે અને મંજૂર યાદી ખાલી રાખે છે. બંને પરસ્પર વિશિષ્ટ છે, અને લોકોને તે રનટાઇમમાં ખબર પડે છે જ્યારે સેટિંગ્સ સ્ક્રીન પહેલેથી બંને ટોગલ ઑફર કરી ચૂકી હોય છે.

પેકેજ દૃશ્યતા પણ કરડે છે. Android 11 અને તેના પછી તમે ફક્ત એ જ પેકેજના નામ આપી શકો જે તમે જોઈ શકો, તેથી જે ક્વેરી તમારી એપને ચલાવવાની મંજૂરી નથી તેમાંથી બનેલી બાકાત યાદી શાંતિથી એન્ટ્રી ચૂકી જશે. યાદી પર ભરોસો રાખતા પહેલાં તેને પેકેજ મેનેજર ખરેખર શું પરત કરે છે તેની સાથે સરખાવો.

વર્ક પ્રોફાઇલ શ્રોતાઓને ફરી વિભાજિત કરે છે. પ્રોફાઇલની અંદર શરૂ થયેલી ટનલ તે પ્રોફાઇલ અને તેની એપને આવરે છે, જ્યારે અંગત બાજુ પોતાનું જોડાણ રાખે છે. તે એક વાર લેવાયેલો વ્યાપનો નિર્ણય છે, અને તેનું સ્થાન સપોર્ટ ટિકિટમાં નહીં, ઇન્ટરફેસમાં છે.

મિથ 4: stopSelf ટનલ સમાપ્ત કરે છે

ના, કરતું નથી. ઇન્ટરફેસ તે ડેસ્ક્રિપ્ટરમાં જીવે છે જે establish() પરત કરે છે, અને તે ડેસ્ક્રિપ્ટર ખુલ્લું રહે ત્યારે સેવા ઑબ્જેક્ટ મરી શકે છે. પહેલાં ParcelFileDescriptor બંધ કરો, સંદર્ભ છોડી દો, રીડર અને રાઇટર થ્રેડ જોડો કે અટકાવો, પછી stopForeground(true) અને stopSelf() તે ક્રમમાં બોલાવો.

ભૂલાયેલું ડેસ્ક્રિપ્ટર એ સામાન્ય કારણ છે કે સેવા પોતાની બંધ કરવાની વિનંતી પછી પણ ટકી હોય એવું લાગે, અને તે એક જૂનું રૂટ સમજાવે છે જે તેને ઉમેરનારી એપ કરતાં વધુ જીવે છે.

ઊલટી ભૂલ પણ એટલી જ સામાન્ય છે: રીડર થ્રેડ વાંચનની વચ્ચે હોય ત્યારે ડેસ્ક્રિપ્ટર બંધ કરવું, અને પછી તે થ્રેડને એવી અપવાદ સંભાળવા દેવું જેના માટે કોઈએ કોડ લખ્યો નથી. શટડાઉન ક્રમ એક જ જગ્યાએ રાખો અને વપરાશકર્તાની ક્રિયા તથા onRevoke() બંને તેમાં બોલાવે.

ટનલ મૃત લાગે ત્યારે શું તપાસવું

ટનલ ઉપર આવે તે પહેલાં લાંબા જીવનના સોકેટ protect() થી સુરક્ષિત કરો. તેના વિના ટનલનું પોતાનું પરિવહન ફરી ટનલમાં રૂટ થઈ જાય છે અને જોડાણ એવી રીતે અટકી જાય છે જે બરાબર સર્વર ખામી જેવું લાગે છે. એવા સરનામા સામે પરીક્ષણ કરો જે ફક્ત દૂરસ્થ નેટવર્ક પાછળ જ હોય, કેશમાંથી કે અંતર્ગત માર્ગમાંથી જવાબ આપતી જાહેર સાઇટ સામે નહીં.

establish() નું પરિણામ, રૂટ, બાકાત કરેલા પેકેજ અને બંધ કરવાનું કારણ લોગ કરો. તે ચાર લીટીઓ પેકેટ કેપ્ચર વિના સંમતિની સમસ્યાને વ્યાપની સમસ્યા અને જીવનચક્રની સમસ્યાથી અલગ કરે છે.

સંબંધિત લેખો