addDnsServer Bad Address: Android ખરેખર શું ચકાસે છે
addDnsServer તરફથી આવતી Bad address ભૂલ સ્થાનિક ફોર્મેટ ચકાસણી છે, DNS નિષ્ફળતા નહીં. લિટરલનું વિશ્લેષણ કરો, loopback અને wildcard દૂર કરો, પછી પહોંચ ચકાસો.
મૂલ્ય VpnService.Builder.addDnsServer સુધી સ્ટ્રિંગ તરીકે પહોંચ્યું અને builder એ કંઈપણ સ્થાપિત થાય તે પહેલાં ત્યાં જ તેને નકારી કાઢ્યું. આ નકાર સ્થાનિક છે: કોઈ resolver સાથે સંપર્ક થયો નથી, કોઈ tunnel નથી અને જે નિષ્ફળ ગયું તે ફોર્મેટ ચકાસણી છે, DNS નિષ્ફળતા નહીં.
આ મહત્વનું છે કારણ કે સામાન્ય VPN એપમાં ત્રણ સમાન DNS ઇનપુટ હોય છે: પ્રોફાઇલમાં લખાયેલું કે આયાત કરેલું મૂલ્ય, રૂપરેખાંકન દરમિયાન સર્વર મોકલે તે મૂલ્ય, અને સિસ્ટમ સ્તરે Private DNS. પ્રથમ બે જ આ કૉલ સુધી પહોંચી શકે.
તૈયારીનું ઑબ્જેક્ટ દલીલને તરત ચકાસે છે
VpnService.Builder tunnel નથી. તે સરનામાં, રૂટ અને સર્વર એકઠા કરતું તૈયારીનું ઑબ્જેક્ટ છે, અને ફક્ત establish() જ તે સૂચિને જીવંત ParcelFileDescriptor અને ઇન્ટરફેસમાં ફેરવે છે. DNS એન્ટ્રી addDnsServer કૉલ કરતી વખતે ચકાસાય છે, સ્થાપિત કરતી વખતે નહીં.
બે પરિણામ આવે છે. સ્ટેક ટ્રેસ ટૂંકું અને જાણી જોઈને નકામું છે: મૂલ્ય સાદા સ્ટ્રિંગ તરીકે આવ્યું. અને આખા બિલ્ડની આસપાસનું બેદરકાર catch સરનામાં અને રૂટ ધરાવતું પણ resolver વગરનું tunnel છોડી દે છે.
builder તમે આપો તે કોઈપણ સૂચિ રાખે છે. ચકાસણી પાસ કરતું સર્વર ઉમેરવું ફક્ત એ સાબિત કરે છે કે સ્ટ્રિંગ બિલ્ડ સમયે સરનામા લિટરલ તરીકે વિશ્લેષિત થયું.
દલીલ શું હોઈ શકે
પેરામીટર સરનામું છે, endpoint નહીં. Builder સંદર્ભ IPv4 કે IPv6 લિટરલ લે છે, અને વિશ્લેષણ ફક્ત સંખ્યાત્મક છે: android.net.InetAddresses.parseNumericAddress API 29 થી તે પાર્સરનું જાહેર ચહેરું છે. હોસ્ટનામ અહીં ધીમું સરનામું નથી પણ વિશ્લેષણ ન કરી શકાય તેવું સ્ટ્રિંગ છે.
વ્યવહારુ મેપિંગ આવું દેખાય છે:
| Input | Result | Reason |
|---|---|---|
10.8.0.1 | accepted | IPv4 literal |
2606:4700:4700::1111 | accepted | IPv6 literal |
dns.example.com | rejected | hostname; numeric parsing does not resolve it |
10.8.0.1:53 | rejected | port belongs to your own config model |
https://dns.example.com/dns-query | rejected | DoH URL, a different configuration path |
127.0.0.1 | rejected | loopback is not a remote resolver |
0.0.0.0 or :: | accepted by the builder | parses fine, but names no destination; only your own validator rejects it |
આવૃત્તિ તમે કેવી રીતે ચકાસો તેના પર અસર કરે છે, builder શું સ્વીકારે તેના પર નહીં. InetAddresses API 29 થી ઉપલબ્ધ છે, તેથી Android 10 અને પછીના વર્ઝનમાં વિશ્લેષણ એક કૉલ છે. addDnsServer(InetAddress) મૂળ સ્વરૂપ છે, String નવું ઉમેરણ. API 29 નીચે InetAddress.getByName અવરોધક નેટવર્ક શોધ સાથે હોસ્ટનામ ઉકેલશે અને ટાઇપિંગ ભૂલને ધીમા પ્રારંભમાં ફેરવશે.
loopback અહીં નકારાય છે, wildcard નહીં
ડેસ્કટોપ VPN ક્લાયન્ટ તેમના stub resolver ને 127.0.0.1:53 પર મોકલે છે. તેને Android પ્રોફાઇલમાં નકલ કરવાથી સ્થાનિક મશીન વર્ણવતું મૂલ્ય આયાત થાય છે, અને અહીં સ્થાનિક મશીન નથી. builder ફક્ત આ કિસ્સો નકારે છે: null કે loopback સરનામું IllegalArgumentException ફેંકે છે.
wildcard વિરુદ્ધ કિસ્સો છે અને અહીં જ મોટા ભાગના વાંચન ખોટા પડે છે. 0.0.0.0 અને :: loopback નથી, તેથી builder તેમને સ્વીકારે છે; બિલ્ડ સમયે કંઈ ફેંકાતું નથી. પછી ઇન્ટરફેસ કોઈ ગંતવ્ય ન દર્શાવતી એન્ટ્રી સાથે ઉપર આવે છે. તેને પકડવું તમારા વેલિડેટરનું કામ છે: isAnyLocalAddress ને અમાન્ય ઇનપુટ ગણો.
રૂપરેખાંકનની સીમા પર એક વાર વિશ્લેષણ કરો
સસ્તો ઉપાય એ છે કે સ્ટ્રિંગ તમારા મોડેલમાં પ્રવેશે ત્યાં ચકાસો:
import android.net.InetAddresses
import java.net.InetAddress
private fun dnsLiteralOrNull(raw: String?): InetAddress? {
val text = raw?.trim().orEmpty()
if (text.isEmpty()) return null
val address = try {
InetAddresses.parseNumericAddress(text)
} catch (e: IllegalArgumentException) {
return null
}
return address.takeUnless { it.isAnyLocalAddress || it.isLoopbackAddress }
}
null પરિણામ દોષિત ટેક્સ્ટ ધરાવતી ફીલ્ડ-સ્તરીય ભૂલ બને છે અને સપોર્ટ ફક્ત એ જ સ્વરૂપ પર કાર્ય કરી શકે. સફળ માર્ગમાં ઑબ્જેક્ટ સીધું builder.addDnsServer(address) માં જાય છે. IllegalArgumentException ખાસ પકડો, Exception નહીં: પહોળું પકડવું null પોઇન્ટર ભૂલો પણ ગળી જાય છે.
જ્યારે ઇચ્છિત મૂલ્ય નકારાય ત્યારે જાહેર resolver થી બદલો નહીં. ચૂપચાપ જાહેર DNS મૂકતી પ્રોફાઇલ જોડાય છે, પણ આંતરિક નામો ઉકેલાવાનું બંધ થાય છે.
ઇન્ટરફેસ બન્યા પછી પહોંચની પુષ્ટિ કરો
builder ની સ્વીકૃતિ પ્રથમ ચેકપોઇન્ટ છે, છેલ્લું નહીં. ઇન્ટરફેસ ઉપર આવ્યા પછી LinkProperties.getDnsServers() દર્શાવે છે કે નેટવર્કે ખરેખર શું મેળવ્યું. adb shell dumpsys connectivity બહારથી એ જ ગુણધર્મો છાપે છે.
Private DNS અલગ નિયંત્રણ છે અને આ દલીલમાંથી પસાર થતું નથી. DoT પ્રદાતાનું હોસ્ટનામ સિસ્ટમ સેટિંગનું છે, IP ફીલ્ડનું નહીં.
પ્રોફાઇલ પાર્સર ફરી બદલતા પહેલાં આ ક્રમમાં કામ કરો: કાચું સ્ટ્રિંગ અને તેનો સ્રોત લોગ કરો, તે હોસ્ટનામ નહીં લિટરલ છે તેની ખાતરી કરો, loopback કે wildcard નથી તેની ખાતરી કરો, અને વિશ્લેષિત ઑબ્જેક્ટ આગળ મોકલો.