VpnService ആപ്പിലെ സ്പ്ലിറ്റ് ടണലിംഗ് കുറച്ച് നിർദ്ദിഷ്ട സ്ഥലങ്ങളിൽ തകരുന്നു, ഓരോന്നിനും പരിഹാരം വ്യത്യസ്തമാണ്. ക്ലയന്റ് പരാജയപ്പെട്ട ഒരു ലക്ഷ്യസ്ഥാനം മാത്രമേ കാണിക്കുന്നുള്ളൂ, അതിനാൽ ആദ്യ ജോലി നിങ്ങൾ ഏത് അതിർത്തിയിൽ തട്ടുന്നു എന്ന് കണ്ടെത്തുകയാണ്: builder നേടിയ റൂട്ടുകൾ, നിങ്ങൾക്ക് ഓതന്റിക്കേറ്റ് ചെയ്യാൻ കഴിയാത്ത പ്രോക്സി, നിങ്ങൾ പ്രഖ്യാപിച്ചത്രയും മാത്രമുള്ള resolver, അല്ലെങ്കിൽ പ്ലാറ്റ്ഫോം ഓരോ ഉപയോക്താവിനും പ്രയോഗിക്കുന്ന ആപ്പ് ലിസ്റ്റ്. അതുകൊണ്ടാണ് ഞാൻ നാല് ഘട്ട പരിശോധന സൂക്ഷിക്കുന്നത്. അത് താഴെയുള്ള ക്രമത്തിൽ നടക്കുന്നു, ആദ്യ പരാജയത്തിൽ നിലയ്ക്കുന്നു.

builder പ്ലാറ്റ്ഫോമിന് എന്ത് നൽകി എന്ന് ഉറപ്പാക്കുക

VpnService.Builder എന്നത് പ്രഖ്യാപനങ്ങളുടെ ഒരു പട്ടികയാണ്. establish() വിർച്വൽ ഇന്റർഫേസിനായി ParcelFileDescriptor തിരികെ നൽകുന്നു, addAddress, addRoute എന്നിവയുടെ പ്രിഫിക്സുകളുമായി പൊരുത്തപ്പെടുന്ന ട്രാഫിക് മാത്രമേ പ്ലാറ്റ്ഫോം ആ ഡിസ്ക്രിപ്റ്ററിലേക്ക് അയയ്ക്കുന്നുള്ളൂ; addDnsServer ഏത് resolver-നോട് ചോദിക്കണം എന്ന് ക്ലയന്റുകളോട് പറയുന്നു. നിങ്ങൾ ചേർത്ത എല്ലാ പ്രിഫിക്സുകൾക്കും പുറത്തുള്ള ലക്ഷ്യസ്ഥാനം ഇന്റർഫേസ് എന്ത് വാഗ്ദാനം ചെയ്താലും നിങ്ങളുടെ ആപ്പിൽ എത്തുന്നില്ല. ഈ ഒരു വസ്തുത കോഡ് മാറ്റുന്നതിന് മുമ്പുള്ള തകർന്ന സ്പ്ലിറ്റ് ടണലിംഗ് പരാതികളിൽ ഭൂരിഭാഗവും വിശദീകരിക്കുന്നു.

builder ഒരുക്കിയ വിലാസ, റൂട്ട്, DNS പട്ടികകൾ ലോഗ് ചെയ്യുക, പിന്നീട് അവ പരാജയപ്പെടുന്ന ലക്ഷ്യസ്ഥാനങ്ങളുമായി താരതമ്യം ചെയ്യുക. മാനേജ്മെന്റ് ഹോസ്റ്റിനായി വിട്ടുപോയ ഒരു /32 തകർന്ന ടണലിനെക്കാൾ വളരെ സാധാരണമാണ്. പട്ടിക ശരിയാണെങ്കിൽ മുന്നോട്ട് പോകുക; തെറ്റാണെങ്കിൽ ബാക്കി ചെക്ക്ലിസ്റ്റ് പാഴ്ശ്രമമാണ്.

excludeRoute API 33 മുതൽ മാത്രം

ലക്ഷ്യസ്ഥാനാധിഷ്ഠിത ഒഴിവാക്കൽ ഏറ്റവും കൂടുതൽ സപ്പോർട്ട് ത്രെഡാകുന്ന അഭ്യർത്ഥനയാണ്. builder.excludeRoute(IpPrefix) API 33-ൽ വന്നു; അതിന് മുമ്പ് പിന്തുണയുള്ള ഏക ഏകദേശം ഒഴിവാക്കപ്പെട്ട പ്രിഫിക്സ് ഒഴികെ എല്ലാത്തിനും റൂട്ടുകൾ ചേർക്കുകയാണ്, അതായത് പൂരക പ്രിഫിക്സുകൾ നിങ്ങൾ തന്നെ കണക്കാക്കണം. രണ്ട് വിളികളും കണ്ണാടി പ്രതിബിംബങ്ങളല്ല: ഒന്ന് ഇന്റർഫേസിന്റെ റൂട്ട് സെറ്റിൽ നിന്ന് കുറയ്ക്കുന്നു, മറ്റൊന്ന് സെറ്റ് പൂജ്യത്തിൽ നിന്ന് നിർമ്മിക്കുന്നു, പഴയ ഉപകരണം തിരിച്ചറിയാത്ത വിളി എറിയുകയോ നിശ്ശബ്ദമായി അവഗണിക്കുകയോ ചെയ്യും. Build.VERSION.SDK_INT അനുസരിച്ച് ശാഖ ചെയ്ത് രണ്ട് വഴികളും യഥാർത്ഥ ഹാർഡ്‌വെയറിൽ പരിശോധിക്കുക.

പൂരകങ്ങൾ കണക്കാക്കുമ്പോൾ പ്രിഫിക്സ് വിന്യാസം ശ്രദ്ധിക്കുക. /16 റൂട്ടിനുള്ളിൽ /24 ഒഴിവാക്കലിന് ബാക്കി ഭാഗത്തെ യഥാർത്ഥത്തിൽ വിവരിക്കുന്ന ആവരണ പ്രിഫിക്സുകൾ വേണം, വികൃതമായ ഒരു /8 അല്ല. അന്തിമ പട്ടിക ലോഗ് ചെയ്ത് ഒഴിവാക്കിയ ഹോസ്റ്റ് ഇപ്പോഴും ടണലിന് പുറത്തുള്ള വഴിയിലൂടെ പരിഹരിക്കപ്പെടുന്നുവെന്ന് ഉറപ്പാക്കുക.

പ്രോക്സി ക്രെഡൻഷ്യലുകൾ പ്രകടിപ്പിക്കാൻ കഴിയില്ല

setHttpProxy(ProxyInfo) ഇന്റർഫേസിനെ HTTP അല്ലെങ്കിൽ SOCKS പ്രോക്സിയിലേക്ക് തിരിക്കുന്നു, PAC URL ഓരോ ലക്ഷ്യസ്ഥാനത്തിനും അവയ്ക്കിടയിൽ തിരഞ്ഞെടുക്കാം. ProxyInfo-ക്കോ PAC ഫോർമാറ്റിനോ ഉപയോക്തൃനാമവും പാസ്‌വേഡും ഇല്ല, അതിനാൽ ഓതന്റിക്കേഷൻ ആവശ്യപ്പെടുന്ന പ്രോക്സി പ്ലാറ്റ്ഫോം API-ക്ക് പുറത്താണ്. അത് ആവശ്യമുള്ള ആപ്പുകൾ സാധാരണയായി ഒരു userspace സ്റ്റാക്ക്, tun2socks അല്ലെങ്കിൽ സമാനമായ എൻജിൻ ഉൾപ്പെടുത്തി 407 വെല്ലുവിളിക്ക് സ്വയം മറുപടി നൽകുന്നു.

ആ തിരഞ്ഞെടുപ്പിന് അനന്തരഫലങ്ങളുണ്ട്. userspace സ്റ്റാക്ക് നിങ്ങൾ അതിലേക്ക് റൂട്ട് ചെയ്യുന്ന ട്രാഫിക് മാത്രം കാണുന്നു, അതിനാൽ അത് അതേ ഡിസ്ക്രിപ്റ്റർ അതിർത്തിക്കുള്ളിൽ ജീവിക്കണം, സ്വന്തം uplink സോക്കറ്റിന് അതേ protect() ആവശ്യകതയും കൈവരിക്കുന്നു. protect() ഒഴിവാക്കിയാൽ ടണൽ സ്വന്തം ട്രാൻസ്‌പോർട്ട് പിടിച്ചെടുക്കും, അത് ആദ്യ പാക്കറ്റിന് ശേഷം നിലയ്ക്കുന്ന ഹാൻഡ്‌ഷേക്കായി കാണപ്പെടും. ക്രെഡൻഷ്യലുകൾ ആവശ്യപ്പെടുന്ന പ്രോക്സിക്കെതിരെ പരിശോധിക്കുക, കാരണം തുറന്ന പ്രോക്സി പ്ലാറ്റ്ഫോം വഴിയിലൂടെ കടന്നുപോകുന്നു, ഒന്നും തെളിയിക്കുന്നുമില്ല.

ആപ്പ് ലിസ്റ്റുകളും DNS-ഉം പ്രഖ്യാപനങ്ങളാണ്

Builder-ൽ addAllowedApplication-ഉം addDisallowedApplication-ഉം ഉണ്ട്, അവ പരസ്പരവിരുദ്ധമാണ്: രണ്ടും വിളിച്ചാൽ ഒരു എക്സെപ്ഷൻ ഉയരും. ഏതായാലും ഇന്റർഫേസ് ക്രമീകരണത്തിൽ പട്ടിക ഓരോ ഉപയോക്താവിനും പ്രയോഗിക്കുന്നു, അതിനാൽ വർക്ക് പ്രൊഫൈൽ ആപ്പ് നിങ്ങളുടെ ടണലിന് പകരം വർക്ക് പ്രൊഫൈൽ ടണലിന് കീഴിലാണ്. ഏതൊരു API-യും നൽകാത്തത് മറ്റൊരു ആപ്പിന്റെ തീരുമാനത്തിന്റെ നിയന്ത്രണമാണ്: പുറത്തുനിന്ന് പാക്കറ്റ് നിങ്ങളുടെ ടണലിലേക്ക് തള്ളാൻ കഴിയില്ല, ഇതിനകം സജീവമായ VPN അടയ്ക്കാനോ വീണ്ടും ക്രമീകരിക്കാനോ കഴിയില്ല.

