Add split tunneling
This commit is contained in:
parent
20f3c0388a
commit
e7658f9859
14 changed files with 422 additions and 104 deletions
|
|
@ -12,14 +12,20 @@ import java.io.File
|
|||
import java.io.FileOutputStream
|
||||
import java.util.zip.ZipFile
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import org.amnezia.vpn.util.InetNetwork
|
||||
import org.amnezia.vpn.util.Log
|
||||
import org.amnezia.vpn.util.net.InetNetwork
|
||||
import org.amnezia.vpn.util.net.IpRange
|
||||
import org.amnezia.vpn.util.net.IpRangeSet
|
||||
import org.json.JSONObject
|
||||
|
||||
private const val TAG = "Protocol"
|
||||
|
||||
const val VPN_SESSION_NAME = "AmneziaVPN"
|
||||
|
||||
private const val SPLIT_TUNNEL_DISABLE = 0
|
||||
private const val SPLIT_TUNNEL_INCLUDE = 1
|
||||
private const val SPLIT_TUNNEL_EXCLUDE = 2
|
||||
|
||||
abstract class Protocol {
|
||||
|
||||
abstract val statistics: Statistics
|
||||
|
|
@ -33,6 +39,47 @@ abstract class Protocol {
|
|||
|
||||
abstract fun stopVpn()
|
||||
|
||||
protected fun ProtocolConfig.Builder.configSplitTunnel(config: JSONObject) {
|
||||
val splitTunnelType = config.optInt("splitTunnelType")
|
||||
if (splitTunnelType == SPLIT_TUNNEL_DISABLE) return
|
||||
val splitTunnelSites = config.getJSONArray("splitTunnelSites")
|
||||
when (splitTunnelType) {
|
||||
SPLIT_TUNNEL_INCLUDE -> {
|
||||
// remove default routes, if any
|
||||
removeRoute(InetNetwork("0.0.0.0", 0))
|
||||
removeRoute(InetNetwork("::", 0))
|
||||
// add routes from config
|
||||
for (i in 0 until splitTunnelSites.length()) {
|
||||
val address = InetNetwork.parse(splitTunnelSites.getString(i))
|
||||
addRoute(address)
|
||||
}
|
||||
}
|
||||
|
||||
SPLIT_TUNNEL_EXCLUDE -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
// exclude routes from config
|
||||
for (i in 0 until splitTunnelSites.length()) {
|
||||
val address = InetNetwork.parse(splitTunnelSites.getString(i))
|
||||
excludeRoute(address)
|
||||
}
|
||||
} else {
|
||||
// For older versions of Android, build a list of subnets without excluded addresses
|
||||
val ipRangeSet = IpRangeSet()
|
||||
ipRangeSet.remove(IpRange("127.0.0.0", 8))
|
||||
for (i in 0 until splitTunnelSites.length()) {
|
||||
val address = InetNetwork.parse(splitTunnelSites.getString(i))
|
||||
ipRangeSet.remove(IpRange(address))
|
||||
}
|
||||
// remove default routes, if any
|
||||
removeRoute(InetNetwork("0.0.0.0", 0))
|
||||
removeRoute(InetNetwork("::", 0))
|
||||
ipRangeSet.subnets().forEach(::addRoute)
|
||||
addRoute(InetNetwork("2000::", 3))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun buildVpnInterface(config: ProtocolConfig, vpnBuilder: Builder) {
|
||||
vpnBuilder.setSession(VPN_SESSION_NAME)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package org.amnezia.vpn.protocol
|
||||
|
||||
import android.net.ProxyInfo
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import java.net.InetAddress
|
||||
import org.amnezia.vpn.util.InetNetwork
|
||||
import org.amnezia.vpn.util.net.InetNetwork
|
||||
|
||||
open class ProtocolConfig protected constructor(
|
||||
val addresses: Set<InetNetwork>,
|
||||
|
|
@ -62,13 +64,19 @@ open class ProtocolConfig protected constructor(
|
|||
|
||||
fun addRoute(route: InetNetwork) = apply { this.routes += route }
|
||||
fun addRoutes(routes: List<InetNetwork>) = apply { this.routes += routes }
|
||||
fun removeRoute(route: InetNetwork) = apply { this.routes.remove(route) }
|
||||
fun clearRoutes() = apply { this.routes.clear() }
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
fun excludeRoute(route: InetNetwork) = apply { this.excludedRoutes += route }
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
fun excludeRoutes(routes: List<InetNetwork>) = apply { this.excludedRoutes += routes }
|
||||
|
||||
fun excludeApplication(application: String) = apply { this.excludedApplications += application }
|
||||
fun excludeApplications(applications: List<String>) = apply { this.excludedApplications += applications }
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
fun setHttpProxy(httpProxy: ProxyInfo) = apply { this.httpProxy = httpProxy }
|
||||
|
||||
fun setAllowAllAF(allowAllAF: Boolean) = apply { this.allowAllAF = allowAllAF }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue