diff --git a/core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt b/core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt index 2433f2a853..272201ce87 100644 --- a/core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt +++ b/core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt @@ -22,10 +22,13 @@ package com.github.shadowsocks.net import android.util.Log import com.crashlytics.android.Crashlytics +import com.github.shadowsocks.Core +import com.github.shadowsocks.utils.parseNumericAddress import com.github.shadowsocks.utils.printLog import kotlinx.coroutines.* import org.xbill.DNS.* import java.io.EOFException +import java.io.File import java.io.IOException import java.net.* import java.nio.ByteBuffer @@ -55,6 +58,8 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array = emptyList() + private val hostsMap: Map> = readHosts() + companion object { private const val TAG = "LocalDnsServer" private const val TIMEOUT = 10_000L @@ -65,12 +70,25 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array): ByteBuffer = + ByteBuffer.wrap(prepareDnsResponse(request).apply { + header.setFlag(Flags.RA.toInt()) // recursion available + for (address in results) addRecord(when (address) { + is Inet4Address -> ARecord(question.name, DClass.IN, TTL, address) + is Inet6Address -> AAAARecord(question.name, DClass.IN, TTL, address) + else -> throw IllegalStateException("Unsupported address $address") + }, Section.ANSWER) + }.toWire()) } + private val monitor = ChannelMonitor() private val job = SupervisorJob() @@ -102,10 +120,16 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array Array localResults.any(subnet::matches) }) { remote.cancel() - ByteBuffer.wrap(prepareDnsResponse(request).apply { - header.setFlag(Flags.RA.toInt()) // recursion available - for (address in localResults) addRecord(when (address) { - is Inet4Address -> ARecord(question.name, DClass.IN, TTL, address) - is Inet6Address -> AAAARecord(question.name, DClass.IN, TTL, address) - else -> throw IllegalStateException("Unsupported address $address") - }, Section.ANSWER) - }.toWire()) + prepareDnsResponseWithResults(request, localResults) } else remote.await() } catch (e: Exception) { remote.cancel() @@ -142,6 +159,42 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array = + this.hostsMap[h]?.toTypedArray() ?: emptyArray() + + private fun readHosts(): Map> { + val hostsMap: MutableMap> = HashMap() + try { + val hostsFile = File(Core.deviceStorage.getExternalFilesDir(null), "hosts") + hostsFile.createNewFile() + hostsFile.forEachLine { + val line = it.substringBefore('#') + if (line.isEmpty()) { + return@forEachLine + } + + val splitted = line.split(hostsDelimiter) + if (splitted.size < 2) { + return@forEachLine + } + val addr = splitted[0].parseNumericAddress() ?: return@forEachLine + for (j in 1 until splitted.size) { + val d = splitted[j] + var el = hostsMap[d] + if (el == null) { + el = HashSet(1) + hostsMap[d] = el + } + el.add(addr) + } + } + return hostsMap.mapValues { it.value.toList() } + } catch (e: IOException) { + printLog(e) + } + return emptyMap() + } + private suspend fun forward(packet: ByteBuffer): ByteBuffer { packet.position(0) // the packet might have been parsed, reset to beginning return if (tcp) SocketChannel.open().use { channel ->