Handle VPNs without addDnsServer calls
Test case: HTTP Injector
This commit is contained in:
@@ -31,6 +31,7 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
|||||||
*
|
*
|
||||||
* Source: https://android.googlesource.com/platform/system/netd/+/b9baf26/server/RouteController.cpp#65
|
* Source: https://android.googlesource.com/platform/system/netd/+/b9baf26/server/RouteController.cpp#65
|
||||||
*/
|
*/
|
||||||
|
private const val RULE_PRIORITY_DNS = 17700
|
||||||
private const val RULE_PRIORITY_UPSTREAM = 17800
|
private const val RULE_PRIORITY_UPSTREAM = 17800
|
||||||
private const val RULE_PRIORITY_UPSTREAM_FALLBACK = 17900
|
private const val RULE_PRIORITY_UPSTREAM_FALLBACK = 17900
|
||||||
|
|
||||||
@@ -52,11 +53,17 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
|||||||
it.execQuiet("while $IPTABLES -t nat -D POSTROUTING -j vpnhotspot_masquerade; do done")
|
it.execQuiet("while $IPTABLES -t nat -D POSTROUTING -j vpnhotspot_masquerade; do done")
|
||||||
it.execQuiet("$IPTABLES -t nat -F vpnhotspot_masquerade")
|
it.execQuiet("$IPTABLES -t nat -F vpnhotspot_masquerade")
|
||||||
it.execQuiet("$IPTABLES -t nat -X vpnhotspot_masquerade")
|
it.execQuiet("$IPTABLES -t nat -X vpnhotspot_masquerade")
|
||||||
|
it.execQuiet("while ip rule del priority $RULE_PRIORITY_DNS; do done")
|
||||||
it.execQuiet("while ip rule del priority $RULE_PRIORITY_UPSTREAM; do done")
|
it.execQuiet("while ip rule del priority $RULE_PRIORITY_UPSTREAM; do done")
|
||||||
it.execQuiet("while ip rule del priority $RULE_PRIORITY_UPSTREAM_FALLBACK; do done")
|
it.execQuiet("while ip rule del priority $RULE_PRIORITY_UPSTREAM_FALLBACK; do done")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun RootSession.Transaction.ipRule(rule: String, downstream: String, upstream: String, priority: Int) =
|
||||||
|
exec("ip rule add $rule iif $downstream lookup $upstream priority $priority",
|
||||||
|
// by the time stopScript is called, table entry for upstream may already get removed
|
||||||
|
"ip rule del $rule iif $downstream priority $priority")
|
||||||
|
|
||||||
private fun RootSession.Transaction.iptables(command: String, revert: String) {
|
private fun RootSession.Transaction.iptables(command: String, revert: String) {
|
||||||
val result = execQuiet(command, revert)
|
val result = execQuiet(command, revert)
|
||||||
val message = RootSession.checkOutput(command, result, err = false)
|
val message = RootSession.checkOutput(command, result, err = false)
|
||||||
@@ -100,11 +107,7 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
|||||||
*/
|
*/
|
||||||
inner class Subrouting(priority: Int, val upstream: String? = null) {
|
inner class Subrouting(priority: Int, val upstream: String? = null) {
|
||||||
val transaction = RootSession.beginTransaction().safeguard {
|
val transaction = RootSession.beginTransaction().safeguard {
|
||||||
if (upstream != null) {
|
if (upstream != null) ipRule("from all", downstream, upstream, priority)
|
||||||
exec("ip rule add from all iif $downstream lookup $upstream priority $priority",
|
|
||||||
// by the time stopScript is called, table entry for upstream may already get removed
|
|
||||||
"ip rule del from all iif $downstream priority $priority")
|
|
||||||
}
|
|
||||||
fun simpleMasquerade() {
|
fun simpleMasquerade() {
|
||||||
// note: specifying -i wouldn't work for POSTROUTING
|
// note: specifying -i wouldn't work for POSTROUTING
|
||||||
iptablesAdd(if (upstream == null) "vpnhotspot_masquerade -s $hostSubnet -j MASQUERADE" else
|
iptablesAdd(if (upstream == null) "vpnhotspot_masquerade -s $hostSubnet -j MASQUERADE" else
|
||||||
@@ -259,21 +262,27 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class DnsRoute(val dns: String) {
|
private inner class DnsRoute(val upstream: String, val dns: String) {
|
||||||
val transaction = RootSession.beginTransaction().safeguard {
|
val transaction = RootSession.beginTransaction().safeguard {
|
||||||
val hostAddress = hostAddress.address.hostAddress
|
val hostAddress = hostAddress.address.hostAddress
|
||||||
|
ipRule("from $hostSubnet to $dns", downstream, upstream, RULE_PRIORITY_DNS)
|
||||||
iptablesAdd("PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns", "nat")
|
iptablesAdd("PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns", "nat")
|
||||||
iptablesAdd("PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns", "nat")
|
iptablesAdd("PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns", "nat")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private var currentDns: DnsRoute? = null
|
private var currentDns: DnsRoute? = null
|
||||||
private fun updateDnsRoute() {
|
private fun updateDnsRoute() {
|
||||||
var dns = (upstream.dns + fallbackUpstream.dns).firstOrNull { it is Inet4Address }?.hostAddress
|
val selected = sequenceOf(upstream, fallbackUpstream).flatMap { upstream ->
|
||||||
|
val ifname = upstream.subrouting?.upstream
|
||||||
|
if (ifname == null) emptySequence() else upstream.dns.asSequence().map { ifname to it }
|
||||||
|
}.firstOrNull { it.second is Inet4Address }
|
||||||
|
val upstream = selected?.first
|
||||||
|
var dns = selected?.second?.hostAddress
|
||||||
if (dns.isNullOrBlank()) dns = null
|
if (dns.isNullOrBlank()) dns = null
|
||||||
if (dns != currentDns?.dns) {
|
if (upstream != currentDns?.upstream || dns != currentDns?.dns) {
|
||||||
currentDns?.transaction?.revert()
|
currentDns?.transaction?.revert()
|
||||||
currentDns = if (dns == null) null else try {
|
currentDns = if (upstream == null || dns == null) null else try {
|
||||||
DnsRoute(dns)
|
DnsRoute(upstream, dns)
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
Timber.w(e)
|
Timber.w(e)
|
||||||
SmartSnackbar.make(e).show()
|
SmartSnackbar.make(e).show()
|
||||||
|
|||||||
Reference in New Issue
Block a user