Prebuilt binaries for third-party submodules (#252)
* Add prebuilt submodule * Remove Android native library * Add links for Android prebuilt library * Update OpenSSL to prebuilt binaries * Setup links for prebuilt OpenSSL * Set correct OpenSSL header dir * Update prebuilt submodule * Use static OpenSSL for linux build * Use prebuilt binary from 3rd-prebuilt for Win installer * Use prebuilt binary from 3rd-prebuilt for Linux installer * Use prebuilt binary from 3rd-prebuilt for MacOS installer * Use Android prebuilt openvpn libs * Cleanup some unneeded code * Add new maven repo for gradle-versions-plugin * Use jitpack version of jsocks * Fix some unnecessary header copy * Fix issue with package name of original WG libs * Change submodule path to https (3rd-prebuilt) * Fix windows installer * MacOS deploy fixes * NetworkChange detection for OpenVPN protocol (#256) * NetworkChange detection for OpenVPN protocol * Update android native libs * Always on VPN mode for OpenVPN, Cloak+OpenVPN * Set foregroundService type * Android 14 require to set foregroundServiceType * Remove unused code and cleanup submodules * Cleanup gradle build script * Fix start button status * Pull OpenSSL prebuilt for MacOS, iOS * Update links for OpenSSL MacOS, iOS prebuilt * Update OpenSSL binaries path * Refactor some OpenSSL includes * Update MacOS OpenVPN binary with statically linked dependency * Use prebilt for LibSSH * Android resources cleanup * Set static runtime linux * Use shared LibSSH for Android * Update SS Android lib name * Fix Linux install path and file permissions * Feature/iOS GitHub actions (#265) * Move Android cpp code to openvpn-pt-android repo * Remove unused OpenVPN2 Android Libs * Cleanup Gemfile --------- Co-authored-by: Mazay B <pokamest@gmail.com>
This commit is contained in:
parent
9bd8c774ab
commit
f58a16ca9d
327 changed files with 500 additions and 45808 deletions
|
@ -0,0 +1,19 @@
|
|||
package com.wireguard.android.backend;
|
||||
|
||||
|
||||
public final class GoBackend {
|
||||
private static final String TAG = "WireGuard/GoBackend";
|
||||
|
||||
public static native String wgGetConfig(int handle);
|
||||
|
||||
public static native int wgGetSocketV4(int handle);
|
||||
|
||||
public static native int wgGetSocketV6(int handle);
|
||||
|
||||
public static native void wgTurnOff(int handle);
|
||||
|
||||
public static native int wgTurnOn(String ifName, int tunFd, String settings);
|
||||
|
||||
public static native String wgVersion();
|
||||
|
||||
}
|
195
client/android/src/org/amnezia/vpn/NetworkState.kt
Normal file
195
client/android/src/org/amnezia/vpn/NetworkState.kt
Normal file
|
@ -0,0 +1,195 @@
|
|||
/* 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.*
|
||||
import android.net.*
|
||||
import android.system.ErrnoException
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_DUN
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_FOTA
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_IA
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_IMS
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_MCX
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_MMS
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_SUPL
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_XCAP
|
||||
import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH
|
||||
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
|
||||
import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
|
||||
import android.net.NetworkCapabilities.TRANSPORT_LOWPAN
|
||||
import android.net.NetworkCapabilities.TRANSPORT_USB
|
||||
import android.net.NetworkCapabilities.TRANSPORT_VPN
|
||||
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
||||
import android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE
|
||||
import java.io.Closeable
|
||||
import java.util.EnumSet
|
||||
import java.io.File
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import java.io.FileDescriptor
|
||||
import java.io.IOException
|
||||
import java.lang.Exception
|
||||
|
||||
|
||||
class NetworkState(var service: VPNService) {
|
||||
private var mService: VPNService = service
|
||||
var mCurrentContext: Context = service
|
||||
private val tag = "NetworkState"
|
||||
private var active = false
|
||||
private var listeningForDefaultNetwork = false
|
||||
private var metered = false
|
||||
|
||||
|
||||
enum class Transport(val systemConstant: Int) {
|
||||
BLUETOOTH(TRANSPORT_BLUETOOTH),
|
||||
CELLULAR(TRANSPORT_CELLULAR),
|
||||
ETHERNET(TRANSPORT_ETHERNET),
|
||||
VPN(TRANSPORT_VPN),
|
||||
WIFI(TRANSPORT_WIFI),
|
||||
WIFI_AWARE(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) TRANSPORT_WIFI_AWARE else UNSUPPORTED_TRANSPORT),
|
||||
LOWPAN(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) TRANSPORT_LOWPAN else UNSUPPORTED_TRANSPORT),
|
||||
USB(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) TRANSPORT_USB else UNSUPPORTED_TRANSPORT)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val UNSUPPORTED_TRANSPORT: Int = -1 // The TRANSPORT_* constants are non-negative.
|
||||
private const val NOT_VPN = "NOT_VPN"
|
||||
|
||||
private val defaultNetworkRequest = NetworkRequest.Builder()
|
||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
|
||||
.build()
|
||||
|
||||
}
|
||||
|
||||
private data class NetworkTransports(
|
||||
val network: Network,
|
||||
val transports: Set<Transport>
|
||||
)
|
||||
|
||||
private fun getTransports(networkCapabilities: NetworkCapabilities): EnumSet<Transport> =
|
||||
Transport.values().mapNotNullTo(EnumSet.noneOf(Transport::class.java)) {
|
||||
if (networkCapabilities.hasTransport(it.systemConstant)) it else null
|
||||
}
|
||||
|
||||
private var defaultNetworkCapabilities: Map<String, Boolean> = LinkedHashMap()
|
||||
private var defaultNetwork: NetworkTransports? = null
|
||||
val defaultNetworkTransports: Set<Transport>
|
||||
get() = defaultNetwork?.transports ?: emptySet()
|
||||
|
||||
private val capabilitiesConstantMap = mutableMapOf(
|
||||
"MMS" to NET_CAPABILITY_MMS,
|
||||
"SUPL" to NET_CAPABILITY_SUPL,
|
||||
"DUN" to NET_CAPABILITY_DUN,
|
||||
"FOTA" to NET_CAPABILITY_FOTA,
|
||||
"IMS" to NET_CAPABILITY_IMS,
|
||||
"WIFI_P2P" to NET_CAPABILITY_WIFI_P2P,
|
||||
"IA" to NET_CAPABILITY_IA,
|
||||
"XCAP" to NET_CAPABILITY_XCAP,
|
||||
"NOT_METERED" to NET_CAPABILITY_NOT_METERED,
|
||||
"INTERNET" to NET_CAPABILITY_INTERNET,
|
||||
NOT_VPN to NET_CAPABILITY_NOT_VPN,
|
||||
"TRUSTED" to NET_CAPABILITY_TRUSTED,
|
||||
"TEMP NOT METERED" to NET_CAPABILITY_TEMPORARILY_NOT_METERED,
|
||||
"NOT SUSPENDED" to NET_CAPABILITY_MCX,
|
||||
).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
put("VALIDATED", NET_CAPABILITY_VALIDATED)
|
||||
put("CAPTIVE PORTAL", NET_CAPABILITY_CAPTIVE_PORTAL)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
put("NOT ROAMING", NET_CAPABILITY_NOT_ROAMING)
|
||||
put("TRUSTED", NET_CAPABILITY_FOREGROUND)
|
||||
put("NOT CONGESTED", NET_CAPABILITY_NOT_CONGESTED)
|
||||
put("NOT SUSPENDED", NET_CAPABILITY_NOT_SUSPENDED)
|
||||
}
|
||||
} as Map<String, Int>
|
||||
|
||||
|
||||
|
||||
private val connectivity by lazy { mCurrentContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager }
|
||||
|
||||
private var mLastNetworkCapabilities: String? = null
|
||||
|
||||
private val defaultNetworkCallback = object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
super.onAvailable(network)
|
||||
|
||||
|
||||
Log.i(tag, "onAvailable $network")
|
||||
}
|
||||
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
|
||||
val newCapabilities = capabilitiesConstantMap.mapValues {
|
||||
networkCapabilities.hasCapability(it.value)
|
||||
}
|
||||
val newTransports = getTransports(networkCapabilities)
|
||||
val capabilitiesChanged = defaultNetworkCapabilities != newCapabilities
|
||||
if (defaultNetwork?.network != network ||
|
||||
defaultNetwork?.transports != newTransports ||
|
||||
capabilitiesChanged
|
||||
) {
|
||||
Log.i(
|
||||
tag,
|
||||
"default network: $network; transports: ${newTransports.joinToString(", ")}; " +
|
||||
"capabilities: $newCapabilities"
|
||||
)
|
||||
defaultNetwork = NetworkTransports(network, newTransports)
|
||||
}
|
||||
if (capabilitiesChanged) {
|
||||
mService.networkChange()
|
||||
|
||||
Log.i(tag, "onCapabilitiesChanged capabilitiesChanged $network $networkCapabilities")
|
||||
defaultNetworkCapabilities = newCapabilities
|
||||
}
|
||||
super.onCapabilitiesChanged(network, networkCapabilities)
|
||||
}
|
||||
|
||||
override fun onBlockedStatusChanged(network: Network, blocked: Boolean) {
|
||||
super.onBlockedStatusChanged(network, blocked)
|
||||
Log.i(tag, "onBlockedStatusChanged $network $blocked")
|
||||
}
|
||||
|
||||
|
||||
override fun onLost(network: Network) {
|
||||
super.onLost(network)
|
||||
Log.i(tag, "onLost")
|
||||
}
|
||||
}
|
||||
|
||||
fun bindNetworkListener() {
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
// we want REQUEST here instead of LISTEN
|
||||
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
|
||||
listeningForDefaultNetwork = true
|
||||
}
|
||||
}
|
||||
|
||||
fun unBindNetworkListener() {
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
|
||||
listeningForDefaultNetwork = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -26,6 +26,8 @@ import net.openvpn.ovpn3.ClientAPI_OpenVPNClient
|
|||
import net.openvpn.ovpn3.ClientAPI_ProvideCreds
|
||||
import net.openvpn.ovpn3.ClientAPI_Status
|
||||
import net.openvpn.ovpn3.ClientAPI_TransportStats
|
||||
|
||||
|
||||
import java.lang.StringBuilder
|
||||
|
||||
class OpenVPNThreadv3(var service: VPNService): ClientAPI_OpenVPNClient(), Runnable {
|
||||
|
@ -58,6 +60,12 @@ class OpenVPNThreadv3(var service: VPNService): ClientAPI_OpenVPNClient(), Runna
|
|||
return stats_value(bytesOutIndex)
|
||||
}
|
||||
|
||||
override fun reconnect(seconds :Int) {
|
||||
Log.v(tag, "reconnect")
|
||||
super.reconnect(seconds)
|
||||
}
|
||||
|
||||
|
||||
override fun run() {
|
||||
|
||||
val config: ClientAPI_Config = ClientAPI_Config()
|
||||
|
|
|
@ -20,6 +20,7 @@ import androidx.core.content.FileProvider
|
|||
import com.wireguard.android.util.SharedLibraryLoader
|
||||
import com.wireguard.config.*
|
||||
import com.wireguard.crypto.Key
|
||||
import com.wireguard.android.backend.GoBackend
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -48,6 +49,7 @@ import android.net.VpnService as BaseVpnService
|
|||
class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
||||
|
||||
override val data = BaseService.Data(this)
|
||||
|
||||
override val tag: String get() = "VPNService"
|
||||
// override fun createNotification(profileName: String): ServiceNotification =
|
||||
// ServiceNotification(this, profileName, "service-vpn")
|
||||
|
@ -56,6 +58,7 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
private var worker: ProtectWorker? = null
|
||||
private var active = false
|
||||
private var metered = false
|
||||
private var mNetworkState = NetworkState(this)
|
||||
private var underlyingNetwork: Network? = null
|
||||
set(value) {
|
||||
field = value
|
||||
|
@ -121,23 +124,6 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
})
|
||||
}
|
||||
|
||||
@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 var mBinder: VPNServiceBinder = VPNServiceBinder(this)
|
||||
|
@ -162,7 +148,7 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
SharedLibraryLoader.loadSharedLibrary(this, "wg-go")
|
||||
SharedLibraryLoader.loadSharedLibrary(this, "ovpn3")
|
||||
Log.i(tag, "Loaded libs")
|
||||
Log.e(tag, "Wireguard Version ${wgVersion()}")
|
||||
Log.e(tag, "Wireguard Version ${GoBackend.wgVersion()}")
|
||||
mOpenVPNThreadv3 = OpenVPNThreadv3(this)
|
||||
mAlreadyInitialised = true
|
||||
}
|
||||
|
@ -241,6 +227,10 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
|
||||
mProtocol = mConfig!!.getString("protocol")
|
||||
Log.e(tag, "mProtocol: $mProtocol")
|
||||
if (mProtocol.equals("cloak", true) || (mProtocol.equals("openvpn", true))) {
|
||||
startOpenVpn()
|
||||
mNetworkState.bindNetworkListener()
|
||||
}
|
||||
if (mProtocol.equals("shadowsocks", true)) {
|
||||
if (DataStore.serviceMode == modeVpn) {
|
||||
if (prepare(this) != null) {
|
||||
|
@ -266,7 +256,7 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
// At this moment, the VPN interface is already deactivated by the system.
|
||||
override fun onRevoke() {
|
||||
Log.v(tag, "Aman: onRevoke....................")
|
||||
this.turnOff()
|
||||
//this.turnOff()
|
||||
super.onRevoke()
|
||||
}
|
||||
|
||||
|
@ -379,7 +369,15 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
when (mProtocol) {
|
||||
"cloak",
|
||||
"openvpn" -> {
|
||||
startOpenVpn()
|
||||
startOpenVpn()
|
||||
// Store the config in case the service gets
|
||||
// asked boot vpn from the OS
|
||||
val prefs = Prefs.get(this)
|
||||
prefs.edit()
|
||||
.putString("lastConf", mConfig.toString())
|
||||
.apply()
|
||||
|
||||
mNetworkState.bindNetworkListener()
|
||||
}
|
||||
"wireguard" -> {
|
||||
startWireGuard()
|
||||
|
@ -428,6 +426,14 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
mbuilder.addRoute(ip, 32)
|
||||
}
|
||||
}
|
||||
|
||||
fun networkChange() {
|
||||
Log.i(tag, "mProtocol $mProtocol")
|
||||
if (isUp){
|
||||
mbuilder = Builder()
|
||||
mOpenVPNThreadv3?.reconnect(0)
|
||||
}
|
||||
}
|
||||
|
||||
fun setSessionName(name: String) {
|
||||
Log.v(tag, "mbuilder.setSession($name)")
|
||||
|
@ -452,11 +458,12 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
Log.v(tag, "Aman: turnOff....................")
|
||||
when (mProtocol) {
|
||||
"wireguard" -> {
|
||||
wgTurnOff(currentTunnelHandle)
|
||||
GoBackend.wgTurnOff(currentTunnelHandle)
|
||||
}
|
||||
"cloak",
|
||||
"openvpn" -> {
|
||||
ovpnTurnOff()
|
||||
mNetworkState.unBindNetworkListener()
|
||||
}
|
||||
"shadowsocks" -> {
|
||||
stopRunner(false)
|
||||
|
@ -517,7 +524,7 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
if (!isUp) {
|
||||
return null
|
||||
}
|
||||
val config = wgGetConfig(currentTunnelHandle) ?: return null
|
||||
val config = GoBackend.wgGetConfig(currentTunnelHandle) ?: return null
|
||||
val lines = config.split("\n")
|
||||
for (line in lines) {
|
||||
val parts = line.split("=")
|
||||
|
@ -715,7 +722,7 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
if (currentTunnelHandle != -1) {
|
||||
Log.e(tag, "Tunnel already up")
|
||||
// Turn the tunnel down because this might be a switch
|
||||
wgTurnOff(currentTunnelHandle)
|
||||
GoBackend.wgTurnOff(currentTunnelHandle)
|
||||
}
|
||||
val wgConfig: String = wireguard_conf.toWgUserspaceString()
|
||||
val builder = Builder()
|
||||
|
@ -723,16 +730,15 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
builder.setSession("Amnezia")
|
||||
builder.establish().use { tun ->
|
||||
if (tun == null) return
|
||||
Log.i(tag, "Go backend " + wgVersion())
|
||||
currentTunnelHandle = wgTurnOn("Amnezia", tun.detachFd(), wgConfig)
|
||||
currentTunnelHandle = GoBackend.wgTurnOn("Amnezia", tun.detachFd(), wgConfig)
|
||||
}
|
||||
if (currentTunnelHandle < 0) {
|
||||
Log.e(tag, "Activation Error Code -> $currentTunnelHandle")
|
||||
isUp = false
|
||||
return
|
||||
}
|
||||
protect(wgGetSocketV4(currentTunnelHandle))
|
||||
protect(wgGetSocketV6(currentTunnelHandle))
|
||||
protect(GoBackend.wgGetSocketV4(currentTunnelHandle))
|
||||
protect(GoBackend.wgGetSocketV6(currentTunnelHandle))
|
||||
isUp = true
|
||||
|
||||
// Store the config in case the service gets
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue