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