Android VPN: VpnService ડિસ્ક્રિપ્ટર વિરુદ્ધ root tun ડિવાઇસ
Android એપ પોતે tun0 બનાવી શકતી નથી: establish() શું પરત આપે છે, Binder ક્યાં થંભે છે અને JNI ક્યાં શરૂ થાય છે, અને root-બનાવેલું ડિવાઇસ ક્યારે જીતે છે.
બે માર્ગો Android એપની સામે IP ઇન્ટરફેસ મૂકી શકે છે, અને બંને એક જ પ્રકારના ફાઇલ ડિસ્ક્રિપ્ટર પર ખતમ થાય છે જેના માલિકો ઘણા અલગ છે. એક VpnService અને તેના બિલ્ડર દ્વારા જાય છે, બીજો root શેલ અને /dev/net/tun દ્વારા. તે ડિસ્ક્રિપ્ટર પરનું દરેક વાંચન બહાર જતું પેકેટ છે અને દરેક લેખન અંદર આવતું છે. માર્ગોને અલગ પાડે છે કે નીતિ કોની પાસે છે, OS અપગ્રેડ કોણ ટકી રહે છે, અને રાઉટિંગ ટેબલમાંથી કેટલું તમે સ્પર્શી શકો છો.
પ્લેટફોર્મનો માર્ગ લો જ્યાં સુધી તમે તે ચોક્કસ વસ્તુનું નામ ન આપી શકો જે તે કરવાનો ઇનકાર કરે છે. તે ઇનકાર સામાન્ય રીતે TAP, તમારા પોતાના એપ સેટની બહાર કેપ્ચર, અથવા રાઉટિંગ નિયમ છે જે ફ્રેમવર્ક કદી ખુલ્લો કરતું નથી.
પ્લેટફોર્મના માર્ગ પર તમે આદેશોને બદલે ઇરાદો જાહેર કરો છો. તમે ઓછામાં ઓછું એક સરનામું, ઇચ્છિત રૂટ, DNS સર્વર અને વૈકલ્પિક એપ યાદી આપો છો, પછી Androidની સિસ્ટમ સેવા પોતાની ઓળખ હેઠળ વિશેષાધિકૃત સેટઅપ કરે છે. તમે ઇન્ટરફેસનું નામ પહેલાથી કદી જાણતા નથી, અને તેને બનાવતું ioctl કદી બહાર કાઢતા નથી, અને એ જ મુદ્દો છે.
IP ઇન્ટરફેસ મેળવવાની બે રીતો
root માર્ગ જૂની રેસિપી છે. તમે /dev/net/tun ખોલો છો, IFF_TUN સાથે TUNSETIFF બોલાવો છો, ip link વડે ઇન્ટરફેસ ઉપર લાવો છો, અને હાથે સરનામાં અને રૂટ ઉમેરો છો. દરેક પગલું તમારે સાચું કરવાનું છે, જે ફ્રેમવર્ક શાંતિથી સંભાળી લેતું તે પણ. એક રૂટ ખૂટે તો વપરાશકર્તાને મૃત સર્વર જેવો જ રિપોર્ટ મળે છે.
ડિબગિંગ સેટઅપ જેટલું જ અલગ છે. root માર્ગ પર ઇન્ટરફેસ કાં તો હાજર છે અથવા તમારા ioctl એ એવી ભૂલ પરત આપી છે જે તમે સીધી વાંચી શકો છો. પ્લેટફોર્મના માર્ગ પર ઇન્ટરફેસ establish() સફળ થયા પછી જ હાજર છે, તેથી નિષ્ફળતા ડિવાઇસ નોડને બદલે એક્સેપ્શન અથવા null ડિસ્ક્રિપ્ટર તરીકે આવે છે જેમાં તમે ખૂંચી શકો.
establish() ખરેખર શું પરત આપે છે
Builder.establish()ના ત્રણ પરિણામ છે અને તેમને ત્રણ અલગ પ્રતિસાદ જોઈએ. ડિસ્ક્રિપ્ટર એટલે ઇન્ટરફેસ ગોઠવાયેલું છે અને વાપરવા માટે તમારું છે, null એટલે વિનંતી પસાર થઈ નથી, અને ફેંકાયેલો એક્સેપ્શન એટલે સિસ્ટમ સેવાએ તેને નકારી છે. null અને સફળતાને એક booleanમાં ભેગા કરવું એ એપ દ્વારા કાર્યક્ષમ ટનલ જાહેર કરવાની સૌથી સામાન્ય રીત છે જે કદી પેકેટ વહન કરતું નથી. Builder સંદર્ભ સરનામાની આવશ્યકતા જણાવે છે, અને સર્વરને દોષ આપતા પહેલા તે વાંચવા જેવું છે.
દિશાઓ ડિસ્ક્રિપ્ટર નક્કી કરે છે, તમારો પ્રોટોકોલ નહીં. વાંચન તમને બહાર જતાં પેકેટ આપે છે જે પહેલેથી VPN માટે પસંદ થયેલા છે, અને લેખન અંદર આવતાં પેકેટ પાછા ઇન્ટરફેસમાં દાખલ કરે છે. તે પેકેટને એન્ક્રિપ્ટ, પ્રમાણિત અને ફ્રેમ કરવાનું તમારા પોતાના ટ્રાન્સપોર્ટનું કામ છે, કારણ કે પ્લેટફોર્મ પેકેટની સીમા પર અટકે છે.
Binder એક ડગલું છે, JNI બીજો અક્ષ
બિલ્ડર વિનંતી Binder દ્વારા સિસ્ટમમાં પ્રવેશે છે, અને તેની નીચે ક્યાંક પ્લેટફોર્મ ડિવાઇસ ગોઠવવા માટે નેટિવ કોડ બોલાવે છે. આ એક જ કૉલમાં થરાયેલી બે અલગ મિકેનિઝમ છે. Binder તમારી એપ અને સિસ્ટમ સેવા વચ્ચેનો આંતરપ્રક્રિયા સંચાર છે, જ્યારે JNI પ્રક્રિયાની અંદર Java થી નેટિવ સુધીનો પુલ છે. Android 9 AOSP વૃક્ષ વાંચવાથી સ્ટેક શાબ્દિક દેખાય છે, અને યાદ રાખવા જેવું છે કે આંતરિક વર્ગના નામ અને ફાઇલ પાથ આવૃત્તિઓ વચ્ચે બદલાય છે.
જે બદલાતું નથી તે કરાર છે જેના પર તમે ભરોસો કરી શકો: બિલ્ડર, તે પરત આપતું ડિસ્ક્રિપ્ટર, અને તેની આસપાસની સેવા જીવનચક્ર. કોઈ એપે ઇન્ટરફેસ મેળવવા આંતરિક સેવા ટ્રાન્ઝેક્શન બોલાવવું કે ડિવાઇસ નોડ ફરી બનાવવો ન જોઈએ. જો તમારો કોડ AOSP વર્ગના નામ પર આધારિત હોય, તો તમે પરીક્ષણ ન કર્યું હોય તેવી આવૃત્તિ પર તે તૂટશે.
TUN IP વહન કરે છે, TAP Ethernet
TUN એ IP ઇન્ટરફેસ છે. TAP એ Ethernet ઇન્ટરફેસ છે, અને તે ભેદ જ નક્કી કરે છે કે બ્રિજિંગ શક્ય છે કે નહીં. TUN ડિવાઇસમાં MAC સરનામું નથી અને ફોરવર્ડ કરવા Ethernet હેડર નથી, તેથી TUN ક્લાયંટ રૂટ કેવા પણ લખાયા હોય, layer-2 બ્રિજમાં જોડાઈ શકતું નથી.
VpnService તમને IP પ્રકાર આપે છે, જે એપ-સ્તરીય VPNને જોઈએ છે અને કાચા Ethernet સ્ટેક વિના ટેકો આપી શકે છે. જો તમારી ડિઝાઇનને બ્રિજિંગ જોઈએ, તો પ્લેટફોર્મનો માર્ગ તમને ત્યાં ન લઈ જાય, અને root માર્ગ ફક્ત ત્યારે જ લઈ જાય જ્યારે કર્નલ અને ડિવાઇસ પરવાનગીઓ સહકાર આપે.
root માર્ગ હજી ક્યાં જીતે છે
ત્રણ કામ લોકોને પ્લેટફોર્મના માર્ગથી દૂર ધકેલે છે. layer-2 બ્રિજિંગને TAP જોઈએ. તમારા પોતાના VPN વ્યાપની બહારની એપમાંથી ટ્રાફિક કેપ્ચર કરવા એવી દૃશ્યતા જોઈએ જે ફ્રેમવર્ક આપતું નથી. બિલ્ડર કદી ખુલ્લું ન કરતું નીતિ રાઉટિંગ, જેમ કે એક ગંતવ્ય માટે અલગ ટેબલ, તમે જ ઇન્સ્ટોલ કરો તેવા નિયમો માગે છે.
ખર્ચ પછી આવે છે: અનલોક કરેલો bootloader અથવા root કરેલી ઇમેજ, તમારા પગ નીચે સરકતી SELinux નીતિ, અને OTA પછી યોગ્ય વર્તન બંધ કરતું ડિવાઇસ. root કરેલી રેસિપી સામાન્ય એપ વિતરણ દ્વારા મોકલી પણ ન શકાય, તેથી મોટા ભાગની ટીમો તેને ઉત્પાદનને બદલે આંતરિક નિદાન માર્ગ તરીકે રાખે છે.
બંને વચ્ચે પસંદગી
તમારી પાસેના કોડથી નહીં, તમને જરૂરી ઇન્ટરફેસથી શરૂ કરો. જવાબ એપ-મર્યાદિત રૂટ સાથેનું TUN ડિવાઇસ હોય, તો પ્લેટફોર્મનો માર્ગ ટૂંકો છે અને અપગ્રેડ ટકી રહે છે. જવાબમાં Ethernet ફ્રેમ, બીજી એપનું કેપ્ચર, અથવા બિલ્ડર નકારે તેવા રાઉટિંગ નિયમોનો સમાવેશ હોય, તો તમે root પ્રદેશમાં છો અને તેને ઓપરેટિંગ ખર્ચ તરીકે બજેટ કરવું જોઈએ.
મોટાભાગની દલીલો ઉકેલતી એક ચકાસણી: પહેલા પ્લેટફોર્મનો માર્ગ બનાવો, establish()નું પરિણામ દૂરસ્થ સત્રની સ્થિતિથી અલગ નોંધો, અને દરેક દિશામાં એક પેકેટની પુષ્ટિ કરો. ત્યાર પછી જ નક્કી કરો કે ખૂટતી ક્ષમતા સમર્થિત માર્ગ છોડવાનું વાજબી ઠેરવે છે કે નહીં.