addDnsServer Bad Address: Android ਅਸਲ ਵਿੱਚ ਕੀ ਜਾਂਚਦਾ ਹੈ
addDnsServer ਤੋਂ ਆਉਣ ਵਾਲੀ Bad address ਗਲਤੀ ਸਥਾਨਕ ਫਾਰਮੈਟ ਜਾਂਚ ਹੈ, DNS ਫੇਲ੍ਹ ਹੋਣਾ ਨਹੀਂ। ਲਿਟਰਲ ਦਾ ਵਿਸ਼ਲੇਸ਼ਣ ਕਰੋ, loopback ਅਤੇ wildcard ਹਟਾਓ, ਫਿਰ ਪਹੁੰਚ ਜਾਂਚੋ।
ਮੁੱਲ 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 ਤੋਂ ਉਸ ਪਾਰਸਰ ਦਾ ਜਨਤਕ ਚਿਹਰਾ ਹੈ।
ਵਿਹਾਰਕ ਮੈਪਿੰਗ ਇੰਝ ਦਿਸਦੀ ਹੈ:
| 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 |
ਸੰਸਕਰਣ ਤੁਸੀਂ ਕਿਵੇਂ ਪ੍ਰਮਾਣਿਤ ਕਰਦੇ ਹੋ ਉਸ ਉੱਤੇ ਅਸਰ ਪਾਉਂਦਾ ਹੈ, 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 ਨਹੀਂ ਹੈ, ਅਤੇ ਵਿਸ਼ਲੇਸ਼ਿਤ ਵਸਤੂ ਅੱਗੇ ਭੇਜੋ।