Commit ef1bd7d7 authored by Mygod's avatar Mygod

Ensure hosts results are used

Fixes #2412.
parent e9dc275f
......@@ -38,9 +38,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import java.net.UnknownHostException
import java.net.*
import java.security.MessageDigest
/**
......@@ -87,16 +85,24 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro
// it's hard to resolve DNS on a specific interface so we'll do it here
if (profile.host.parseNumericAddress() == null) {
// if fails/null, use IPv4 only, otherwise pick a random IPv4/IPv6 address
val network = service.getActiveNetwork() ?: throw UnknownHostException()
val hasIpv4 = DnsResolverCompat.haveIpv4(network)
val hasIpv6 = DnsResolverCompat.haveIpv6(network)
if (!hasIpv4 && !hasIpv6) throw UnknownHostException()
profile.host = (hosts.resolve(profile.host, hasIpv6).firstOrNull() ?: try {
service.resolver(profile.host).firstOrNull()
} catch (_: IOException) {
null
})?.hostAddress ?: throw UnknownHostException()
profile.host = hosts.resolve(profile.host).run {
if (isEmpty()) try {
service.resolver(profile.host).firstOrNull()
} catch (_: IOException) {
null
} else {
val network = service.getActiveNetwork() ?: throw UnknownHostException()
val hasIpv4 = DnsResolverCompat.haveIpv4(network)
val hasIpv6 = DnsResolverCompat.haveIpv6(network)
firstOrNull {
when (it) {
is Inet4Address -> hasIpv4
is Inet6Address -> hasIpv6
else -> error(it)
}
}
}
}?.hostAddress ?: throw UnknownHostException()
}
}
......
......@@ -21,8 +21,6 @@
package com.github.shadowsocks.net
import com.github.shadowsocks.utils.parseNumericAddress
import java.net.Inet4Address
import java.net.Inet6Address
import java.net.InetAddress
class HostsFile(input: String = "") {
......@@ -36,9 +34,5 @@ class HostsFile(input: String = "") {
}
val configuredHostnames get() = map.size
fun resolve(hostname: String, isIpv6: Boolean): List<InetAddress> {
return (map[hostname] ?: return emptyList()).run {
if (isIpv6) filterIsInstance<Inet6Address>() else filterIsInstance<Inet4Address>()
}.shuffled()
}
fun resolve(hostname: String) = map[hostname]?.shuffled() ?: emptyList()
}
......@@ -124,10 +124,12 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd
else -> return@supervisorScope remote.await()
}
val host = question.name.canonicalize().toString(true)
val hostsResults = hosts.resolve(host, isIpv6)
val hostsResults = hosts.resolve(host)
if (hostsResults.isNotEmpty()) {
remote.cancel()
return@supervisorScope cookDnsResponse(request, hostsResults)
return@supervisorScope cookDnsResponse(request, hostsResults.run {
if (isIpv6) filterIsInstance<Inet6Address>() else filterIsInstance<Inet4Address>()
})
}
val acl = acl?.await() ?: return@supervisorScope remote.await()
val useLocal = when (acl.shouldBypass(host)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment