addDnsServer Bad Address: Android нақты нені тексереді
addDnsServer қатесі Bad address — бұл жергілікті формат тексерісі, DNS іркілісі емес. Литералды талдап, loopback пен wildcard-ты алып тастаңыз, содан кейін қолжетімділікті тексеріңіз.
Мән VpnService.Builder.addDnsServer ішіне жол ретінде жетті және builder оны сол жерде қабылдамады, ештеңе орнатылмай тұрып. Бұл бас тарту жергілікті: ешбір resolver-ге хабарласу болған жоқ, туннель жоқ, сәтсіз болғаны формат тексерісі, DNS емес.
Бұл маңызды, өйткені әдеттегі VPN қолданбасында үш ұқсас DNS кірісі бар: профильдегі мән, сервер жіберетін мән және жүйе деңгейіндегі Private DNS. Тек алғашқы екеуі осы шақыруға жетеді.
Дайындық нысаны аргументті бірден тексереді
VpnService.Builder туннель емес. Ол мекенжайларды, маршруттарды және серверлерді жинайтын дайындық нысаны, және тек establish() сол тізімдерді тірі ParcelFileDescriptor мен интерфейске айналдырады. DNS жазбасы addDnsServer шақырғанда тексеріледі.
Екі салдар: стек ізі қысқа және әдейі ақпаратсыз, ал немқұрайлы catch resolver-сіз туннель қалдырады.
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 емес.
Мақсатты мән қабылданбағанда оны ашық resolver-мен алмастырмаңыз; үнсіз ашық DNS қоятын профиль қосылады, бірақ ішкі атаулар шешілмейді.
Интерфейс пайда болған соң қолжетімділікті растаңыз
Builder-дің қабылдауы бірінші бақылау нүктесі, соңғысы емес. Интерфейс көтерілген соң LinkProperties.getDnsServers() желінің нақты не алғанын көрсетеді, adb shell dumpsys connectivity сол қасиеттерді сырттан басып шығарады.
Private DNS бөлек басқару және бұл аргументтен өтпейді; DoT провайдерінің хост аты жүйелік параметрге жатады, IP өрісіне емес.
Профиль парсерін қайта өзгертуден бұрын шикі жолды және оның көзін жазып алыңыз, оның хост аты емес литерал екенін, loopback немесе wildcard еместігін растап, талданған нысанды өткізіңіз.