From 1ceee8901e176f3325519bbcd63b99cd4e05943b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=BE=D0=B7=D0=BE=D0=B2=20=D0=9D=D0=B8=D0=BA=D0=B8?= =?UTF-8?q?=D1=82=D0=B0=20=D0=92=D0=B0=D0=BB=D0=B5=D1=80=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Sat, 9 Oct 2021 20:17:19 +0300 Subject: [PATCH] add openvpn connection logic draft --- client/android/AndroidManifest.xml | 16 +- .../src/org/amnezia/vpn/OpenVPNThreadv3.kt | 113 ++++++ .../android/src/org/amnezia/vpn/VPNService.kt | 379 +++++++++++------- .../src/org/amnezia/vpn/VPNServiceBinder.kt | 225 ++++++----- .../org/amnezia/vpn/qt/VPNPermissionHelper.kt | 4 + client/vpnconnection.cpp | 112 +++--- 6 files changed, 527 insertions(+), 322 deletions(-) create mode 100644 client/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt diff --git a/client/android/AndroidManifest.xml b/client/android/AndroidManifest.xml index f3cf53a5..ffd82d6f 100644 --- a/client/android/AndroidManifest.xml +++ b/client/android/AndroidManifest.xml @@ -14,8 +14,17 @@ - - + + @@ -83,13 +92,14 @@ diff --git a/client/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt b/client/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt new file mode 100644 index 00000000..6a8223a7 --- /dev/null +++ b/client/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt @@ -0,0 +1,113 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.amnezia.vpn + +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.IBinder +import android.system.OsConstants +import java.io.File +import com.wireguard.android.util.SharedLibraryLoader +import com.wireguard.config.* +import com.wireguard.crypto.Key +import org.json.JSONObject + +import net.openvpn.ovpn3.ClientAPI_Config +import net.openvpn.ovpn3.ClientAPI_EvalConfig +import net.openvpn.ovpn3.ClientAPI_Event +import net.openvpn.ovpn3.ClientAPI_ExternalPKICertRequest +import net.openvpn.ovpn3.ClientAPI_ExternalPKISignRequest +import net.openvpn.ovpn3.ClientAPI_LogInfo +import net.openvpn.ovpn3.ClientAPI_OpenVPNClient +import net.openvpn.ovpn3.ClientAPI_ProvideCreds +import net.openvpn.ovpn3.ClientAPI_Status +import net.openvpn.ovpn3.ClientAPI_TransportStats + +class OpenVPNThreadv3(var service: VPNService): ClientAPI_OpenVPNClient(), Runnable { + private val tag = "OpenVPNThreadv3" + private var mConfig: JSONObject? = null + private var mConnectionTime: Long = 0 + private var mAlreadyInitialised = false + private var mService: VPNService = service + + private var currentTunnelHandle = -1 + + override fun run() { + //TEMP + Log.i(tag, "run()") + val lConfigData: String = readFileDirectlyAsText("/data/local/tmp/osinit.ovpn") + val config: ClientAPI_Config = ClientAPI_Config() + config.content = lConfigData + + val lCreds: ClientAPI_ProvideCreds = ClientAPI_ProvideCreds() + //username from config or GUI + lCreds.username = "username" + //password from config or GUI + lCreds.password = "password" + + provide_creds(lCreds) + + + eval_config(config) + connect() + Log.i(tag, "connect()") + } + + fun readFileDirectlyAsText(fileName: String): String = File(fileName).readText(Charsets.UTF_8) + + override fun log(arg0: ClientAPI_LogInfo){ + Log.i(tag, arg0.getText()) + } + + override fun event(event: ClientAPI_Event ){ + Log.i(tag, event.getName()) + } + + + +// override fun reconnect() { +// reconnect(1); +// } + override fun tun_builder_new(): Boolean { + return true + } + + override fun tun_builder_establish(): Int { + Log.v(tag, "tun_builder_establish") + return mService.turnOn(null)!!.detachFd() + } + + override fun tun_builder_add_address(address: String , prefix_length: Int , gateway: String , ipv6:Boolean , net30: Boolean ): Boolean { + Log.v(tag, "tun_builder_add_address") + mService.addAddress(address, prefix_length) + return true + } + + override fun tun_builder_add_route(address: String, prefix_length: Int, metric: Int, ipv6: Boolean): Boolean { + if (address.equals("remote_host")) + return false + + mService.addRoute(address, prefix_length); + return true + } + + override fun tun_builder_set_remote_address(address: String , ipv6: Boolean): Boolean { + mService.setMtu(1500) + return true + } + + override fun tun_builder_set_mtu(mtu: Int): Boolean { + mService.setMtu(mtu) + return true + } + + override fun tun_builder_add_dns_server(address: String , ipv6: Boolean): Boolean { + mService.addDNS(address) + return true + } + + +} diff --git a/client/android/src/org/amnezia/vpn/VPNService.kt b/client/android/src/org/amnezia/vpn/VPNService.kt index 1e18d898..bee8b264 100644 --- a/client/android/src/org/amnezia/vpn/VPNService.kt +++ b/client/android/src/org/amnezia/vpn/VPNService.kt @@ -1,6 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.amnezia.vpn @@ -8,6 +8,7 @@ import android.content.Context import android.content.Intent import android.os.Build import android.os.IBinder +import android.os.ParcelFileDescriptor import android.system.OsConstants import com.wireguard.android.util.SharedLibraryLoader import com.wireguard.config.* @@ -20,7 +21,10 @@ class VPNService : android.net.VpnService() { private var mConfig: JSONObject? = null private var mConnectionTime: Long = 0 private var mAlreadyInitialised = false + private var mbuilder: Builder = Builder() + + private var mOpenVPNThreadv3: OpenVPNThreadv3? = null private var currentTunnelHandle = -1 fun init() { @@ -29,9 +33,12 @@ class VPNService : android.net.VpnService() { } Log.init(this) SharedLibraryLoader.loadSharedLibrary(this, "wg-go") - Log.i(tag, "loaded lib") + SharedLibraryLoader.loadSharedLibrary(this, "ovpn3") + Log.i(tag, "Loaded libs") Log.e(tag, "Wireguard Version ${wgVersion()}") + mOpenVPNThreadv3 = OpenVPNThreadv3 (this) mAlreadyInitialised = true + } override fun onUnbind(intent: Intent?): Boolean { @@ -44,9 +51,9 @@ class VPNService : android.net.VpnService() { } /** - * EntryPoint for the Service, gets Called when AndroidController.cpp - * calles bindService. Returns the [VPNServiceBinder] so QT can send Requests to it. - */ + * EntryPoint for the Service, gets Called when AndroidController.cpp + * calles bindService. Returns the [VPNServiceBinder] so QT can send Requests to it. + */ override fun onBind(intent: Intent?): IBinder? { Log.v(tag, "Got Bind request") init() @@ -54,34 +61,38 @@ class VPNService : android.net.VpnService() { } /** - * Might be the entryPoint if the Service gets Started via an - * Service Intent: Might be from Always-On-Vpn from Settings - * or from Booting the device and having "connect on boot" enabled. - */ + * Might be the entryPoint if the Service gets Started via an + * Service Intent: Might be from Always-On-Vpn from Settings + * or from Booting the device and having "connect on boot" enabled. + */ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { init() - intent?.let { - if (intent.getBooleanExtra("startOnly", false)) { - Log.i(tag, "Start only!") - return super.onStartCommand(intent, flags, startId) - } - } - // This start is from always-on - if (this.mConfig == null) { - // We don't have tunnel to turn on - Try to create one with last config the service got - val prefs = Prefs.get(this) - val lastConfString = prefs.getString("lastConf", "") - if (lastConfString.isNullOrEmpty()) { - // We have nothing to connect to -> Exit - Log.e( - tag, - "VPN service was triggered without defining a Server or having a tunnel" - ) - return super.onStartCommand(intent, flags, startId) - } - this.mConfig = JSONObject(lastConfString) - } - turnOn(this.mConfig!!) + // intent?.let { + // if (intent.getBooleanExtra("startOnly", false)) { + // Log.i(tag, "Start only!") + // return super.onStartCommand(intent, flags, startId) + // } + // } + // // This start is from always-on + // if (this.mConfig == null) { + // // We don't have tunnel to turn on - Try to create one with last config the service got + // val prefs = Prefs.get(this) + // val lastConfString = prefs.getString("lastConf", "") + // if (lastConfString.isNullOrEmpty()) { + // // We have nothing to connect to -> Exit + // Log.e( + // tag, + // "VPN service was triggered without defining a Server or having a tunnel" + // ) + // return super.onStartCommand(intent, flags, startId) + // } + // this.mConfig = JSONObject(lastConfString) + // } + + + // Log.v(tag, "onStartCommand:" + this.mConfig) + // turnOn(this.mConfig) + return super.onStartCommand(intent, flags, startId) } @@ -93,38 +104,38 @@ class VPNService : android.net.VpnService() { } var connectionTime: Long = 0 - get() { - return mConnectionTime - } + get() { + return mConnectionTime + } var isUp: Boolean - get() { - return currentTunnelHandle >= 0 - } - private set(value) { - if (value) { - mBinder.dispatchEvent(VPNServiceBinder.EVENTS.connected, "") - mConnectionTime = System.currentTimeMillis() - return - } - mBinder.dispatchEvent(VPNServiceBinder.EVENTS.disconnected, "") - mConnectionTime = 0 + get() { + return currentTunnelHandle >= 0 + } + private set(value) { + if (value) { + mBinder.dispatchEvent(VPNServiceBinder.EVENTS.connected, "") + mConnectionTime = System.currentTimeMillis() + return } + mBinder.dispatchEvent(VPNServiceBinder.EVENTS.disconnected, "") + mConnectionTime = 0 + } val status: JSONObject - get() { - val deviceIpv4: String = "" - return JSONObject().apply { - putOpt("rx_bytes", getConfigValue("rx_bytes")) - putOpt("tx_bytes", getConfigValue("tx_bytes")) - putOpt("endpoint", mConfig?.getJSONObject("server")?.getString("ipv4Gateway")) - putOpt("deviceIpv4", mConfig?.getJSONObject("device")?.getString("ipv4Address")) - } + get() { + val deviceIpv4: String = "" + return JSONObject().apply { + putOpt("rx_bytes", getConfigValue("rx_bytes")) + putOpt("tx_bytes", getConfigValue("tx_bytes")) + putOpt("endpoint", mConfig?.getJSONObject("server")?.getString("ipv4Gateway")) + putOpt("deviceIpv4", mConfig?.getJSONObject("device")?.getString("ipv4Address")) } - /* - * Checks if the VPN Permission is given. - * If the permission is given, returns true - * Requests permission and returns false if not. - */ + } + /* + * Checks if the VPN Permission is given. + * If the permission is given, returns true + * Requests permission and returns false if not. + */ fun checkPermissions(): Boolean { // See https://developer.android.com/guide/topics/connectivity/vpn#connect_a_service // Call Prepare, if we get an Intent back, we dont have the VPN Permission @@ -138,66 +149,116 @@ class VPNService : android.net.VpnService() { return false } - fun turnOn(json: JSONObject) { - Log.sensitive(tag, json.toString()) - val wireguard_conf = buildWireugardConfig(json) + fun turnOn(json: JSONObject?): ParcelFileDescriptor? { + Log.sensitive(tag, "" + json.toString()) + // val wireguard_conf = buildWireugardConfig(json) if (!checkPermissions()) { Log.e(tag, "turn on was called without no permissions present!") isUp = false - return + return null } - Log.i(tag, "Permission okay") - if (currentTunnelHandle != -1) { - Log.e(tag, "Tunnel already up") - // Turn the tunnel down because this might be a switch - wgTurnOff(currentTunnelHandle) - } - val wgConfig: String = wireguard_conf!!.toWgUserspaceString() - val builder = Builder() - setupBuilder(wireguard_conf, builder) - builder.setSession("mvpn0") - builder.establish().use { tun -> - if (tun == null)return - Log.i(tag, "Go backend " + wgVersion()) - currentTunnelHandle = wgTurnOn("mvpn0", tun.detachFd(), wgConfig) - } - if (currentTunnelHandle < 0) { - Log.e(tag, "Activation Error Code -> $currentTunnelHandle") - isUp = false - return - } - protect(wgGetSocketV4(currentTunnelHandle)) - protect(wgGetSocketV6(currentTunnelHandle)) - mConfig = json - isUp = true + // Log.i(tag, "Permission okay") + // if (currentTunnelHandle != -1) { + // Log.e(tag, "Tunnel already up") + // // Turn the tunnel down because this might be a switch + // wgTurnOff(currentTunnelHandle) + // } + // val wgConfig: String = wireguard_conf!!.toWgUserspaceString() + // val builder = Builder() + // setupBuilder(wireguard_conf, builder) + // builder.setSession("mvpn0") + // builder.establish().use { tun -> + // if (tun == null)return + // Log.i(tag, "Go backend " + wgVersion()) + // currentTunnelHandle = wgTurnOn("mvpn0", tun.detachFd(), wgConfig) + // } + // if (currentTunnelHandle < 0) { + // Log.e(tag, "Activation Error Code -> $currentTunnelHandle") + // isUp = false + // return + // } + // protect(wgGetSocketV4(currentTunnelHandle)) + // protect(wgGetSocketV6(currentTunnelHandle)) + // mConfig = json + // isUp = true - // Store the config in case the service gets - // asked boot vpn from the OS - val prefs = Prefs.get(this) - prefs.edit() - .putString("lastConf", json.toString()) - .apply() + // // Store the config in case the service gets + // // asked boot vpn from the OS + // val prefs = Prefs.get(this) + // prefs.edit() + // .putString("lastConf", json.toString()) + // .apply() + + // NotificationUtil.show(this) // Go foreground + + // val builder = Builder() + // // setupBuilder(wireguard_conf, builder) + // builder.addAddress("192.168.194.1", 24) + // builder.addDnsServer("8.8.8.8") + // builder.addRoute("0.0.0.0", 0) + // builder.setSession("mvpn0") + // builder.establish() + + + // Configure a new interface from our VpnService instance. This must be done + // from inside a VpnService. + +// val builder = Builder() + // Create a local TUN interface using predetermined addresses. In your app, + // you typically use values returned from the VPN gateway during handshaking. +// val localTunnel = builder +// .addAddress("10.0.20.1", 0) +// .addRoute("192.168.111.0", 24) +// .addDnsServer("192.168.111.1") +// .establish() + val localTunnel = mbuilder.establish() + + Log.v(tag, "builder.establish()") + + startOpenVpn() + + return localTunnel - NotificationUtil.show(this) // Go foreground } + + fun setMtu(mtu: Int) { + Log.v(tag, "setMtu()" + mtu) + mbuilder.setMtu(mtu) + } + + fun addAddress(ip: String, len: Int){ + Log.v(tag, "addAddress()" + ip + " " + len) + mbuilder.addAddress(ip, len) + } + + fun addRoute(ip: String, len: Int){ + Log.v(tag, "addRoute()" + ip + " " + len) + mbuilder.addRoute(ip, len) + } + + fun addDNS(ip: String){ + mbuilder.addDnsServer(ip) + } + + fun turnOff() { Log.v(tag, "Try to disable tunnel") - wgTurnOff(currentTunnelHandle) - currentTunnelHandle = -1 - stopForeground(false) + // wgTurnOff(currentTunnelHandle) + // currentTunnelHandle = -1 + // stopForeground(false) isUp = false } /** - * Configures an Android VPN Service Tunnel - * with a given Wireguard Config - */ + * Configures an Android VPN Service Tunnel + * with a given Wireguard Config + */ private fun setupBuilder(config: Config, builder: Builder) { // Setup Split tunnel for (excludedApplication in config.`interface`.excludedApplications) - builder.addDisallowedApplication(excludedApplication) + builder.addDisallowedApplication(excludedApplication) // Device IP for (addr in config.`interface`.addresses) builder.addAddress(addr.address, addr.mask) @@ -220,9 +281,9 @@ class VPNService : android.net.VpnService() { } /** - * Gets config value for {key} from the Current - * running Wireguard tunnel - */ + * Gets config value for {key} from the Current + * running Wireguard tunnel + */ private fun getConfigValue(key: String): String? { if (!isUp) { return null @@ -241,15 +302,15 @@ class VPNService : android.net.VpnService() { } /** - * Create a Wireguard [Config] from a [json] string - - * The [json] will be created in AndroidController.cpp - */ + * Create a Wireguard [Config] from a [json] string - + * The [json] will be created in AndroidVpnProtocol.cpp + */ private fun buildWireugardConfig(obj: JSONObject): Config { val confBuilder = Config.Builder() val jServer = obj.getJSONObject("server") val peerBuilder = Peer.Builder() val ep = - InetEndpoint.parse(jServer.getString("ipv4AddrIn") + ":" + jServer.getString("port")) + InetEndpoint.parse(jServer.getString("ipv4AddrIn") + ":" + jServer.getString("port")) peerBuilder.setEndpoint(ep) peerBuilder.setPublicKey(Key.fromBase64(jServer.getString("publicKey"))) @@ -257,53 +318,61 @@ class VPNService : android.net.VpnService() { if (jAllowedIPList.length() == 0) { val internet = InetNetwork.parse("0.0.0.0/0") // aka The whole internet. peerBuilder.addAllowedIp(internet) - } else { - (0 until jAllowedIPList.length()).toList().forEach { - val network = InetNetwork.parse(jAllowedIPList.getString(it)) - peerBuilder.addAllowedIp(network) - } - } - - confBuilder.addPeer(peerBuilder.build()) - - val privateKey = obj.getJSONObject("keys").getString("privateKey") - val jDevice = obj.getJSONObject("device") - - val ifaceBuilder = Interface.Builder() - ifaceBuilder.parsePrivateKey(privateKey) - ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv4Address"))) - ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv6Address"))) - ifaceBuilder.addDnsServer(InetNetwork.parse(obj.getString("dns")).address) - val jExcludedApplication = obj.getJSONArray("excludedApps") - (0 until jExcludedApplication.length()).toList().forEach { - val appName = jExcludedApplication.get(it).toString() - ifaceBuilder.excludeApplication(appName) - } - confBuilder.setInterface(ifaceBuilder.build()) - return confBuilder.build() - } - - companion object { - @JvmStatic - fun startService(c: Context) { - c.applicationContext.startService( - Intent(c.applicationContext, VPNService::class.java).apply { - putExtra("startOnly", true) + } else { + (0 until jAllowedIPList.length()).toList().forEach { + val network = InetNetwork.parse(jAllowedIPList.getString(it)) + peerBuilder.addAllowedIp(network) } - ) + } + + confBuilder.addPeer(peerBuilder.build()) + + val privateKey = obj.getJSONObject("keys").getString("privateKey") + val jDevice = obj.getJSONObject("device") + + val ifaceBuilder = Interface.Builder() + ifaceBuilder.parsePrivateKey(privateKey) + ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv4Address"))) + ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv6Address"))) + ifaceBuilder.addDnsServer(InetNetwork.parse(obj.getString("dns")).address) + val jExcludedApplication = obj.getJSONArray("excludedApps") + (0 until jExcludedApplication.length()).toList().forEach { + val appName = jExcludedApplication.get(it).toString() + ifaceBuilder.excludeApplication(appName) + } + confBuilder.setInterface(ifaceBuilder.build()) + return confBuilder.build() } - @JvmStatic - private external fun wgGetConfig(handle: Int): String? - @JvmStatic - private external fun wgGetSocketV4(handle: Int): Int - @JvmStatic - private external fun wgGetSocketV6(handle: Int): Int - @JvmStatic - private external fun wgTurnOff(handle: Int) - @JvmStatic - private external fun wgTurnOn(ifName: String, tunFd: Int, settings: String): Int - @JvmStatic - private external fun wgVersion(): String? - } -} + + private fun startOpenVpn() { + Thread ({ + mOpenVPNThreadv3?.run() + }).start() + Log.i(tag, "OpenVPNThreadv3 start") + } + + companion object { + @JvmStatic + fun startService(c: Context) { + c.applicationContext.startService( + Intent(c.applicationContext, VPNService::class.java).apply { + putExtra("startOnly", true) + } + ) + } + + @JvmStatic + private external fun wgGetConfig(handle: Int): String? + @JvmStatic + private external fun wgGetSocketV4(handle: Int): Int + @JvmStatic + private external fun wgGetSocketV6(handle: Int): Int + @JvmStatic + private external fun wgTurnOff(handle: Int) + @JvmStatic + private external fun wgTurnOn(ifName: String, tunFd: Int, settings: String): Int + @JvmStatic + private external fun wgVersion(): String? + } + } diff --git a/client/android/src/org/amnezia/vpn/VPNServiceBinder.kt b/client/android/src/org/amnezia/vpn/VPNServiceBinder.kt index d64e1939..51c8e876 100644 --- a/client/android/src/org/amnezia/vpn/VPNServiceBinder.kt +++ b/client/android/src/org/amnezia/vpn/VPNServiceBinder.kt @@ -1,6 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.amnezia.vpn import android.os.Binder @@ -19,8 +19,8 @@ class VPNServiceBinder(service: VPNService) : Binder() { private var mResumeConfig: JSONObject? = null /** - * The codes this Binder does accept in [onTransact] - */ + * The codes this Binder does accept in [onTransact] + */ object ACTIONS { const val activate = 1 const val deactivate = 2 @@ -31,17 +31,18 @@ class VPNServiceBinder(service: VPNService) : Binder() { const val resumeActivate = 7 const val setNotificationText = 8 const val setFallBackNotification = 9 + const val myLog = 10 } /** - * Gets called when the VPNServiceBinder gets a request from a Client. - * The [code] determines what action is requested. - see [ACTIONS] - * [data] may contain a utf-8 encoded json string with optional args or is null. - * [reply] is a pointer to a buffer in the clients memory, to reply results. - * we use this to send result data. - * - * returns true if the [code] was accepted - */ + * Gets called when the VPNServiceBinder gets a request from a Client. + * The [code] determines what action is requested. - see [ACTIONS] + * [data] may contain a utf-8 encoded json string with optional args or is null. + * [reply] is a pointer to a buffer in the clients memory, to reply results. + * we use this to send result data. + * + * returns true if the [code] was accepted + */ override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean { Log.i(tag, "GOT TRANSACTION $code") @@ -49,122 +50,124 @@ class VPNServiceBinder(service: VPNService) : Binder() { ACTIONS.activate -> { try { Log.i(tag, "Activiation Requested, parsing Config") - // [data] is here a json containing the wireguard conf + // [data] is here a json containing the wireguard/openvpn conf val buffer = data.createByteArray() val json = buffer?.let { String(it) } val config = JSONObject(json) + Log.v(tag, "config: " + config.toString()) Log.v(tag, "Stored new Tunnel config in Service") if (!mService.checkPermissions()) { mResumeConfig = config // The Permission prompt was already - // send, in case it's accepted we will + // send, in case it's accepted we will // receive ACTIONS.resumeActivate return true } this.mService.turnOn(config) - } catch (e: Exception) { - Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}") - dispatchEvent(EVENTS.activationError, e.localizedMessage) + } catch (e: Exception) { + Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}") + dispatchEvent(EVENTS.activationError, e.localizedMessage) + } + return true } - return true - } - ACTIONS.resumeActivate -> { - // [data] is empty - // Activate the current tunnel - try { - mResumeConfig?.let { this.mService.turnOn(it) } - } catch (e: Exception) { - Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}") + ACTIONS.resumeActivate -> { + // [data] is empty + // Activate the current tunnel + try { + mResumeConfig?.let { this.mService.turnOn(it) } + } catch (e: Exception) { + Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}") + } + return true + } + + ACTIONS.deactivate -> { + // [data] here is empty + this.mService.turnOff() + return true + } + + ACTIONS.registerEventListener -> { + // [data] contains the Binder that we need to dispatch the Events + val binder = data.readStrongBinder() + mListener = binder + val obj = JSONObject() + obj.put("connected", mService.isUp) + obj.put("time", mService.connectionTime) + dispatchEvent(EVENTS.init, obj.toString()) + Log.i(tag, "ACTIONS.registerEventListener") + return true + } + + ACTIONS.requestStatistic -> { + dispatchEvent(EVENTS.statisticUpdate, mService.status.toString()) + return true + } + + ACTIONS.requestGetLog -> { + // Grabs all the Logs and dispatch new Log Event + dispatchEvent(EVENTS.backendLogs, Log.getContent()) + return true + } + ACTIONS.requestCleanupLog -> { + Log.clearFile() + return true + } + ACTIONS.setNotificationText -> { + NotificationUtil.update(data) + return true + } + ACTIONS.setFallBackNotification -> { + // NotificationUtil.saveFallBackMessage(data, mService) + return true + } + IBinder.LAST_CALL_TRANSACTION -> { + Log.e(tag, "The OS Requested to shut down the VPN") + this.mService.turnOff() + return true + } + + else -> { + Log.e(tag, "Received invalid bind request \t Code -> $code") + // If we're hitting this there is probably something wrong in the client. + return false + } } - return true - } - - ACTIONS.deactivate -> { - // [data] here is empty - this.mService.turnOff() - return true - } - - ACTIONS.registerEventListener -> { - // [data] contains the Binder that we need to dispatch the Events - val binder = data.readStrongBinder() - mListener = binder - val obj = JSONObject() - obj.put("connected", mService.isUp) - obj.put("time", mService.connectionTime) - dispatchEvent(EVENTS.init, obj.toString()) - return true - } - - ACTIONS.requestStatistic -> { - dispatchEvent(EVENTS.statisticUpdate, mService.status.toString()) - return true - } - - ACTIONS.requestGetLog -> { - // Grabs all the Logs and dispatch new Log Event - dispatchEvent(EVENTS.backendLogs, Log.getContent()) - return true - } - ACTIONS.requestCleanupLog -> { - Log.clearFile() - return true - } - ACTIONS.setNotificationText -> { - NotificationUtil.update(data) - return true - } - ACTIONS.setFallBackNotification -> { - NotificationUtil.saveFallBackMessage(data, mService) - return true - } - IBinder.LAST_CALL_TRANSACTION -> { - Log.e(tag, "The OS Requested to shut down the VPN") - this.mService.turnOff() - return true - } - - else -> { - Log.e(tag, "Received invalid bind request \t Code -> $code") - // If we're hitting this there is probably something wrong in the client. return false } - } - return false - } - /** - * Dispatches an Event to all registered Binders - * [code] the Event that happened - see [EVENTS] - * To register an Eventhandler use [onTransact] with - * [ACTIONS.registerEventListener] - */ - fun dispatchEvent(code: Int, payload: String?) { - try { - mListener?.let { - if (it.isBinderAlive) { - val data = Parcel.obtain() - data.writeByteArray(payload?.toByteArray(charset("UTF-8"))) - it.transact(code, data, Parcel.obtain(), 0) + /** + * Dispatches an Event to all registered Binders + * [code] the Event that happened - see [EVENTS] + * To register an Eventhandler use [onTransact] with + * [ACTIONS.registerEventListener] + */ + fun dispatchEvent(code: Int, payload: String?) { + try { + mListener?.let { + if (it.isBinderAlive) { + val data = Parcel.obtain() + data.writeByteArray(payload?.toByteArray(charset("UTF-8"))) + it.transact(code, data, Parcel.obtain(), 0) + } + } + } catch (e: DeadObjectException) { + // If the QT Process is killed (not just inactive) + // we cant access isBinderAlive, so nothing to do here. + } + } + + /** + * The codes we Are Using in case of [dispatchEvent] + */ + object EVENTS { + const val init = 0 + const val connected = 1 + const val disconnected = 2 + const val statisticUpdate = 3 + const val backendLogs = 4 + const val activationError = 5 } } - } catch (e: DeadObjectException) { - // If the QT Process is killed (not just inactive) - // we cant access isBinderAlive, so nothing to do here. - } - } - - /** - * The codes we Are Using in case of [dispatchEvent] - */ - object EVENTS { - const val init = 0 - const val connected = 1 - const val disconnected = 2 - const val statisticUpdate = 3 - const val backendLogs = 4 - const val activationError = 5 - } -} diff --git a/client/android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt b/client/android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt index 7ae82f66..d3d3eeee 100644 --- a/client/android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt +++ b/client/android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt @@ -6,14 +6,18 @@ package org.amnezia.vpn.qt import android.content.Context import android.content.Intent +import android.util.Log class VPNPermissionHelper : android.net.VpnService() { + + private val tag = "VPNPermissionHelper" /** * This small service does nothing else then checking if the vpn permission * is present and prompting if not. */ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { val intent = prepare(this.applicationContext) + Log.i(tag, "VPNPermissionHelper onStartCommand") if (intent != null) { startActivityForResult(intent) } diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 48b164e9..53597fc6 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -271,63 +271,69 @@ ErrorCode VpnConnection::connectToVpn(int serverIndex, m_vpnProtocol.reset(); } - if (container == DockerContainer::None || container == DockerContainer::OpenVpn) { - ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::OpenVpn, containerConfig); - if (e) { - emit connectionStateChanged(VpnProtocol::Error); - return e; - } +// if (container == DockerContainer::None || container == DockerContainer::OpenVpn) { +// ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::OpenVpn, containerConfig); +// if (e) { +// emit connectionStateChanged(VpnProtocol::Error); +// return e; +// } - m_vpnProtocol.reset(new OpenVpnProtocol(m_vpnConfiguration)); - e = static_cast(m_vpnProtocol.data())->checkAndSetupTapDriver(); - if (e) { - emit connectionStateChanged(VpnProtocol::Error); - return e; - } - } - else if (container == DockerContainer::ShadowSocks) { - ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::ShadowSocks, containerConfig); - if (e) { - emit connectionStateChanged(VpnProtocol::Error); - return e; - } +// m_vpnProtocol.reset(new OpenVpnProtocol(m_vpnConfiguration)); +// e = static_cast(m_vpnProtocol.data())->checkAndSetupTapDriver(); +// if (e) { +// emit connectionStateChanged(VpnProtocol::Error); +// return e; +// } +// } +// else if (container == DockerContainer::ShadowSocks) { +// ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::ShadowSocks, containerConfig); +// if (e) { +// emit connectionStateChanged(VpnProtocol::Error); +// return e; +// } - m_vpnProtocol.reset(new ShadowSocksVpnProtocol(m_vpnConfiguration)); - e = static_cast(m_vpnProtocol.data())->checkAndSetupTapDriver(); - if (e) { - emit connectionStateChanged(VpnProtocol::Error); - return e; - } - } - else if (container == DockerContainer::Cloak) { - ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::Cloak, containerConfig); - if (e) { - emit connectionStateChanged(VpnProtocol::Error); - return e; - } +// m_vpnProtocol.reset(new ShadowSocksVpnProtocol(m_vpnConfiguration)); +// e = static_cast(m_vpnProtocol.data())->checkAndSetupTapDriver(); +// if (e) { +// emit connectionStateChanged(VpnProtocol::Error); +// return e; +// } +// } +// else if (container == DockerContainer::Cloak) { +// ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::Cloak, containerConfig); +// if (e) { +// emit connectionStateChanged(VpnProtocol::Error); +// return e; +// } - m_vpnProtocol.reset(new OpenVpnOverCloakProtocol(m_vpnConfiguration)); - e = static_cast(m_vpnProtocol.data())->checkAndSetupTapDriver(); - if (e) { - emit connectionStateChanged(VpnProtocol::Error); - return e; - } - } - else if (container == DockerContainer::WireGuard) { - ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::WireGuard, containerConfig); - if (e) { - emit connectionStateChanged(VpnProtocol::Error); - return e; - } +// m_vpnProtocol.reset(new OpenVpnOverCloakProtocol(m_vpnConfiguration)); +// e = static_cast(m_vpnProtocol.data())->checkAndSetupTapDriver(); +// if (e) { +// emit connectionStateChanged(VpnProtocol::Error); +// return e; +// } +// } +// else if (container == DockerContainer::WireGuard) { +// ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::WireGuard, containerConfig); +// if (e) { +// emit connectionStateChanged(VpnProtocol::Error); +// return e; +// } -#ifdef Q_OS_ANDROID - AndroidVpnProtocol *androidVpnProtocol = new AndroidVpnProtocol(Protocol::WireGuard, m_vpnConfiguration); - androidVpnProtocol->initialize(); - m_vpnProtocol.reset(androidVpnProtocol); -#else - m_vpnProtocol.reset(new WireguardProtocol(m_vpnConfiguration)); -#endif - } +//#ifdef Q_OS_ANDROID +// AndroidVpnProtocol *androidVpnProtocol = new AndroidVpnProtocol(Protocol::WireGuard, m_vpnConfiguration); +// androidVpnProtocol->initialize(); +// m_vpnProtocol.reset(androidVpnProtocol); +//#else +// m_vpnProtocol.reset(new WireguardProtocol(m_vpnConfiguration)); +//#endif +// } + + + + AndroidVpnProtocol *androidVpnProtocol = new AndroidVpnProtocol(Protocol::OpenVpn, m_vpnConfiguration); + androidVpnProtocol->initialize(); + m_vpnProtocol.reset(androidVpnProtocol); connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError); connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(VpnProtocol::ConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::ConnectionState)));