De wearde berikte VpnService.Builder.addDnsServer as in string en de builder wegere dy dêr foardat der eat oprjochte wie. Dy wegering is lokaal: gjin resolver is kontakt, der is gjin tunnel en wat mislearre is in formaatkontrôle, gjin DNS-steuring.

Dat is fan belang om’t in typyske VPN-app trije like DNS-ynfier hat: in wearde dy’t yn it profyl typt of ymportearre is, in wearde dy’t de server by konfiguraasje stjoert en Private DNS op systeemnivo. Allinnich de earste twa berikke dizze oprop.

In tariedend objekt kontrolearret it argumint daliks

VpnService.Builder is net de tunnel. It is in tariedend objekt dat adressen, rûtes en servers sammelt, en allinnich establish() makket dy listen ta in libjend ParcelFileDescriptor en in interface. De DNS-ynfier wurdt kontrolearre by it oproppen fan addDnsServer, net by it oprjochtsjen.

Twa gefolgen. It spoar is koart en mei opsetsin sûnder ynformaasje: de wearde kaam as in gewoane string. En in slordige catch om de hiele bou lit in tunnel mei adressen en rûtes mar sûnder resolver.

De builder hâldt elke list dy’t him jout. In server tafoegje dy’t de kontrôle trochstiet bewiist allinnich dat de string by de bou as adresliteraal analysearre is.

Wat it argumint wêze mei

De parameter is in adres, net in endpoint. De Builder-referinsje nimt in IPv4- of IPv6-literaal, en de analyze is allinnich numerysk: android.net.InetAddresses.parseNumericAddress is it iepenbiere gesicht fan dy parser fan API 29 ôf. In hostnamme is hjir gjin stadich adres mar in string dy’t net analysearre wurde kin.

De praktyske mapping sjocht der sa út:

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

De ferzje makket út hoe’t jo validearje, net wat de builder akseptearret. InetAddresses is beskikber fan API 29 ôf, dus op Android 10 en nijer is de analyze ien oprop. addDnsServer(InetAddress) is de oarspronklike foarm, String de nijere tafoeging. Under API 29 sil InetAddress.getByName in hostnamme oplosse mei in blokkearjende netwurksyktocht en in typflater ta in stadige start meitsje.

Loopback wurdt hjir wegere, in wildcard net

Desktop-VPN-klanten rjochtsje harren eigen stub resolver faak op 127.0.0.1:53. Dat kopiearje yn in Android-profyl ymportearret in wearde dy’t de lokale masine beskriuwt, en hjir is gjin lokale masine. De builder wegere allinnich dit gefal: in null- of loopback-adres smyt IllegalArgumentException.

In wildcard is it tsjinoerstelde gefal, en hjir geane de measte lêzingen fan dizze flater mis. 0.0.0.0 en :: binne gjin loopback, dus de builder akseptearret se; by de bou wurdt neat smiten. De interface komt dan op mei in ynfier dy’t gjin bestimming neamt. Dat fange is it wurk fan jo validator: behannelje isAnyLocalAddress as ûnjildige ynfier.

Analysearje ien kear op de grins fan de konfiguraasje

De geunstige oplossing is validearje dêr’t de string jo model yngiet:

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 }
}

In null-resultaat wurdt in fjildnivo-flater mei de skuldige tekst, en dat is de iennichste foarm dêr’t stipe op wurkje kin. Op it suksespaad giet it objekt direkt yn builder.addDnsServer(address). Fange IllegalArgumentException spesifyk, net Exception: in brede fangst slokt ek null-oanwizerflaters.

Ferfange net troch in iepenbiere resolver as de bedoelde wearde wegere wurdt. In profyl dat stil in iepenbiere DNS set ferbynt noch, mar ynterne nammen wurde net mear oplost.

Befêstigje berikberens as de interface bestiet

Akseptaasje troch de builder is it earste kontrôlepunt, net it lêste. As de interface omheech is, lit LinkProperties.getDnsServers() sjen wat it netwurk wier krigen hat. adb shell dumpsys connectivity prints deselde eigenskippen fan bûten.

Private DNS is in aparte kontrôle en giet net troch dit argumint. De hostnamme fan in DoT-oanbieder heart by de systeemynstelling, net by in IP-fjild.

Foardat jo de profylparser wer feroarje, wurkje yn dizze folchoarder: log de rauwe string en syn boarne, befêstigje dat it in literaal is en gjin hostnamme, dat it gjin loopback en gjin wildcard is, en jou dan it analysearre objekt troch.

Relatearre artikelen