Cyrhaeddodd y gwerth VpnService.Builder.addDnsServer fel llinyn, a gwrthododd y builder ef yno cyn i unrhyw beth gael ei sefydlu. Mae gwrthodiad yn lleol: ni chysylltwyd unrhyw resolver, nid oes tiwnel.

Mae hyn yn bwysig oherwydd bod gan ap VPN arferol dri mewnbwn DNS tebyg: gwerth yn y proffil, gwerth a anfonir gan y gweinydd, a Private DNS ar lefel y system. Dim ond y ddau gyntaf sy yn cyrraedd y galwad hon.

Mae gwrthrych paratoi yn gwirio y ddadl ar unwaith

Nid tiwnel yw VpnService.Builder. Mae yn wrthrych paratoi sy yn casglu cyfeiriadau, llwybrau a gweinyddwyr, a dim ond establish() sy yn troi rhestrau yn ParcelFileDescriptor byw. Gwiriwyd cofnod DNS pan alwch addDnsServer.

Mae dwy ganlyniad. Mae trace yn fyr ac yn fwriadol ddiwerth: daeth y gwerth fel llinyn plaen. Mae catch diofal o amgylch y adeiladu yn gadael tiwnel heb resolver.

Mae builder yn cadw unrhyw restr a roddwch. Nid yw ychwanegu gweinydd sy yn pasio ond yn profi bod y llinyn wedi ei ddadansoddi fel cyfeiriad.

Beth all y ddadl fod

Nid cyfeiriad yn unig yw parametr. Mae cyfeirlyfr Builder yn cymryd llythrennol IPv4 neu IPv6, ac mae dadansoddi yn rhifol yn unig: android.net.InetAddresses.parseNumericAddress yw wyneb cyhoeddus y parser hwnnw o API 29. Nid yw enw gwesteiwr yn gyfeiriad araf yma.

Dyma y mapio ymarferol:

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

Mae fersiwn yn effeithio ar sut rydych yn gwirio, nid ar beth mae builder yn ei dderbyn. Mae InetAddresses ar gael o API 29, felly ar Android 10 a hwyrach mae dadansoddi yn un alwad. addDnsServer(InetAddress) yw y ffurf wreiddiol, String y ychwanegiad newydd. O dan API 29 bydd InetAddress.getByName yn datrys enw gwesteiwr gyda chwiliad rhwydwaith blocio.

Gwrthodir loopback yma, nid wildcard

Mae cleientiaid VPN bwrdd gwaith yn aml yn anfon eu stub resolver i 127.0.0.1:53. Mae copio hynny i broffil Android yn mewnforio gwerth sy yn disgrifio y peiriant lleol, ac nid oes peiriant lleol yma. Mae builder yn gwrthod y achos hwn yn unig: mae cyfeiriad null neu loopback yn taflu IllegalArgumentException.

Mae wildcard yn y achos arall, a dyma lle mae rhan fwyaf o ddarlleniadau yn mynd o chwith. Nid yw 0.0.0.0 a :: yn loopback, felly mae builder yn eu derbyn; nid oes dim yn cael ei daflu. Mae y rhyngwyneb yn codi gyda chofnod heb gyrchfan. Eich gwaith chi yw dal hyn: triniwch isAnyLocalAddress fel mewnbwn annilys.

Dadansoddwch unwaith ar ffin y ffurfweddiad

Yr ateb rhad yw gwirio lle mae y llinyn yn dod i mewn i eich model:

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

Mae canlyniad null yn dod yn wall maes gyda y testun bai, a dyna y ffurf unig y gall cymorth weithredu arni. Ar lwybr llwyddiant mae y gwrthrych yn mynd i builder.addDnsServer(address). Deliwch IllegalArgumentException yn benodol, nid Exception.

Peidiwch a disodli gyda resolver cyhoeddus pan wrthodir y gwerth a fwriadwyd. Mae proffil sy yn newid yn dawel i DNS cyhoeddus yn cysylltu, ond mae enwau mewnol yn peidio datrys.

Cadarnhewch gyrhaeddiad ar ol i rhyngwyneb fodoli

Y derbyniad gan builder yw y pwynt gwirio cyntaf, nid yr olaf. Ar ol i rhyngwyneb godi mae LinkProperties.getDnsServers() yn dangos beth gafodd y rhwydwaith. Mae adb shell dumpsys connectivity yn argraffu yr un priodoleddau o tu allan.

Mae Private DNS yn rheolaeth ar wahan ac nid yw yn mynd trwy y ddadl hon. Mae enw gwesteiwr DoT yn perthyn i osodiad y system, nid i faes IP.

Cyn newid y parser proffil eto, gweithiwch yn y drefn hon: cofnodwch y llinyn crai a ei ffynhonnell, cadarnhewch ei fod yn llythrennol ac nid yn enw gwesteiwr, nad yw yn loopback nac yn wildcard, a throsglwyddwch y gwrthrych a ddadansoddwyd.

Erthyglau cysylltiedig