mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-10-08 10:56:13 -08:00
Configure one mobile VPN from running TUN instances
Gather addresses and routes from running instances in the GUI for VpnService. Attach its single fd to the core shared TUN and refresh the VPN when instance configuration changes. Keep the FFI set_tun_fd call scoped to one instance and report attachment errors. Cover mobile configuration and reconciliation in GUI tests.
This commit is contained in:
1 parent
cc2d58bb00
commit
de77efac60
11 files changed
+367
-317
No files matched your search
@@ -10,6 +10,7 @@ import android.os.ParcelFileDescriptor
|
||||
import android.os.Bundle
|
||||
import android.content.pm.ServiceInfo
|
||||
import androidx.core.app.NotificationCompat
|
||||
import android.system.OsConstants.AF_INET6
|
||||
import java.net.InetAddress
|
||||
import java.util.Arrays
|
||||
|
||||
@@ -20,10 +21,12 @@ class TauriVpnService : VpnService() {
|
||||
@JvmField var triggerCallback: (String, JSObject) -> Unit = { _, _ -> }
|
||||
@JvmField var self: TauriVpnService? = null
|
||||
@JvmField var ipv4Addr: String? = null
|
||||
@JvmField var ipv4Addrs: Array<String> = emptyArray()
|
||||
@JvmField var routes: Array<String> = emptyArray()
|
||||
@JvmField var dns: String? = null
|
||||
|
||||
const val IPV4_ADDR = "IPV4_ADDR"
|
||||
const val IPV4_ADDRS = "IPV4_ADDRS"
|
||||
const val ROUTES = "ROUTES"
|
||||
const val DNS = "DNS"
|
||||
const val DISALLOWED_APPLICATIONS = "DISALLOWED_APPLICATIONS"
|
||||
@@ -39,7 +42,8 @@ class TauriVpnService : VpnService() {
|
||||
println("vpn on start command ${intent?.getExtras()} $intent")
|
||||
startVpnForegroundService()
|
||||
var args = intent?.getExtras()
|
||||
ipv4Addr = args?.getString(IPV4_ADDR)
|
||||
ipv4Addrs = getIpv4Addrs(args)
|
||||
ipv4Addr = ipv4Addrs.firstOrNull()
|
||||
routes = args?.getStringArray(ROUTES) ?: emptyArray()
|
||||
dns = args?.getString(DNS)
|
||||
|
||||
@@ -90,6 +94,7 @@ class TauriVpnService : VpnService() {
|
||||
|
||||
private fun clearStatus() {
|
||||
ipv4Addr = null
|
||||
ipv4Addrs = emptyArray()
|
||||
routes = emptyArray()
|
||||
dns = null
|
||||
}
|
||||
@@ -159,25 +164,40 @@ class TauriVpnService : VpnService() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getIpv4Addrs(args: Bundle?): Array<String> {
|
||||
val ipv4Addrs = args
|
||||
?.getStringArray(IPV4_ADDRS)
|
||||
?.filter { it.isNotBlank() }
|
||||
?.toTypedArray()
|
||||
?: emptyArray()
|
||||
if (ipv4Addrs.isNotEmpty()) {
|
||||
return ipv4Addrs
|
||||
}
|
||||
|
||||
return arrayOf(args?.getString(IPV4_ADDR) ?: "10.126.126.1/24")
|
||||
}
|
||||
|
||||
private fun createVpnInterface(args: Bundle?): ParcelFileDescriptor {
|
||||
var builder = Builder()
|
||||
.setSession("TauriVpnService")
|
||||
.setBlocking(false)
|
||||
|
||||
var mtu = args?.getInt(MTU) ?: 1500
|
||||
var ipv4Addr = args?.getString(IPV4_ADDR) ?: "10.126.126.1/24"
|
||||
var ipv4Addrs = getIpv4Addrs(args)
|
||||
var dns: String? = args?.getString(DNS)
|
||||
var routes = args?.getStringArray(ROUTES) ?: emptyArray()
|
||||
var disallowedApplications = args?.getStringArray(DISALLOWED_APPLICATIONS) ?: emptyArray()
|
||||
|
||||
println("vpn create vpn interface. mtu: $mtu, ipv4Addr: $ipv4Addr, dns:" +
|
||||
println("vpn create vpn interface. mtu: $mtu, ipv4Addrs: ${java.util.Arrays.toString(ipv4Addrs)}, dns:" +
|
||||
"$dns, routes: ${java.util.Arrays.toString(routes)}," +
|
||||
"disallowedApplications: ${java.util.Arrays.toString(disallowedApplications)}")
|
||||
|
||||
val ipParts = ipv4Addr.split("/")
|
||||
if (ipParts.size != 2) throw IllegalArgumentException("Invalid IP addr string")
|
||||
builder.addAddress(ipParts[0], ipParts[1].toInt())
|
||||
builder.addAddress("fd00::1", 128)
|
||||
for (ipv4Addr in ipv4Addrs) {
|
||||
val ipParts = ipv4Addr.split("/")
|
||||
if (ipParts.size != 2) throw IllegalArgumentException("Invalid IP addr string")
|
||||
builder.addAddress(ipParts[0], ipParts[1].toInt())
|
||||
}
|
||||
builder.allowFamily(AF_INET6)
|
||||
|
||||
builder.setMtu(mtu)
|
||||
dns?.let { builder.addDnsServer(it) }
|
||||
|
||||
@@ -12,6 +12,7 @@ import app.tauri.plugin.Invoke
|
||||
import app.tauri.plugin.JSObject
|
||||
import app.tauri.plugin.Plugin
|
||||
import android.webkit.WebView
|
||||
import org.json.JSONArray
|
||||
|
||||
@InvokeArg
|
||||
class PingArgs {
|
||||
@@ -21,6 +22,7 @@ class PingArgs {
|
||||
@InvokeArg
|
||||
class StartVpnArgs {
|
||||
var ipv4Addr: String? = null
|
||||
var ipv4Addrs: Array<String> = emptyArray()
|
||||
var routes: Array<String> = emptyArray()
|
||||
var dns: String? = null
|
||||
var disallowedApplications: Array<String> = emptyArray()
|
||||
@@ -106,6 +108,7 @@ class VpnServicePlugin(private val activity: Activity) : Plugin(activity) {
|
||||
} else {
|
||||
val intent = Intent(activity, TauriVpnService::class.java)
|
||||
intent.putExtra(TauriVpnService.IPV4_ADDR, args.ipv4Addr)
|
||||
intent.putExtra(TauriVpnService.IPV4_ADDRS, args.ipv4Addrs)
|
||||
intent.putExtra(TauriVpnService.ROUTES, args.routes)
|
||||
intent.putExtra(TauriVpnService.DNS, args.dns)
|
||||
intent.putExtra(TauriVpnService.DISALLOWED_APPLICATIONS, args.disallowedApplications)
|
||||
@@ -137,7 +140,8 @@ class VpnServicePlugin(private val activity: Activity) : Plugin(activity) {
|
||||
val ret = JSObject()
|
||||
ret.put("running", TauriVpnService.self != null)
|
||||
ret.put("ipv4Addr", TauriVpnService.ipv4Addr)
|
||||
ret.put("routes", TauriVpnService.routes)
|
||||
ret.put("ipv4Addrs", JSONArray(TauriVpnService.ipv4Addrs))
|
||||
ret.put("routes", JSONArray(TauriVpnService.routes))
|
||||
ret.put("dns", TauriVpnService.dns)
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export interface InvokeResponse {
|
||||
|
||||
export interface StartVpnRequest {
|
||||
ipv4Addr?: string;
|
||||
ipv4Addrs?: string[];
|
||||
routes?: string[];
|
||||
dns?: string;
|
||||
disallowedApplications?: string[];
|
||||
@@ -24,6 +25,7 @@ export interface StartVpnRequest {
|
||||
export interface VpnStatusResponse {
|
||||
running: boolean;
|
||||
ipv4Addr?: string;
|
||||
ipv4Addrs?: string[];
|
||||
routes?: string[];
|
||||
dns?: string;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ pub struct VoidRequest {}
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StartVpnRequest {
|
||||
pub ipv4_addr: Option<String>,
|
||||
pub ipv4_addrs: Option<Vec<String>>,
|
||||
pub routes: Option<Vec<String>>,
|
||||
pub dns: Option<String>,
|
||||
pub disallowed_applications: Option<Vec<String>>,
|
||||
@@ -39,6 +40,7 @@ pub struct Status {
|
||||
pub struct VpnStatus {
|
||||
pub running: bool,
|
||||
pub ipv4_addr: Option<String>,
|
||||
pub ipv4_addrs: Option<Vec<String>>,
|
||||
pub routes: Option<Vec<String>>,
|
||||
pub dns: Option<String>,
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user