DNS അതേ മാതൃക പിന്തുടരുന്നു. addDnsServer ഒരു resolver വിലാസം പ്രഖ്യാപിക്കുന്നു; അത് നിങ്ങളുടെ ആപ്പിന് ചോദ്യങ്ങൾക്ക് ഉത്തരം നൽകാൻ അനുവദിക്കുന്നില്ല. നിങ്ങൾ തന്നെ പേരുകൾ പരിഹരിക്കാൻ ആഗ്രഹിക്കുന്നുവെങ്കിൽ ഒരു resolver പ്രവർത്തിപ്പിച്ച് അതിന്റെ വിലാസം ടണലിലേക്ക് റൂട്ട് ചെയ്യുക. സ്ഥിരമായ ഹോസ്റ്റ്നാമത്തിലേക്ക് DoT അല്ലെങ്കിൽ DoH ഉപയോഗിക്കുന്ന ആപ്പുകൾക്ക് നിങ്ങൾ പ്രഖ്യാപിച്ച വിലാസം മറികടക്കാം, അതിനാൽ ചോദ്യത്തിന്റെ വഴിയും തടയുന്നില്ലെങ്കിൽ പേര് പരിഹരിക്കലിനെ മികച്ച ശ്രമമായി കാണുക.

Manifest, always-on, നാല് ഘട്ട പരീക്ഷണം

യോഗ്യത manifest-ൽ പ്രഖ്യാപിക്കുന്നു: BIND_VPN_SERVICE, android.net.VpnService intent ഫിൽട്ടർ, ടണൽ പശ്ചാത്തലത്തിൽ നിലനിൽക്കണമെങ്കിൽ foreground സേവനം. Always-on VPN അധികമായി വ്യക്തമായ onRevoke ആവശ്യപ്പെടുന്നു, കാരണം ഉപയോക്താവ് ക്രമീകരണങ്ങൾ മാറ്റുമ്പോഴോ മറ്റൊരു ആപ്പ് നിയന്ത്രണമേൽക്കുമ്പോഴോ സിസ്റ്റം അത് വിളിക്കുന്നു.

പരിശോധനകൾ ക്രമത്തിൽ നടത്തി ആദ്യ പരാജയത്തിൽ നിർത്തുക. ആദ്യം, builder-ന് നൽകിയ വിലാസ, റൂട്ട്, DNS പട്ടികകൾ പുറത്തെടുക്കുക. രണ്ടാമതായി, establish() ഒരു ഡിസ്ക്രിപ്റ്റർ തിരികെ നൽകിയെന്നും ട്രാൻസ്‌പോർട്ട് സോക്കറ്റ് സംരക്ഷിതമാണെന്നും ഉറപ്പാക്കുക. മൂന്നാമതായി, ഉൾപ്പെടുത്തിയ പ്രിഫിക്സിനുള്ളിൽ ഒരു ലക്ഷ്യവും ഒഴിവാക്കിയ പ്രിഫിക്സിനുള്ളിൽ ഒരു ലക്ഷ്യവും അഭ്യർത്ഥിക്കുക. നാലാമതായി, നിങ്ങളുടെ resolver മാത്രം പരിഹരിക്കാൻ കഴിയുന്ന ഹോസ്റ്റ്നാമം ചോദിച്ച് ഏത് resolver യഥാർത്ഥത്തിൽ ഉത്തരം നൽകി എന്ന് പരിശോധിക്കുക.

പൂർത്തിയായ ഹാൻഡ്‌ഷേക്ക് തുടർന്നുള്ള ഘട്ടങ്ങളിൽ ഒന്നും തെളിയിക്കുന്നില്ല. ഓരോ പരിശോധനയും ഒരു പാളി വേർതിരിക്കുന്നു, അതിനാൽ രണ്ടാം ഘട്ടത്തിലെ വിജയം നാലാമത്തേതിനെക്കുറിച്ച് ഒന്നും പറയുന്നില്ല.

VpnService.Builder റഫറൻസ് builder-ന്റെ മുഴുവൻ ഉപരിതലവും പട്ടികപ്പെടുത്തുന്നു. അതിനപ്പുറം വേണ്ടതെല്ലാം മറ്റൊരു API, മറ്റൊരു ആപ്പ് അല്ലെങ്കിൽ നിങ്ങളുടെ സ്വന്തം userspace സ്റ്റാക്ക് ആണ്, അത് സ്പ്ലിറ്റ്-ടണൽ ബഗ്ഗല്ല, ഒരു ഡിസൈൻ തീരുമാനമാണ്.

അനുബന്ധ ലേഖനങ്ങൾ