Migrate from NoisySu to RootSession

Fix #24. Note that just like before, IpMonitor doesn't use RootSession.
This commit is contained in:
Mygod
2018-09-06 15:36:34 +08:00
parent aa624708bb
commit 823ae9633b
12 changed files with 273 additions and 205 deletions

View File

@@ -3,11 +3,15 @@ package be.mygod.vpnhotspot.net
import android.os.Build
import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.R
import be.mygod.vpnhotspot.util.RootSession
import be.mygod.vpnhotspot.util.debugLog
import be.mygod.vpnhotspot.util.noisySu
import java.net.*
import java.util.*
/**
* A transaction wrapper that helps set up routing environment.
*
* Once revert is called, this object no longer serves any purpose.
*/
class Routing(val upstream: String?, private val downstream: String, ownerAddress: InterfaceAddress? = null) {
companion object {
/**
@@ -18,17 +22,22 @@ class Routing(val upstream: String?, private val downstream: String, ownerAddres
*/
private val IPTABLES = if (Build.VERSION.SDK_INT >= 26) "iptables -w 1" else "iptables -w"
fun clean() = noisySu(
"$IPTABLES -t nat -F PREROUTING",
"quiet while $IPTABLES -D FORWARD -j vpnhotspot_fwd; do done",
"$IPTABLES -F vpnhotspot_fwd",
"$IPTABLES -X vpnhotspot_fwd",
"quiet while $IPTABLES -t nat -D POSTROUTING -j vpnhotspot_masquerade; do done",
"$IPTABLES -t nat -F vpnhotspot_masquerade",
"$IPTABLES -t nat -X vpnhotspot_masquerade",
"quiet while ip rule del priority 17900; do done",
"quiet while ip rule del iif lo uidrange 0-0 lookup local_network priority 11000; do done",
report = false)
fun clean() = RootSession.use {
it.submit("$IPTABLES -t nat -F PREROUTING")
it.submit("while $IPTABLES -D FORWARD -j vpnhotspot_fwd; do done")
it.submit("$IPTABLES -F vpnhotspot_fwd")
it.submit("$IPTABLES -X vpnhotspot_fwd")
it.submit("while $IPTABLES -t nat -D POSTROUTING -j vpnhotspot_masquerade; do done")
it.submit("$IPTABLES -t nat -F vpnhotspot_masquerade")
it.submit("$IPTABLES -t nat -X vpnhotspot_masquerade")
it.submit("while ip rule del priority 17900; do done")
it.submit("while ip rule del iif lo uidrange 0-0 lookup local_network priority 11000; do done")
}
fun RootSession.Transaction.iptablesAdd(content: String, table: String = "filter") =
exec("$IPTABLES -t $table -A $content", "$IPTABLES -t $table -D $content")
fun RootSession.Transaction.iptablesInsert(content: String, table: String = "filter") =
exec("$IPTABLES -t $table -I $content", "$IPTABLES -t $table -D $content")
}
class InterfaceNotFoundException : SocketException() {
@@ -37,18 +46,13 @@ class Routing(val upstream: String?, private val downstream: String, ownerAddres
val hostAddress = ownerAddress ?: NetworkInterface.getByName(downstream)?.interfaceAddresses?.asSequence()
?.singleOrNull { it.address is Inet4Address } ?: throw InterfaceNotFoundException()
private val startScript = LinkedList<String>()
private val stopScript = LinkedList<String>()
private val transaction = RootSession.beginTransaction()
var started = false
fun ipForward() {
startScript.add("echo 1 >/proc/sys/net/ipv4/ip_forward")
}
fun ipForward() = transaction.exec("echo 1 >/proc/sys/net/ipv4/ip_forward")
fun disableIpv6() {
startScript.add("echo 1 >/proc/sys/net/ipv6/conf/$downstream/disable_ipv6")
stopScript.add("echo 0 >/proc/sys/net/ipv6/conf/$downstream/disable_ipv6")
}
fun disableIpv6() = transaction.exec("echo 1 >/proc/sys/net/ipv6/conf/$downstream/disable_ipv6",
"echo 0 >/proc/sys/net/ipv6/conf/$downstream/disable_ipv6")
/**
* Since Android 5.0, RULE_PRIORITY_TETHERING = 18000.
@@ -58,63 +62,50 @@ class Routing(val upstream: String?, private val downstream: String, ownerAddres
*/
fun rule() {
if (upstream != null) {
startScript.add("ip rule add from all iif $downstream lookup $upstream priority 17900")
// by the time stopScript is called, table entry for upstream may already get removed
stopScript.addFirst("ip rule del from all iif $downstream priority 17900")
transaction.exec("ip rule add from all iif $downstream lookup $upstream priority 17900",
// by the time stopScript is called, table entry for upstream may already get removed
"ip rule del from all iif $downstream priority 17900")
}
}
fun forward(strict: Boolean = true) {
startScript.add("quiet $IPTABLES -N vpnhotspot_fwd 2>/dev/null")
transaction.execQuiet("$IPTABLES -N vpnhotspot_fwd")
transaction.iptablesInsert("FORWARD -j vpnhotspot_fwd")
if (strict) {
if (upstream != null) {
startScript.add("$IPTABLES -A vpnhotspot_fwd -i $upstream -o $downstream -m state --state ESTABLISHED,RELATED -j ACCEPT")
startScript.add("$IPTABLES -A vpnhotspot_fwd -i $downstream -o $upstream -j ACCEPT")
stopScript.addFirst("$IPTABLES -D vpnhotspot_fwd -i $upstream -o $downstream -m state --state ESTABLISHED,RELATED -j ACCEPT")
stopScript.addFirst("$IPTABLES -D vpnhotspot_fwd -i $downstream -o $upstream -j ACCEPT")
transaction.iptablesAdd("vpnhotspot_fwd -i $upstream -o $downstream -m state --state ESTABLISHED,RELATED -j ACCEPT")
transaction.iptablesAdd("vpnhotspot_fwd -i $downstream -o $upstream -j ACCEPT")
} // else nothing needs to be done
} else {
// for not strict mode, allow downstream packets to be redirected to anywhere
// because we don't wanna keep track of default network changes
startScript.add("$IPTABLES -A vpnhotspot_fwd -o $downstream -m state --state ESTABLISHED,RELATED -j ACCEPT")
startScript.add("$IPTABLES -A vpnhotspot_fwd -i $downstream -j ACCEPT")
stopScript.addFirst("$IPTABLES -D vpnhotspot_fwd -o $downstream -m state --state ESTABLISHED,RELATED -j ACCEPT")
stopScript.addFirst("$IPTABLES -D vpnhotspot_fwd -i $downstream -j ACCEPT")
transaction.iptablesAdd("vpnhotspot_fwd -o $downstream -m state --state ESTABLISHED,RELATED -j ACCEPT")
transaction.iptablesAdd("vpnhotspot_fwd -i $downstream -j ACCEPT")
}
startScript.add("$IPTABLES -I FORWARD -j vpnhotspot_fwd")
stopScript.addFirst("$IPTABLES -D FORWARD -j vpnhotspot_fwd")
}
fun overrideSystemRules() {
startScript.add("$IPTABLES -A vpnhotspot_fwd -i $downstream -j DROP")
stopScript.addFirst("$IPTABLES -D vpnhotspot_fwd -i $downstream -j DROP")
}
fun overrideSystemRules() = transaction.iptablesAdd("vpnhotspot_fwd -i $downstream -j DROP")
fun masquerade(strict: Boolean = true) {
val hostSubnet = "${hostAddress.address.hostAddress}/${hostAddress.networkPrefixLength}"
startScript.add("quiet $IPTABLES -t nat -N vpnhotspot_masquerade 2>/dev/null")
transaction.execQuiet("$IPTABLES -t nat -N vpnhotspot_masquerade")
transaction.iptablesInsert("POSTROUTING -j vpnhotspot_masquerade", "nat")
// note: specifying -i wouldn't work for POSTROUTING
if (strict) {
if (upstream != null) {
startScript.add("$IPTABLES -t nat -A vpnhotspot_masquerade -s $hostSubnet -o $upstream -j MASQUERADE")
stopScript.addFirst("$IPTABLES -t nat -D vpnhotspot_masquerade -s $hostSubnet -o $upstream -j MASQUERADE")
transaction.iptablesAdd("vpnhotspot_masquerade -s $hostSubnet -o $upstream -j MASQUERADE", "nat")
} // else nothing needs to be done
} else {
startScript.add("$IPTABLES -t nat -A vpnhotspot_masquerade -s $hostSubnet -j MASQUERADE")
stopScript.addFirst("$IPTABLES -t nat -D vpnhotspot_masquerade -s $hostSubnet -j MASQUERADE")
transaction.iptablesAdd("vpnhotspot_masquerade -s $hostSubnet -j MASQUERADE", "nat")
}
startScript.add("$IPTABLES -t nat -I POSTROUTING -j vpnhotspot_masquerade")
stopScript.addFirst("$IPTABLES -t nat -D POSTROUTING -j vpnhotspot_masquerade")
}
fun dnsRedirect(dnses: List<InetAddress>) {
val hostAddress = hostAddress.address.hostAddress
val dns = dnses.firstOrNull { it is Inet4Address }?.hostAddress ?: app.pref.getString("service.dns", "8.8.8.8")
debugLog("Routing", "Using $dns from ($dnses)")
startScript.add("$IPTABLES -t nat -A PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")
startScript.add("$IPTABLES -t nat -A PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")
stopScript.addFirst("$IPTABLES -t nat -D PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")
stopScript.addFirst("$IPTABLES -t nat -D PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")
transaction.iptablesAdd("PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns", "nat")
transaction.iptablesAdd("PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns", "nat")
}
/**
@@ -125,20 +116,9 @@ class Routing(val upstream: String?, private val downstream: String, ownerAddres
*
* Source: https://android.googlesource.com/platform/system/netd/+/b9baf26/server/RouteController.cpp#57
*/
fun dhcpWorkaround() {
startScript.add("ip rule add iif lo uidrange 0-0 lookup local_network priority 11000")
stopScript.addFirst("ip rule del iif lo uidrange 0-0 lookup local_network priority 11000")
}
fun dhcpWorkaround() = transaction.exec("ip rule add iif lo uidrange 0-0 lookup local_network priority 11000",
"ip rule del iif lo uidrange 0-0 lookup local_network priority 11000")
fun start(): Boolean {
if (started) return true
started = true
if (noisySu(startScript) != true) stop()
return started
}
fun stop(): Boolean {
if (!started) return true
started = false
return noisySu(stopScript, false) == true
}
fun commit() = transaction.commit()
fun revert() = transaction.revert()
}