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:

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

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.

Artikuj të ngjashëm