मूल्य 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 पासून त्या पार्सरचा सार्वजनिक चेहरा.

व्यावहारिक मॅपिंग असे दिसते:

InputResultReason
10.8.0.1acceptedIPv4 literal
2606:4700:4700::1111acceptedIPv6 literal
dns.example.comrejectedhostname; numeric parsing does not resolve it
10.8.0.1:53rejectedport belongs to your own config model
https://dns.example.com/dns-queryrejectedDoH URL, a different configuration path
127.0.0.1rejectedloopback is not a remote resolver
0.0.0.0 or ::accepted by the builderparses 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 नाही.

इच्छित मूल्य नाकारले गेल्यास सार्वजनिक resolver ने बदलू नका; गुपचूप सार्वजनिक DNS टाकणारे प्रोफाइल जोडले जाते पण अंतर्गत नावे सोडवली जात नाहीत.

इंटरफेस तयार झाल्यावर पोहोच निश्चित करा

builder ची स्वीकृती पहिला तपासणी बिंदू आहे, शेवटचा नाही. इंटरफेस वर आल्यावर LinkProperties.getDnsServers() नेटवर्कला प्रत्यक्षात काय मिळाले ते दाखवते आणि adb shell dumpsys connectivity तीच गुणधर्म बाहेरून छापते.

Private DNS स्वतंत्र नियंत्रण आहे आणि या वितर्कातून जात नाही; DoT पुरवठादाराचे होस्टनाव सिस्टम सेटिंगचे आहे, IP फील्डचे नाही.

प्रोफाइल पार्सर पुन्हा बदलण्यापूर्वी कच्ची स्ट्रिंग आणि तिचा स्रोत नोंदवा, ती होस्टनाव नसलेले लिटरल आहे, loopback किंवा wildcard नाही याची खात्री करा, आणि विश्लेषित ऑब्जेक्ट पुढे पाठवा.

संबंधित लेख