addDnsServer Bad Address: Android aslida nimani tekshiradi
addDnsServer xatosi Bad address mahalliy format tekshiruvi, DNS uzilishi emas. Literalni tahlil qiling, loopback va wildcardni olib tashlang, song yetib borishni sinang.
Qiymat VpnService.Builder.addDnsServer ga satr sifatida yetib keldi va builder uni hech narsa ornatilmasdan turib osha yerda rad etdi. Bu rad etish mahalliy: hech qanday resolver bilan aloqa qilinmadi, tunnel yoq, va muvaffaqiyatsiz bolgan narsa format tekshiruvi, DNS emas.
Bu muhim, chunki odatiy VPN ilovasida uchta oxshash DNS kirishi bor: profildagi qiymat, server yuboradigan qiymat va tizim darajasidagi Private DNS. Faqat birinchi ikkitasi bu chaqiruvga yetib boradi.
Tayyorlash obyekti argumentni darhol tekshiradi
VpnService.Builder tunnel emas. U manzillar, marshrutlar va serverlarni toplaydigan tayyorlash obyekti, va faqat establish() bu royxatlarni tirik ParcelFileDescriptor va interfeysga aylantiradi. DNS yozuvi addDnsServer chaqirilganda tekshiriladi.
Ikki natija: stack izi qisqa va ataylab malumotsiz, beparvo catch esa resolver siz tunnel qoldiradi.
Builder berilgan har qanday royxatni saqlaydi; tekshiruvdan otgan server qoshish satr qurish paytida manzil literali sifatida tahlil qilinganini isbotlaydi xolos.
Argument nima bolishi mumkin
Parametr manzil, endpoint emas. Builder manbasi IPv4 yoki IPv6 literalini oladi va tahlil faqat sonli: android.net.InetAddresses.parseNumericAddress API 29 dan beri osha parserniнг ommaviy yuzi.
Amaliy moslik shunday korinadi:
| 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 |
Versiya qanday tekshirishingizga tasir qiladi, builder nima qabul qilishiga emas. InetAddresses API 29 dan mavjud, shuning uchun Android 10 da tahlil bitta chaqiruv; addDnsServer(InetAddress) asl shakl, String yangi qoshimcha. API 29 dan pastda InetAddress.getByName xost nomini bloklovchi tarmoq qidiruvi bilan hal qiladi.
Loopback bu yerda rad etiladi, wildcard emas
Ish stoli VPN mijozlari oz stub resolverlarini 127.0.0.1:53 ga yuboradi; uni Android profiliga ko chirish mahalliy mashinani tasvirlovchi qiymat kiritadi, bu yerda esa mahalliy mashina yoq. Builder faqat shu holatni rad etadi: null yoki loopback manzil IllegalArgumentException tashlaydi.
Wildcard buning aksi va aynan shu yerda bu xatoning kop talqinlari xato qiladi. 0.0.0.0 va :: loopback emas, shuning uchun builder ularni qabul qiladi; qurishda hech narsa tashlanmaydi. Song interfeys hech qanday manzilni nomlamaydigan yozuv bilan kotariladi. Buni tutish validatoringiz ishi: isAnyLocalAddress ni notogri kirish deb biling.
Konfiguratsiya chegarasida bir marta tahlil qiling
Arzon yechim satr modelingizga kiradigan joyda tekshirish:
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 natija aybdor matnni olib yuruvchi maydon darajasidagi xatoga aylanadi va qollab-quvvatlash faqat shu shaklda harakat qila oladi. Muvaffaqiyat yolda obyekt togri builder.addDnsServer(address) ichiga kiradi, IllegalArgumentException ni aniq tuting, Exception ni emas.
Kutilgan qiymat rad etilganda ommaviy resolver bilan almashtirmang; jimgina ommaviy DNS qoyadigan profil ulanadi, lekin ichki nomlar hal bolmaydi.
Interfeys paydo bolgach yetib borishni tasdiqlang
Builderning qabul qilishi birinchi nazorat nuqtasi, oxirgisi emas. Interfeys kotarilgach LinkProperties.getDnsServers() tarmoq aslida nima olganini korsatadi, adb shell dumpsys connectivity esa osha xossalarni tashqaridan chop etadi.
Private DNS alohida boshqaruv va bu argumentdan otmaydi; DoT provayderining xost nomi tizim sozlamasiga tegishli, IP maydoniga emas.
Profil parserini yana ozgartirishdan oldin xom satrni va uning manbasini yozib oling, u xost nomi emas literal ekanini, loopback yoki wildcard emasligini tasdiqlang va tahlil qilingan obyektni uzating.