/
VpnConfigurator.kt
123 lines (102 loc) · 3.99 KB
/
VpnConfigurator.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package tunnel
import android.net.VpnService
import android.system.OsConstants
import core.Kontext
import core.Result
import java.net.Inet4Address
import java.net.Inet6Address
import java.net.InetSocketAddress
import java.util.*
internal class VpnConfigurator(
private val dnsServers: List<InetSocketAddress>,
private val filterManager: FilterManager
): Configurator {
private var dnsIndex = 1
override fun configure(ktx: Kontext, builder: VpnService.Builder) {
var format: String? = null
// Those are TEST-NET IP ranges from RFC5735, so that we don't collide.
for (prefix in arrayOf("203.0.113", "198.51.100", "192.0.2")) {
try {
builder.addAddress("$prefix.1", 24)
} catch (e: IllegalArgumentException) {
continue
}
format = "$prefix.%d"
break
}
if (format == null) {
// If no subnet worked, just go with something safe.
builder.addAddress("192.168.50.1", 24)
}
// Also a special subnet (2001:DB8::/32), from RFC3849. Meant for documentation use.
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.getAddress() is Inet6Address }) {
try {
val address = Inet6Address.getByAddress(ipv6Template)
builder.addAddress(address, 120)
} catch (e: Exception) {
ktx.e("failed adding ipv6 address", e)
ipv6Template = null
}
} else {
ipv6Template = null
}
dnsIndex = 1
for (address in dnsServers) {
try {
builder.addDnsServer(format, ipv6Template, address)
} catch (e: Exception) {
ktx.e("failed adding dns server", e)
}
}
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)
}
filterManager.getWhitelistedApps(ktx).forEach {
builder.addDisallowedApplication(it)
}
// People kept asking why GPlay doesnt work
Result.of { builder.addDisallowedApplication("com.android.vending") }
builder.setBlocking(true)
}
private fun VpnService.Builder.addDnsServer(format: String?, ipv6Template: ByteArray?,
address: InetSocketAddress) = when {
address.getAddress() is Inet6Address && ipv6Template != null -> {
ipv6Template[ipv6Template.size - 1] = (++dnsIndex).toByte()
val ipv6Address = Inet6Address.getByAddress(ipv6Template)
this.addDnsServer(ipv6Address)
}
address.getAddress() is Inet4Address && format != null -> {
val alias = String.format(Locale.ENGLISH, format, ++dnsIndex)
this.addDnsServer(alias)
this.addRoute(alias, 32)
}
else -> Unit
}
}
internal class PausedVpnConfigurator(
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.getAddress())
} catch (e: Exception) {
ktx.e("failed adding dns server", e)
}
}
filterManager.getWhitelistedApps(ktx).forEach {
builder.addDisallowedApplication(it)
}
// People kept asking why GPlay doesnt work
Result.of { builder.addDisallowedApplication("com.android.vending") }
builder.addAddress("203.0.113.0", 32)
builder.setBlocking(true)
}
}
interface Configurator {
fun configure(ktx: Kontext, builder: VpnService.Builder)
}