Permalink
Browse files

Merge pull request #288 from ant9000/master

Patch for using DNS servers on nonstandard ports
  • Loading branch information...
kar committed Feb 5, 2019
2 parents c11aeb7 + 206c30f commit 39d05dc5439923528d665e7515dc07a069737b81
@@ -27,8 +27,10 @@ import kotlinx.coroutines.experimental.runBlocking
import org.blokada.R
import java.io.InputStreamReader
import java.net.InetAddress
import java.net.InetSocketAddress
import java.nio.charset.Charset
import java.util.Properties
import org.pcap4j.packet.namednumber.UdpPort

fun newDnsModule(ctx: Context): Kodein.Module {
return Kodein.Module {
@@ -73,7 +75,7 @@ fun newDnsModule(ctx: Context): Kodein.Module {

abstract class Dns {
abstract val choices: IProperty<List<DnsChoice>>
abstract val dnsServers: IProperty<List<InetAddress>>
abstract val dnsServers: IProperty<List<InetSocketAddress>>
}

class DnsImpl(
@@ -157,7 +159,7 @@ class DnsImpl(

data class DnsChoice(
val id: String,
var servers: List<InetAddress>,
var servers: List<InetSocketAddress>,
var active: Boolean = false,
var ipv6: Boolean = false,
val credit: String? = null,
@@ -198,7 +200,7 @@ class DnsSerialiser {
return dns.map {
val active = if (it.active) "active" else "inactive"
val ipv6 = if (it.ipv6) "ipv6" else "ipv4"
val servers = it.servers.map { it.hostAddress }.joinToString(";")
val servers = it.servers.map { it.getHostString() + ( if(it.getPort()!=53) ":" + it.getPort().toString() else "" ) }.joinToString(";")
val credit = it.credit ?: ""
val comment = it.comment ?: ""

@@ -213,7 +215,12 @@ class DnsSerialiser {
val id = entry[1]
val active = entry[2] == "active"
val ipv6 = entry[3] == "ipv6"
val servers = entry[4].split(";").filter { it.isNotBlank() }.map { InetAddress.getByName(it) }
val servers = entry[4].split(";").filter { it.isNotBlank() }.map {
val hostport = it.split(':',limit=2)
val host = hostport[0]
val port = (if (hostport.size==2) hostport[1] else "").toIntOrNull() ?: UdpPort.DOMAIN.valueAsInt()
InetSocketAddress(InetAddress.getByName(host), port)
}
val credit = if (entry[5].isNotBlank()) entry[5] else null
val comment = if (entry[6].isNotBlank()) entry[6] else null

@@ -442,8 +449,8 @@ class DnsListView(
}
}

fun printServers(s: List<InetAddress>): String {
return s.map { it.hostAddress.replace("/", "") }.joinToString (", ")
fun printServers(s: List<InetSocketAddress>): String {
return s.map { it.getHostString() + ( if(it.getPort()!=53) ":" + it.getPort().toString() else "" ) }.joinToString (", ")
}

class DnsActor(
@@ -538,7 +545,7 @@ class AddDialog(
fun show(filter: DnsChoice?) {
view.appView.reset()
if (filter != null) {
val s = filter.servers.map { it.hostAddress }.toMutableList()
val s = filter.servers.map { it.getHostString() + ( if(it.getPort()!=53) ":" + it.getPort().toString() else "" ) }.toMutableList()
view.appView.server1 = s.first()
view.appView.server2 = s.getOrElse(1, {""})
view.appView.correct = true
@@ -563,7 +570,10 @@ class AddDialog(
else {
val s = listOf(view.appView.server1, view.appView.server2).filter { it.isNotBlank() }.map {
runBlocking { async {
InetAddress.getByName(it)
val hostport = it.split(':',limit=2)
val host = hostport[0]
val port = (if (hostport.size==2) hostport[1] else "").toIntOrNull() ?: UdpPort.DOMAIN.valueAsInt()
InetSocketAddress(InetAddress.getByName(host), port)
}.await() }
}
dialog.dismiss()
@@ -715,7 +725,10 @@ class DnsAddView(
forceNotEmpty && s.isBlank() -> false
s.isBlank() -> true
else -> { try {
InetAddress.getByName(s)
val hostport = s.split(':',limit=2)
val host = hostport[0]
val port = (if (hostport.size==2) hostport[1] else "").toIntOrNull() ?: UdpPort.DOMAIN.valueAsInt()
InetSocketAddress(InetAddress.getByName(host), port)
true
} catch (e: Exception) { false }
}
@@ -2,6 +2,7 @@ package gs.environment

import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import org.pcap4j.packet.namednumber.UdpPort

/**
* Contains various utility functions related to connectivity on Android.
@@ -21,10 +22,10 @@ fun isTethering(ctx: android.content.Context, intent: android.content.Intent? =
return tethering
}

fun getDnsServers(ctx: android.content.Context): List<java.net.InetAddress> {
fun getDnsServers(ctx: android.content.Context): List<java.net.InetSocketAddress> {
var servers = if (android.os.Build.VERSION.SDK_INT >= 21) gs.environment.getDnsServersMethod1(ctx) else emptyList()
if (servers.isEmpty()) servers = gs.environment.getDnsServersMethod2()
return servers
return servers.map { java.net.InetSocketAddress(it, UdpPort.DOMAIN.valueAsInt()) }
}

fun isWifi(ctx: android.content.Context): Boolean {
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<core.DnsAddView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBackground">
@@ -21,9 +22,8 @@
android:id="@+id/filter_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/dns_edit_name_placeholder"
android:digits="0123456789."
android:inputType="numberSigned|numberDecimal" />
android:digits="0123456789.:"
android:hint="@string/dns_edit_name_placeholder" />

<TextView
android:layout_width="match_parent"
@@ -9,7 +9,7 @@ import kotlinx.coroutines.experimental.newSingleThreadContext
import kotlinx.coroutines.experimental.runBlocking
import java.io.FileDescriptor
import java.net.DatagramSocket
import java.net.InetAddress
import java.net.InetSocketAddress
import java.util.*

object Events {
@@ -42,7 +42,7 @@ class Main(
onClose = onVpnClose,
onConfigure = { ktx, tunnel -> 0L }
)
private var currentServers = emptyList<InetAddress>()
private var currentServers = emptyList<InetSocketAddress>()
private var currentUrl: String = ""

private var tunnelThread: Thread? = null
@@ -54,7 +54,7 @@ class Main(
private var threadCounter = 0
private var usePausedConfigurator = false

fun setup(ktx: AndroidKontext, servers: List<InetAddress>, start: Boolean = false) = async(CTRL) {
fun setup(ktx: AndroidKontext, servers: List<InetSocketAddress>, start: Boolean = false) = async(CTRL) {
ktx.v("setup tunnel, start = $start, enabled = $enabled", servers)
when {
servers.isEmpty() -> {
@@ -10,9 +10,10 @@ import org.xbill.DNS.*
import java.io.IOException
import java.net.*
import java.util.*
import org.pcap4j.packet.namednumber.UdpPort

internal class Proxy(
private val dnsServers: List<InetAddress>,
private val dnsServers: List<InetSocketAddress>,
private val blockade: Blockade,
private val forwarder: Forwarder,
private val loopback: Queue<ByteArray>,
@@ -37,7 +38,7 @@ internal class Proxy(

if (udp.payload == null) {
// Some apps use empty UDP packets for something good
val proxiedUdp = DatagramPacket(ByteArray(0), 0, 0, destination,
val proxiedUdp = DatagramPacket(ByteArray(0), 0, 0, destination.getAddress(),
udp.header.dstPort.valueAsInt())
forward(ktx, proxiedUdp)
return
@@ -54,8 +55,8 @@ internal class Proxy(

val host = dnsMessage.question.name.toString(true).toLowerCase(Locale.ENGLISH)
if (blockade.allowed(host) || !blockade.denied(host)) {
val proxiedDns = DatagramPacket(udpRaw, 0, udpRaw.size, destination,
udp.header.dstPort.valueAsInt())
val proxiedDns = DatagramPacket(udpRaw, 0, udpRaw.size, destination.getAddress(),
destination.getPort())
forward(ktx, proxiedDns, originEnvelope)
} else {
dnsMessage.header.setFlag(Flags.QR.toInt())
@@ -114,14 +115,14 @@ internal class Proxy(

private fun loopback(ktx: Kontext, response: ByteArray) = loopback.add(response)

private fun resolveActualDestination(packet: IpPacket): InetAddress {
private fun resolveActualDestination(packet: IpPacket): InetSocketAddress {
val servers = dnsServers
val current = packet.header.dstAddr
val current = InetSocketAddress(packet.header.dstAddr, UdpPort.DOMAIN.valueAsInt())
return when {
servers.isEmpty() -> current
else -> try {
// Last octet of DNS server IP corresponds to its index
val index = current.address.last() - 2
val index = current.getAddress().address.last() - 2
servers[index]
} catch (e: Exception) {
current
@@ -6,11 +6,11 @@ import core.Kontext
import core.Result
import java.net.Inet4Address
import java.net.Inet6Address
import java.net.InetAddress
import java.net.InetSocketAddress
import java.util.*

internal class VpnConfigurator(
private val dnsServers: List<InetAddress>,
private val dnsServers: List<InetSocketAddress>,
private val filterManager: FilterManager
): Configurator {

@@ -40,7 +40,7 @@ internal class VpnConfigurator(
var ipv6Template: ByteArray? = byteArrayOf(32, 1, 13, (184 and 0xFF).toByte(),
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

if (dnsServers.any { it is Inet6Address }) {
if (dnsServers.any { it.getAddress() is Inet6Address }) {
try {
val address = Inet6Address.getByAddress(ipv6Template)
builder.addAddress(address, 120)
@@ -60,7 +60,7 @@ internal class VpnConfigurator(
ktx.e("failed adding dns server", e)
}
}
if (dnsServers.none { it is Inet6Address }) {
if (dnsServers.none { it.getAddress() is Inet6Address }) {
// If we add no IPv6 route or DNS server, all IPv6 access is otherwise blocked by default
builder.allowFamily(OsConstants.AF_INET6)
}
@@ -76,13 +76,13 @@ internal class VpnConfigurator(
}

private fun VpnService.Builder.addDnsServer(format: String?, ipv6Template: ByteArray?,
address: InetAddress) = when {
address is Inet6Address && ipv6Template != null -> {
address: InetSocketAddress) = when {
address.getAddress() is Inet6Address && ipv6Template != null -> {
ipv6Template[ipv6Template.size - 1] = (++dnsIndex).toByte()
val ipv6Address = Inet6Address.getByAddress(ipv6Template)
this.addDnsServer(ipv6Address)
}
address is Inet4Address && format != null -> {
address.getAddress() is Inet4Address && format != null -> {
val alias = String.format(Locale.ENGLISH, format, ++dnsIndex)
this.addDnsServer(alias)
this.addRoute(alias, 32)
@@ -92,14 +92,14 @@ internal class VpnConfigurator(
}

internal class PausedVpnConfigurator(
private val dnsServers: List<InetAddress>,
private val dnsServers: List<InetSocketAddress>,
private val filterManager: FilterManager
): Configurator {

override fun configure(ktx: Kontext, builder: VpnService.Builder) {
for (address in dnsServers) {
try {
builder.addDnsServer(address)
builder.addDnsServer(address.getAddress())
} catch (e: Exception) {
ktx.e("failed adding dns server", e)
}

0 comments on commit 39d05dc

Please sign in to comment.