addDnsServer Bad Address: çfarë vërteton vërtet Android
Gabimi Bad address nga addDnsServer është një kontroll lokal i formatit, jo një dështim DNS. Analizoni literalin, hiqni loopback dhe wildcard, pastaj provoni arritshmërinë.
Vlera arriti në VpnService.Builder.addDnsServer si varg dhe builder-i e refuzoi atje para se të vendosej çdo gjë. Ky refuzim është lokal: asnjë resolver nuk u kontaktua, nuk ka tunel, dhe ajo që dështoi është një kontroll formati, jo DNS.
Kjo ka rëndësi sepse një aplikacion tipik VPN ka tre hyrje DNS të ngjashme: vlera në profil, vlera që dërgon serveri dhe Private DNS në nivel sistemi. Vetëm dy të parat arrijnë në këtë thirrje.
Objekti përgatitor e kontrollon argumentin menjëherë
VpnService.Builder nuk është tuneli. Është një objekt përgatitor që mbledh adresa, rrugë dhe serverë, dhe vetëm establish() i kthen ato lista në ParcelFileDescriptor të gjallë dhe në ndërfaqe. Hyrja DNS kontrollohet kur thirrni addDnsServer.
Dy pasoja: gjurma është e shkurtër dhe qëllimisht joinformative, dhe një catch i pakujdesshëm lë një tunel pa resolver.
Builder-i ruan çdo listë; shtimi i një serveri që kalon kontrollin provon vetëm se vargu u analizua si literal adrese gjatë ndërtimit.
Çfarë mund të jetë argumenti
Parametri është adresë, jo endpoint. Referenca Builder pranon një literal IPv4 ose IPv6, dhe analiza është vetëm numerike: android.net.InetAddresses.parseNumericAddress është fytyra publike e atij parseri që nga API 29.
Harta praktike duket kështu:
| 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 |
Versioni ndikon në mënyrën se si vërtetoni, jo në atë që pranon builder-i. InetAddresses është i disponueshëm nga API 29, prandaj në Android 10 analiza është një thirrje; addDnsServer(InetAddress) është forma origjinale, String shtesa më e re. Nën API 29 InetAddress.getByName do të zgjidhë një emër hosti me një kërkim rrjeti bllokues.
Loopback refuzohet këtu, wildcard jo
Klientët VPN të desktopit shpesh e drejtojnë stub resolver-in e tyre në 127.0.0.1:53; kopjimi i kësaj në një profil Android sjell një vlerë që përshkruan makinën lokale, dhe këtu nuk ka makinë lokale. Builder-i refuzon vetëm këtë rast: një adresë null ose loopback hedh IllegalArgumentException.
Wildcard është rasti i kundërt dhe këtu gabojnë shumica e leximeve. 0.0.0.0 dhe :: nuk janë loopback, prandaj builder-i i pranon; gjatë ndërtimit nuk hidhet asgjë. Ndërfaqja ngrihet me një zë që nuk emërton destinacion. Kapja e kësaj është puna e validatorit tuaj: trajtojeni isAnyLocalAddress si hyrje të pavlefshme.
Analizojeni një herë në kufirin e konfigurimit
Rregullimi i lirë është të vërtetohet aty ku vargu hyn në modelin tuaj:
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 }
}
Rezultati null bëhet gabim në nivel fushe me tekstin fajtor dhe është forma e vetme mbi të cilën mund të veprojë suporti. Në rrugën e suksesit objekti shkon drejt në builder.addDnsServer(address), dhe kapni IllegalArgumentException konkretisht, jo Exception.
Mos e zëvendësoni me resolver publik kur vlera e synuar refuzohet; një profil që vendos në heshtje një DNS publik lidhet, por emrat e brendshëm nuk zgjidhen më.
Vërtetoni arritshmërinë kur ndërfaqja ekziston
Pranimi nga builder-i është pika e parë e kontrollit, jo e fundit. Kur ndërfaqja ngrihet, LinkProperties.getDnsServers() raporton çfarë mori vërtet rrjeti, dhe adb shell dumpsys connectivity shtyp të njëjtat veti nga jashtë.
Private DNS është kontroll i veçantë dhe nuk kalon nëpër këtë argument; emri i hostit të një ofruesi DoT i takon konfigurimit të sistemit, jo një fushe IP.
Përpara se të ndryshoni përsëri parserin e profilit, regjistroni vargun e papërpunuar dhe burimin e tij, vërtetoni se është literal dhe jo emër hosti, se nuk është loopback as wildcard, dhe kaloni objektin e analizuar.