Revert "Remove fallback upstream monitor"
This commit reverts 99e721bf7e.
Fixes #119.
This commit is contained in:
@@ -48,7 +48,7 @@ abstract class RoutingManager(private val caller: Any, val downstream: String, p
|
||||
ipForward() // local only interfaces need to enable ip_forward
|
||||
forward()
|
||||
masquerade(masqueradeMode)
|
||||
commit(true)
|
||||
commit()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import androidx.preference.SwitchPreference
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.net.Routing.Companion.IPTABLES
|
||||
import be.mygod.vpnhotspot.net.TetherOffloadManager
|
||||
import be.mygod.vpnhotspot.net.monitor.FallbackUpstreamMonitor
|
||||
import be.mygod.vpnhotspot.net.monitor.IpMonitor
|
||||
import be.mygod.vpnhotspot.net.monitor.UpstreamMonitor
|
||||
import be.mygod.vpnhotspot.net.wifi.WifiDoubleLock
|
||||
@@ -115,6 +116,9 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
|echo iptables -nvx -L vpnhotspot_fwd
|
||||
|$IPTABLES -nvx -L vpnhotspot_fwd
|
||||
|echo
|
||||
|echo iptables -nvx -L vpnhotspot_acl
|
||||
|$IPTABLES -nvx -L vpnhotspot_acl
|
||||
|echo
|
||||
|echo logcat-su
|
||||
|logcat -d
|
||||
""".trimMargin())
|
||||
@@ -146,7 +150,8 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
|
||||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
when (preference.key) {
|
||||
UpstreamMonitor.KEY -> AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat().apply {
|
||||
UpstreamMonitor.KEY, FallbackUpstreamMonitor.KEY ->
|
||||
AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat().apply {
|
||||
setArguments(preference.key, try {
|
||||
NetworkInterface.getNetworkInterfaces().asSequence()
|
||||
.filter {
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.R
|
||||
import be.mygod.vpnhotspot.net.monitor.DefaultNetworkMonitor
|
||||
import be.mygod.vpnhotspot.net.monitor.FallbackUpstreamMonitor
|
||||
import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor
|
||||
import be.mygod.vpnhotspot.net.monitor.TrafficRecorder
|
||||
import be.mygod.vpnhotspot.net.monitor.UpstreamMonitor
|
||||
@@ -52,6 +52,8 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
||||
it.execQuiet("while $IPTABLES -D FORWARD -j vpnhotspot_fwd; do done")
|
||||
it.execQuiet("$IPTABLES -F vpnhotspot_fwd")
|
||||
it.execQuiet("$IPTABLES -X vpnhotspot_fwd")
|
||||
it.execQuiet("$IPTABLES -F vpnhotspot_acl")
|
||||
it.execQuiet("$IPTABLES -X vpnhotspot_acl")
|
||||
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 -X vpnhotspot_masquerade")
|
||||
@@ -120,17 +122,23 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
||||
*/
|
||||
inner class Subrouting(priority: Int, val upstream: String? = null) {
|
||||
val transaction = RootSession.beginTransaction().safeguard {
|
||||
if (upstream != null) ipRule("from all", downstream, upstream, priority)
|
||||
fun simpleMasquerade() {
|
||||
if (upstream != null) {
|
||||
ipRule("from all", downstream, upstream, priority)
|
||||
iptablesInsert("vpnhotspot_fwd -i $downstream -o $upstream -j vpnhotspot_acl")
|
||||
iptablesInsert("vpnhotspot_fwd -i $upstream -o $downstream -m state --state ESTABLISHED,RELATED -j vpnhotspot_acl")
|
||||
} else {
|
||||
iptablesInsert("vpnhotspot_fwd -i $downstream -j vpnhotspot_acl")
|
||||
iptablesInsert("vpnhotspot_fwd -o $downstream -m state --state ESTABLISHED,RELATED -j vpnhotspot_acl")
|
||||
}
|
||||
@TargetApi(28) when (masqueradeMode) {
|
||||
MasqueradeMode.None -> { } // nothing to be done here
|
||||
MasqueradeMode.Simple -> {
|
||||
// note: specifying -i wouldn't work for POSTROUTING
|
||||
iptablesAdd(if (upstream == null) "vpnhotspot_masquerade -s $hostSubnet -j MASQUERADE" else
|
||||
"vpnhotspot_masquerade -s $hostSubnet -o $upstream -j MASQUERADE", "nat")
|
||||
}
|
||||
@TargetApi(28) when (masqueradeMode) {
|
||||
MasqueradeMode.None -> { } // nothing to be done here
|
||||
MasqueradeMode.Simple -> simpleMasquerade()
|
||||
// fallback is only needed for repeater on API 23
|
||||
MasqueradeMode.Netd -> if (upstream == null) simpleMasquerade() else {
|
||||
MasqueradeMode.Netd -> {
|
||||
check(upstream != null) // fallback is only needed for repeater on API 23 < 28
|
||||
/**
|
||||
* 0 means that there are no interface addresses coming after, which is unused anyway.
|
||||
*
|
||||
@@ -166,7 +174,7 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
||||
override fun onLost() = synchronized(this@Routing) {
|
||||
val subrouting = subrouting ?: return
|
||||
// we could be removing fallback subrouting which no collision could ever happen, check before removing
|
||||
if (subrouting.upstream != null) check(upstreams.remove(subrouting.upstream))
|
||||
subrouting.upstream?.let { check(upstreams.remove(it)) }
|
||||
subrouting.transaction.revert()
|
||||
this.subrouting = null
|
||||
dns = emptyList()
|
||||
@@ -191,8 +199,8 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
||||
private inner class Client(private val ip: Inet4Address, mac: Long) : AutoCloseable {
|
||||
private val transaction = RootSession.beginTransaction().safeguard {
|
||||
val address = ip.hostAddress
|
||||
iptablesInsert("vpnhotspot_fwd -i $downstream -s $address -j ACCEPT")
|
||||
iptablesInsert("vpnhotspot_fwd -o $downstream -d $address -m state --state ESTABLISHED,RELATED -j ACCEPT")
|
||||
iptablesInsert("vpnhotspot_acl -i $downstream -s $address -j ACCEPT")
|
||||
iptablesInsert("vpnhotspot_acl -o $downstream -d $address -j ACCEPT")
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -261,6 +269,7 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
||||
|
||||
fun forward() {
|
||||
transaction.execQuiet("$IPTABLES -N vpnhotspot_fwd")
|
||||
transaction.execQuiet("$IPTABLES -N vpnhotspot_acl")
|
||||
transaction.iptablesInsert("FORWARD -j vpnhotspot_fwd")
|
||||
transaction.iptablesAdd("vpnhotspot_fwd -i $downstream ! -o $downstream -j DROP") // ensure blocking works
|
||||
// the real forwarding filters will be added in Subrouting when clients are connected
|
||||
@@ -306,15 +315,14 @@ class Routing(private val caller: Any, private val downstream: String) : IpNeigh
|
||||
|
||||
fun stop() {
|
||||
IpNeighbourMonitor.unregisterCallback(this)
|
||||
DefaultNetworkMonitor.unregisterCallback(fallbackUpstream)
|
||||
FallbackUpstreamMonitor.unregisterCallback(fallbackUpstream)
|
||||
UpstreamMonitor.unregisterCallback(upstream)
|
||||
}
|
||||
|
||||
fun commit(localOnly: Boolean = false) {
|
||||
fun commit() {
|
||||
transaction.commit()
|
||||
Timber.i("Started routing for $downstream by $caller")
|
||||
@TargetApi(28)
|
||||
if (localOnly || masqueradeMode != MasqueradeMode.Netd) DefaultNetworkMonitor.registerCallback(fallbackUpstream)
|
||||
FallbackUpstreamMonitor.registerCallback(fallbackUpstream)
|
||||
UpstreamMonitor.registerCallback(upstream)
|
||||
IpNeighbourMonitor.registerCallback(this)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package be.mygod.vpnhotspot.net.monitor
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
|
||||
abstract class FallbackUpstreamMonitor private constructor() : UpstreamMonitor() {
|
||||
companion object : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
const val KEY = "service.upstream.fallback"
|
||||
|
||||
init {
|
||||
app.pref.registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
private fun generateMonitor(): UpstreamMonitor {
|
||||
val upstream = app.pref.getString(KEY, null)
|
||||
return if (upstream.isNullOrEmpty()) DefaultNetworkMonitor else InterfaceMonitor(upstream)
|
||||
}
|
||||
private var monitor = generateMonitor()
|
||||
|
||||
fun registerCallback(callback: Callback) = synchronized(this) { monitor.registerCallback(callback) }
|
||||
fun unregisterCallback(callback: Callback) = synchronized(this) { monitor.unregisterCallback(callback) }
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
if (key == KEY) synchronized(this) {
|
||||
val old = monitor
|
||||
val callbacks = synchronized(old) {
|
||||
val callbacks = old.callbacks.toList()
|
||||
old.callbacks.clear()
|
||||
old.destroyLocked()
|
||||
callbacks
|
||||
}
|
||||
val new = generateMonitor()
|
||||
monitor = new
|
||||
for (callback in callbacks) {
|
||||
callback.onLost()
|
||||
new.registerCallback(callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ object TrafficRecorder {
|
||||
private fun doUpdate(timestamp: Long) {
|
||||
val oldRecords = LongSparseArray<TrafficRecord>()
|
||||
loop@ for (line in RootSession.use {
|
||||
val command = "$IPTABLES -nvx -L vpnhotspot_fwd"
|
||||
val command = "$IPTABLES -nvx -L vpnhotspot_acl"
|
||||
val result = it.execQuiet(command)
|
||||
val message = RootSession.checkOutput(command, result, false, false)
|
||||
if (result.err.isNotEmpty()) Timber.i(message)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M5,2c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v4L1,6v6h6L7,6L5,6L5,2zM9,16c0,1.3 0.84,2.4 2,2.82L11,23h2v-4.18c1.16,-0.41 2,-1.51 2,-2.82v-2L9,14v2zM1,16c0,1.3 0.84,2.4 2,2.82L3,23h2v-4.18C6.16,18.4 7,17.3 7,16v-2L1,14v2zM21,6L21,2c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v4h-2v6h6L23,6h-2zM13,2c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v4L9,6v6h6L15,6h-2L13,2zM17,16c0,1.3 0.84,2.4 2,2.82L19,23h2v-4.18c1.16,-0.41 2,-1.51 2,-2.82v-2h-6v2z"/>
|
||||
</vector>
|
||||
@@ -99,6 +99,8 @@
|
||||
<string name="settings_service_ip_monitor_poll_root">轮询 (root)</string>
|
||||
<string name="settings_service_upstream">上游网络接口</string>
|
||||
<string name="settings_service_upstream_auto">自动检测系统 VPN</string>
|
||||
<string name="settings_upstream_fallback">备用上游接口</string>
|
||||
<string name="settings_upstream_fallback_auto">自动检测系统默认网络</string>
|
||||
<string name="settings_service_clean">清理/重新应用路由规则</string>
|
||||
<string name="settings_service_clean_summary">将修改的设置应用到当前启用的服务上。也可用于修复偶尔会发生的竞态条件。</string>
|
||||
<string name="settings_service_dhcp_workaround">尝试修复 DHCP</string>
|
||||
|
||||
@@ -104,6 +104,8 @@
|
||||
<string name="settings_service_ip_monitor_poll_root">Poll with root</string>
|
||||
<string name="settings_service_upstream">Upstream network interface</string>
|
||||
<string name="settings_service_upstream_auto">Auto detect system VPN</string>
|
||||
<string name="settings_upstream_fallback">Fallback upstream interface</string>
|
||||
<string name="settings_upstream_fallback_auto">Auto detect system default network</string>
|
||||
<string name="settings_service_dhcp_workaround">Enable DHCP workaround</string>
|
||||
<string name="settings_service_dhcp_workaround_summary">Use this if clients cannot obtain IP addresses.</string>
|
||||
<string name="settings_service_clean">Clean/reapply routing rules</string>
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
app:icon="@drawable/ic_action_settings_ethernet"
|
||||
app:title="@string/settings_service_upstream"
|
||||
app:summary="@string/settings_service_upstream_auto"/>
|
||||
<be.mygod.vpnhotspot.preference.AlwaysAutoCompleteEditTextPreference
|
||||
app:key="service.upstream.fallback"
|
||||
app:icon="@drawable/ic_action_settings_input_component"
|
||||
app:title="@string/settings_upstream_fallback"
|
||||
app:summary="@string/settings_upstream_fallback_auto"/>
|
||||
<com.takisoft.preferencex.SimpleMenuPreference
|
||||
app:key="service.masqueradeMode"
|
||||
app:icon="@drawable/ic_social_people"
|
||||
|
||||
Reference in New Issue
Block a user