ਮੁੱਲ VpnService.Builder.addDnsServer ਤੱਕ ਸਟ੍ਰਿੰਗ ਵਜੋਂ ਪਹੁੰਚਿਆ ਅਤੇ builder ਨੇ ਕੁਝ ਵੀ ਸਥਾਪਿਤ ਹੋਣ ਤੋਂ ਪਹਿਲਾਂ ਉੱਥੇ ਹੀ ਇਨਕਾਰ ਕਰ ਦਿੱਤਾ। ਇਹ ਇਨਕਾਰ ਸਥਾਨਕ ਹੈ: ਕਿਸੇ resolver ਨਾਲ ਸੰਪਰਕ ਨਹੀਂ ਹੋਇਆ, tunnel ਨਹੀਂ, ਅਤੇ ਜੋ ਫੇਲ੍ਹ ਹੋਇਆ ਉਹ ਫਾਰਮੈਟ ਜਾਂਚ ਹੈ, DNS ਨਹੀਂ।

ਇਹ ਮਹੱਤਵਪੂਰਨ ਹੈ ਕਿਉਂਕਿ ਆਮ VPN ਐਪ ਵਿੱਚ ਤਿੰਨ ਸਮਾਨ DNS ਇਨਪੁਟ ਹੁੰਦੇ ਹਨ: ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਮੁੱਲ, ਸਰਵਰ ਭੇਜਦਾ ਮੁੱਲ ਅਤੇ ਸਿਸਟਮ ਪੱਧਰ ਦਾ Private DNS। ਪਹਿਲੇ ਦੋ ਹੀ ਇਸ ਕਾਲ ਤੱਕ ਪਹੁੰਚਦੇ ਹਨ।

ਤਿਆਰੀ ਵਸਤੂ ਤਰਕ ਦੀ ਜਾਂਚ ਤੁਰੰਤ ਕਰਦੀ ਹੈ

VpnService.Builder tunnel ਨਹੀਂ ਹੈ। ਇਹ ਪਤੇ, ਰੂਟ ਅਤੇ ਸਰਵਰ ਇਕੱਠੇ ਕਰਨ ਵਾਲੀ ਤਿਆਰੀ ਵਸਤੂ ਹੈ, ਅਤੇ ਸਿਰਫ਼ establish() ਹੀ ਉਨ੍ਹਾਂ ਸੂਚੀਆਂ ਨੂੰ ਜੀਵਤ ParcelFileDescriptor ਅਤੇ ਇੰਟਰਫੇਸ ਵਿੱਚ ਬਦਲਦਾ ਹੈ। DNS ਐਂਟਰੀ addDnsServer ਕਾਲ ਕਰਦਿਆਂ ਜਾਂਚੀ ਜਾਂਦੀ ਹੈ।

ਦੋ ਨਤੀਜੇ: ਸਟੈਕ ਟਰੇਸ ਛੋਟਾ ਅਤੇ ਜਾਣਬੁੱਝ ਕੇ ਜਾਣਕਾਰੀ ਰਹਿਤ ਹੈ, ਅਤੇ ਲਾਪਰਵਾਹ catch resolver ਤੋਂ ਬਿਨਾਂ tunnel ਛੱਡ ਦਿੰਦਾ ਹੈ।

builder ਦਿੱਤੀ ਕੋਈ ਵੀ ਸੂਚੀ ਰੱਖਦਾ ਹੈ; ਜਾਂਚ ਪਾਸ ਕਰਨ ਵਾਲਾ ਸਰਵਰ ਜੋੜਨਾ ਸਿਰਫ਼ ਇਹ ਸਾਬਤ ਕਰਦਾ ਹੈ ਕਿ ਸਟ੍ਰਿੰਗ ਨਿਰਮਾਣ ਸਮੇਂ ਪਤਾ ਲਿਟਰਲ ਵਜੋਂ ਵਿਸ਼ਲੇਸ਼ਿਤ ਹੋਈ।

ਤਰਕ ਕੀ ਹੋ ਸਕਦਾ ਹੈ

ਪੈਰਾਮੀਟਰ ਪਤਾ ਹੈ, endpoint ਨਹੀਂ। Builder ਸੰਦਰਭ IPv4 ਜਾਂ IPv6 ਲਿਟਰਲ ਲੈਂਦਾ ਹੈ, ਅਤੇ ਵਿਸ਼ਲੇਸ਼ਣ ਸਿਰਫ਼ ਸੰਖਿਆਤਮਕ ਹੈ: android.net.InetAddresses.parseNumericAddress API 29 ਤੋਂ ਉਸ ਪਾਰਸਰ ਦਾ ਜਨਤਕ ਚਿਹਰਾ ਹੈ।

ਵਿਹਾਰਕ ਮੈਪਿੰਗ ਇੰਝ ਦਿਸਦੀ ਹੈ:

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

ਸੰਸਕਰਣ ਤੁਸੀਂ ਕਿਵੇਂ ਪ੍ਰਮਾਣਿਤ ਕਰਦੇ ਹੋ ਉਸ ਉੱਤੇ ਅਸਰ ਪਾਉਂਦਾ ਹੈ, builder ਕੀ ਸਵੀਕਾਰਦਾ ਹੈ ਉਸ ਉੱਤੇ ਨਹੀਂ। InetAddresses API 29 ਤੋਂ ਉਪਲਬਧ ਹੈ, ਇਸ ਲਈ Android 10 ਵਿੱਚ ਵਿਸ਼ਲੇਸ਼ਣ ਇੱਕ ਕਾਲ ਹੈ; addDnsServer(InetAddress) ਮੂਲ ਰੂਪ, String ਨਵੀਂ ਸ਼ਾਮਲ। API 29 ਤੋਂ ਹੇਠਾਂ InetAddress.getByName ਰੋਕਣ ਵਾਲੀ ਨੈੱਟਵਰਕ ਖੋਜ ਨਾਲ ਹੋਸਟਨਾਮ ਹੱਲ ਕਰੇਗਾ।

loopback ਇੱਥੇ ਅਸਵੀਕਾਰ ਹੁੰਦਾ ਹੈ, wildcard ਨਹੀਂ

ਡੈਸਕਟਾਪ VPN ਕਲਾਇੰਟ ਆਪਣਾ stub resolver 127.0.0.1:53 ਵੱਲ ਭੇਜਦੇ ਹਨ; ਇਸਨੂੰ Android ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਨਕਲ ਕਰਨ ਨਾਲ ਸਥਾਨਕ ਮਸ਼ੀਨ ਦਾ ਵਰਣਨ ਕਰਨ ਵਾਲਾ ਮੁੱਲ ਆਉਂਦਾ ਹੈ, ਅਤੇ ਇੱਥੇ ਸਥਾਨਕ ਮਸ਼ੀਨ ਨਹੀਂ ਹੈ। builder ਸਿਰਫ਼ ਇਸ ਹਾਲਤ ਨੂੰ ਇਨਕਾਰ ਕਰਦਾ ਹੈ: null ਜਾਂ loopback ਪਤਾ IllegalArgumentException ਸੁੱਟਦਾ ਹੈ।

wildcard ਉਲਟ ਹਾਲਤ ਹੈ ਅਤੇ ਇੱਥੇ ਹੀ ਬਹੁਤੇ ਪਾਠ ਗਲਤ ਹੁੰਦੇ ਹਨ। 0.0.0.0 ਅਤੇ :: loopback ਨਹੀਂ ਹਨ, ਇਸ ਲਈ builder ਉਨ੍ਹਾਂ ਨੂੰ ਸਵੀਕਾਰ ਕਰਦਾ ਹੈ; ਨਿਰਮਾਣ ਵਿੱਚ ਕੁਝ ਨਹੀਂ ਸੁੱਟਿਆ ਜਾਂਦਾ। ਫਿਰ ਇੰਟਰਫੇਸ ਕੋਈ ਮੰਜ਼ਿਲ ਨਾ ਦੱਸਣ ਵਾਲੀ ਐਂਟਰੀ ਨਾਲ ਉੱਠਦਾ ਹੈ। ਇਸਨੂੰ ਫੜਨਾ ਤੁਹਾਡੇ ਵੈਲਿਡੇਟਰ ਦਾ ਕੰਮ ਹੈ: isAnyLocalAddress ਨੂੰ ਅਵੈਧ ਇਨਪੁਟ ਮੰਨੋ।

ਕਨਫਿਗਰੇਸ਼ਨ ਦੀ ਸੀਮਾ ਉੱਤੇ ਇੱਕ ਵਾਰ ਵਿਸ਼ਲੇਸ਼ਣ ਕਰੋ

ਸਸਤਾ ਹੱਲ ਇਹ ਹੈ ਕਿ ਸਟ੍ਰਿੰਗ ਤੁਹਾਡੇ ਮਾਡਲ ਵਿੱਚ ਜਿੱਥੇ ਦਾਖਲ ਹੁੰਦੀ ਹੈ ਉੱਥੇ ਪ੍ਰਮਾਣਿਤ ਕਰੋ:

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 ਨਤੀਜਾ ਦੋਸ਼ੀ ਟੈਕਸਟ ਵਾਲੀ ਫੀਲਡ-ਪੱਧਰੀ ਗਲਤੀ ਬਣਦਾ ਹੈ ਅਤੇ ਸਹਾਇਤਾ ਸਿਰਫ਼ ਇਸੇ ਰੂਪ ਉੱਤੇ ਕੰਮ ਕਰ ਸਕਦੀ ਹੈ। ਸਫਲ ਰਾਹ ਵਿੱਚ ਵਸਤੂ ਸਿੱਧੀ builder.addDnsServer(address) ਵਿੱਚ ਜਾਂਦੀ ਹੈ, ਅਤੇ IllegalArgumentException ਨੂੰ ਖਾਸ ਤੌਰ ਉੱਤੇ ਫੜੋ, Exception ਨੂੰ ਨਹੀਂ।

ਜਦੋਂ ਲੋੜੀਂਦਾ ਮੁੱਲ ਇਨਕਾਰ ਹੋਵੇ ਤਾਂ ਜਨਤਕ resolver ਨਾਲ ਨਾ ਬਦਲੋ; ਚੁੱਪਚਾਪ ਜਨਤਕ DNS ਰੱਖਣ ਵਾਲਾ ਪ੍ਰੋਫਾਈਲ ਜੁੜਦਾ ਹੈ ਪਰ ਅੰਦਰੂਨੀ ਨਾਮ ਹੱਲ ਹੋਣਾ ਬੰਦ ਹੋ ਜਾਂਦਾ ਹੈ।

ਇੰਟਰਫੇਸ ਬਣਨ ਤੋਂ ਬਾਅਦ ਪਹੁੰਚ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ

builder ਦੀ ਸਵੀਕ੍ਰਿਤੀ ਪਹਿਲਾ ਜਾਂਚ ਬਿੰਦੂ ਹੈ, ਆਖਰੀ ਨਹੀਂ। ਇੰਟਰਫੇਸ ਉੱਠਣ ਤੋਂ ਬਾਅਦ LinkProperties.getDnsServers() ਦਿਖਾਉਂਦਾ ਹੈ ਕਿ ਨੈੱਟਵਰਕ ਨੇ ਅਸਲ ਵਿੱਚ ਕੀ ਪ੍ਰਾਪਤ ਕੀਤਾ ਅਤੇ adb shell dumpsys connectivity ਉਹੀ ਗੁਣ ਬਾਹਰੋਂ ਛਾਪਦਾ ਹੈ।

Private DNS ਵੱਖਰਾ ਨਿਯੰਤਰਣ ਹੈ ਅਤੇ ਇਸ ਤਰਕ ਵਿੱਚੋਂ ਨਹੀਂ ਲੰਘਦਾ; DoT ਪ੍ਰਦਾਤਾ ਦਾ ਹੋਸਟਨਾਮ ਸਿਸਟਮ ਸੈਟਿੰਗ ਦਾ ਹੈ, IP ਫੀਲਡ ਦਾ ਨਹੀਂ।

ਪ੍ਰੋਫਾਈਲ ਪਾਰਸਰ ਦੁਬਾਰਾ ਬਦਲਣ ਤੋਂ ਪਹਿਲਾਂ ਕੱਚੀ ਸਟ੍ਰਿੰਗ ਅਤੇ ਉਸਦਾ ਸਰੋਤ ਲੌਗ ਕਰੋ, ਪੁਸ਼ਟੀ ਕਰੋ ਕਿ ਇਹ ਹੋਸਟਨਾਮ ਨਹੀਂ ਲਿਟਰਲ ਹੈ, loopback ਜਾਂ wildcard ਨਹੀਂ ਹੈ, ਅਤੇ ਵਿਸ਼ਲੇਸ਼ਿਤ ਵਸਤੂ ਅੱਗੇ ਭੇਜੋ।

ਸੰਬੰਧਿਤ ਲੇਖ