From c7e1abb585edcad6a07727aaef05f37b5378b247 Mon Sep 17 00:00:00 2001 From: Mygod Date: Thu, 8 Mar 2018 00:41:50 -0800 Subject: [PATCH] Properly support proper VPNs It turns out that not using masquerade will not work with real VPNs (as opposed to dummy ones, including adblockers and sockifiers). Fixes #10. --- .../be/mygod/vpnhotspot/RepeaterService.kt | 2 +- .../be/mygod/vpnhotspot/TetheringService.kt | 2 +- .../java/be/mygod/vpnhotspot/net/Routing.kt | 24 +++++++++++++++---- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt index 58ddc446..57ea0b55 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt @@ -296,7 +296,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, VpnMonitor.Ca val strict = app.pref.getBoolean("service.repeater.strict", false) return if (strict && upstream == null || // in this case, nothing to be done routing.ipForward() // Wi-Fi direct doesn't enable ip_forward - .rule().forward(strict).dnsRedirect(dns).start()) true else { + .rule().forward(strict).masquerade(strict).dnsRedirect(dns).start()) true else { routing.stop() Toast.makeText(this, getText(R.string.noisy_su_failure), Toast.LENGTH_SHORT).show() false diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/TetheringService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/TetheringService.kt index aa2d24ab..b46b027c 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/TetheringService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/TetheringService.kt @@ -52,7 +52,7 @@ class TetheringService : Service(), VpnMonitor.Callback, IpNeighbourMonitor.Call for ((downstream, value) in routings) if (value == null) try { // system tethering already has working forwarding rules // so it doesn't make sense to add additional forwarding rules - val routing = Routing(upstream, downstream).rule().forward().dnsRedirect(dns) + val routing = Routing(upstream, downstream).rule().forward().masquerade().dnsRedirect(dns) if (routing.start()) routings[downstream] = routing else { failed = true routing.stop() diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt index 6d7b2483..3927ce75 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt @@ -26,9 +26,11 @@ class Routing(val upstream: String?, val downstream: String, ownerAddress: InetA fun clean() = noisySu( "$IPTABLES -t nat -F PREROUTING", "quiet while $IPTABLES -D FORWARD -j vpnhotspot_fwd; do done", - "quiet while $IPTABLES -t nat -D POSTROUTING -j MASQUERADE; 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") fun dump(): InputStream? { @@ -95,19 +97,33 @@ class Routing(val upstream: String?, val downstream: String, ownerAddress: InetA stopScript.addFirst("$IPTABLES -D vpnhotspot_fwd -i $downstream -o $upstream -j ACCEPT") } else { // for not strict mode, allow downstream packets to be redirected to anywhere - // also enable unconditional NAT masquerade + // 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") - startScript.add("$IPTABLES -t nat -A POSTROUTING -j MASQUERADE") 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") - stopScript.addFirst("$IPTABLES -t nat -D POSTROUTING -j MASQUERADE") } startScript.add("$IPTABLES -I FORWARD -j vpnhotspot_fwd") stopScript.addFirst("$IPTABLES -D FORWARD -j vpnhotspot_fwd") return this } + fun masquerade(strict: Boolean = true): Routing { + startScript.add("quiet $IPTABLES -t nat -N vpnhotspot_masquerade 2>/dev/null") + // note: specifying -i wouldn't work for POSTROUTING + if (strict) { + check(upstream != null) + startScript.add("$IPTABLES -t nat -A vpnhotspot_masquerade -o $upstream -j MASQUERADE") + stopScript.addFirst("$IPTABLES -t nat -D vpnhotspot_masquerade -o $upstream -j MASQUERADE") + } else { + startScript.add("$IPTABLES -t nat -A vpnhotspot_masquerade -j MASQUERADE") + stopScript.addFirst("$IPTABLES -t nat -D vpnhotspot_masquerade -j MASQUERADE") + } + startScript.add("$IPTABLES -t nat -I POSTROUTING -j vpnhotspot_masquerade") + stopScript.addFirst("$IPTABLES -t nat -D POSTROUTING -j vpnhotspot_masquerade") + return this + } + fun dnsRedirect(dnses: List): Routing { val hostAddress = hostAddress.hostAddress val dns = dnses.firstOrNull { it is Inet4Address }?.hostAddress