Commit 7ea25c7c authored by Mygod's avatar Mygod

Support matching IPv6 in LocalDnsServer

This fixes confusions once and for all in like fa3d4e78.

Also updates China IP address blocks.
parent 3f25eace
......@@ -37,9 +37,15 @@ import java.util.*
object LocalDnsService {
private val googleApisTester =
"(^|\\.)googleapis(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}\$".toRegex()
private val chinaIpList by lazy {
app.resources.openRawResource(R.raw.china_ip_list).bufferedReader()
.lineSequence().map(Subnet.Companion::fromString).filterNotNull().toList()
private val chinaIpv4List by lazy {
app.resources.openRawResource(R.raw.zone_cn).bufferedReader().lineSequence().map {
Subnet.fromString(it, 4)
}.filterNotNull().toList()
}
private val chinaIpv6List by lazy {
app.resources.openRawResource(R.raw.zone_cn_ipv6).bufferedReader().lineSequence().map {
Subnet.fromString(it, 16)
}.filterNotNull().toList()
}
private val servers = WeakHashMap<Interface, LocalDnsServer>()
......@@ -61,7 +67,8 @@ object LocalDnsService {
when (profile.route) {
Acl.BYPASS_CHN, Acl.BYPASS_LAN_CHN, Acl.GFWLIST, Acl.CUSTOM_RULES -> {
remoteDomainMatcher = googleApisTester
localIpMatcher = chinaIpList
localIpv4Matcher = chinaIpv4List
localIpv6Matcher = chinaIpv6List
}
Acl.CHINALIST -> { }
else -> forwardOnly = true
......
......@@ -55,7 +55,8 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd
*/
var tcp = true
var remoteDomainMatcher: Regex? = null
var localIpMatcher: List<Subnet> = emptyList()
var localIpv4Matcher: List<Subnet> = emptyList()
var localIpv6Matcher: List<Subnet> = emptyList()
companion object {
private const val TAG = "LocalDnsServer"
......@@ -122,7 +123,11 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd
try {
if (request.header.opcode != Opcode.QUERY) return@supervisorScope remote.await()
val question = request.question
if (question?.type != Type.A) return@supervisorScope remote.await()
val isIpv6 = when (question?.type) {
Type.A -> false
Type.AAAA -> true
else -> return@supervisorScope remote.await()
}
val host = question.name.toString(true)
val hostsResults = hosts.resolve(host)
if (hostsResults.isNotEmpty()) {
......@@ -140,7 +145,8 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd
return@supervisorScope remote.await()
}
if (localResults.isEmpty()) return@supervisorScope remote.await()
if (localIpMatcher.isEmpty() || localIpMatcher.any { subnet -> localResults.any(subnet::matches) }) {
val matcher = if (isIpv6) localIpv6Matcher else localIpv4Matcher
if (matcher.isEmpty() || matcher.any { subnet -> localResults.any(subnet::matches) }) {
remote.cancel()
cookDnsResponse(request, localResults.asIterable())
} else remote.await()
......
......@@ -26,9 +26,10 @@ import java.util.*
class Subnet(val address: InetAddress, val prefixSize: Int) : Comparable<Subnet> {
companion object {
fun fromString(value: String): Subnet? {
fun fromString(value: String, lengthCheck: Int = -1): Subnet? {
val parts = value.split('/', limit = 2)
val addr = parts[0].parseNumericAddress() ?: return null
check(lengthCheck < 0 || addr.address.size == lengthCheck)
return if (parts.size == 2) try {
val prefixSize = parts[1].toInt()
if (prefixSize < 0 || prefixSize > addr.address.size shl 3) null else Subnet(addr, prefixSize)
......
This diff is collapsed.
......@@ -381,7 +381,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
view.setOnApplyWindowInsetsListener(ListHolderListener)
if (savedInstanceState != null) {
selectedItems.addAll(savedInstanceState.getStringArray(SELECTED_SUBNETS)
?.mapNotNull(Subnet.Companion::fromString) ?: listOf())
?.mapNotNull { Subnet.fromString(it) } ?: listOf())
selectedItems.addAll(savedInstanceState.getStringArray(SELECTED_HOSTNAMES)
?: arrayOf())
selectedItems.addAll(savedInstanceState.getStringArray(SELECTED_URLS)?.map { URL(it) }
......
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