Add AWG module
This commit is contained in:
parent
91f44fb394
commit
9297f877c4
11 changed files with 295 additions and 43 deletions
18
client/android/awg/build.gradle.kts
Normal file
18
client/android/awg/build.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
plugins {
|
||||||
|
id(libs.plugins.android.library.get().pluginId)
|
||||||
|
id(libs.plugins.kotlin.android.get().pluginId)
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvmToolchain(17)
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "org.amnezia.vpn.protocol.awg"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly(project(":utils"))
|
||||||
|
compileOnly(project(":protocolApi"))
|
||||||
|
implementation(project(":wireguard"))
|
||||||
|
}
|
79
client/android/awg/src/main/kotlin/Awg.kt
Normal file
79
client/android/awg/src/main/kotlin/Awg.kt
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package org.amnezia.vpn.protocol.awg
|
||||||
|
|
||||||
|
import org.amnezia.vpn.protocol.wireguard.Wireguard
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config example:
|
||||||
|
* {
|
||||||
|
* "protocol": "awg",
|
||||||
|
* "description": "Server 1",
|
||||||
|
* "dns1": "1.1.1.1",
|
||||||
|
* "dns2": "1.0.0.1",
|
||||||
|
* "hostName": "100.100.100.0",
|
||||||
|
* "splitTunnelSites": [
|
||||||
|
* ],
|
||||||
|
* "splitTunnelType": 0,
|
||||||
|
* "awg_config_data": {
|
||||||
|
* "H1": "969537490",
|
||||||
|
* "H2": "481688153",
|
||||||
|
* "H3": "2049399200",
|
||||||
|
* "H4": "52029755",
|
||||||
|
* "Jc": "3",
|
||||||
|
* "Jmax": "1000",
|
||||||
|
* "Jmin": "50",
|
||||||
|
* "S1": "49",
|
||||||
|
* "S2": "60",
|
||||||
|
* "client_ip": "10.8.1.1",
|
||||||
|
* "hostName": "100.100.100.0",
|
||||||
|
* "port": 12345,
|
||||||
|
* "client_pub_key": "clientPublicKeyBase64",
|
||||||
|
* "client_priv_key": "privateKeyBase64",
|
||||||
|
* "psk_key": "presharedKeyBase64",
|
||||||
|
* "server_pub_key": "publicKeyBase64",
|
||||||
|
* "config": "[Interface]
|
||||||
|
* Address = 10.8.1.1/32
|
||||||
|
* DNS = 1.1.1.1, 1.0.0.1
|
||||||
|
* PrivateKey = privateKeyBase64
|
||||||
|
* Jc = 3
|
||||||
|
* Jmin = 50
|
||||||
|
* Jmax = 1000
|
||||||
|
* S1 = 49
|
||||||
|
* S2 = 60
|
||||||
|
* H1 = 969537490
|
||||||
|
* H2 = 481688153
|
||||||
|
* H3 = 2049399200
|
||||||
|
* H4 = 52029755
|
||||||
|
*
|
||||||
|
* [Peer]
|
||||||
|
* PublicKey = publicKeyBase64
|
||||||
|
* PresharedKey = presharedKeyBase64
|
||||||
|
* AllowedIPs = 0.0.0.0/0, ::/0
|
||||||
|
* Endpoint = 100.100.100.0:12345
|
||||||
|
* PersistentKeepalive = 25
|
||||||
|
* "
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Awg : Wireguard() {
|
||||||
|
|
||||||
|
override val ifName: String = "awg0"
|
||||||
|
|
||||||
|
override fun parseConfig(config: JSONObject): AwgConfig {
|
||||||
|
val configDataJson = config.getJSONObject("awg_config_data")
|
||||||
|
val configData = parseConfigData(configDataJson.getString("config"))
|
||||||
|
return AwgConfig.build {
|
||||||
|
configureWireguard(wireguardConfigBuilder(configData))
|
||||||
|
configData["Jc"]?.let { setJc(it.toInt()) }
|
||||||
|
configData["Jmin"]?.let { setJmin(it.toInt()) }
|
||||||
|
configData["Jmax"]?.let { setJmax(it.toInt()) }
|
||||||
|
configData["S1"]?.let { setS1(it.toInt()) }
|
||||||
|
configData["S2"]?.let { setS2(it.toInt()) }
|
||||||
|
configData["H1"]?.let { setH1(it.toLong()) }
|
||||||
|
configData["H2"]?.let { setH2(it.toLong()) }
|
||||||
|
configData["H3"]?.let { setH3(it.toLong()) }
|
||||||
|
configData["H4"]?.let { setH4(it.toLong()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
115
client/android/awg/src/main/kotlin/AwgConfig.kt
Normal file
115
client/android/awg/src/main/kotlin/AwgConfig.kt
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
package org.amnezia.vpn.protocol.awg
|
||||||
|
|
||||||
|
import org.amnezia.vpn.protocol.BadConfigException
|
||||||
|
import org.amnezia.vpn.protocol.wireguard.WireguardConfig
|
||||||
|
|
||||||
|
class AwgConfig private constructor(
|
||||||
|
wireguardConfigBuilder: WireguardConfig.Builder,
|
||||||
|
val jc: Int,
|
||||||
|
val jmin: Int,
|
||||||
|
val jmax: Int,
|
||||||
|
val s1: Int,
|
||||||
|
val s2: Int,
|
||||||
|
val h1: Long,
|
||||||
|
val h2: Long,
|
||||||
|
val h3: Long,
|
||||||
|
val h4: Long
|
||||||
|
) : WireguardConfig(wireguardConfigBuilder) {
|
||||||
|
|
||||||
|
private constructor(builder: Builder) : this(
|
||||||
|
builder.wireguardConfigBuilder,
|
||||||
|
builder.jc,
|
||||||
|
builder.jmin,
|
||||||
|
builder.jmax,
|
||||||
|
builder.s1,
|
||||||
|
builder.s2,
|
||||||
|
builder.h1,
|
||||||
|
builder.h2,
|
||||||
|
builder.h3,
|
||||||
|
builder.h4
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun toWgUserspaceString(): String = with(StringBuilder()) {
|
||||||
|
append(super.toWgUserspaceString())
|
||||||
|
appendLine("jc=$jc")
|
||||||
|
appendLine("jmin=$jmin")
|
||||||
|
appendLine("jmax=$jmax")
|
||||||
|
appendLine("s1=$s1")
|
||||||
|
appendLine("s2=$s2")
|
||||||
|
appendLine("h1=$h1")
|
||||||
|
appendLine("h2=$h2")
|
||||||
|
appendLine("h3=$h3")
|
||||||
|
appendLine("h4=$h4")
|
||||||
|
return this.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
internal lateinit var wireguardConfigBuilder: WireguardConfig.Builder
|
||||||
|
private set
|
||||||
|
|
||||||
|
private var _jc: Int? = null
|
||||||
|
internal var jc: Int
|
||||||
|
get() = _jc ?: throw BadConfigException("AWG: parameter jc is undefined")
|
||||||
|
private set(value) { _jc = value}
|
||||||
|
|
||||||
|
private var _jmin: Int? = null
|
||||||
|
internal var jmin: Int
|
||||||
|
get() = _jmin ?: throw BadConfigException("AWG: parameter jmin is undefined")
|
||||||
|
private set(value) { _jmin = value}
|
||||||
|
|
||||||
|
private var _jmax: Int? = null
|
||||||
|
internal var jmax: Int
|
||||||
|
get() = _jmax ?: throw BadConfigException("AWG: parameter jmax is undefined")
|
||||||
|
private set(value) { _jmax = value}
|
||||||
|
|
||||||
|
private var _s1: Int? = null
|
||||||
|
internal var s1: Int
|
||||||
|
get() = _s1 ?: throw BadConfigException("AWG: parameter s1 is undefined")
|
||||||
|
private set(value) { _s1 = value}
|
||||||
|
|
||||||
|
private var _s2: Int? = null
|
||||||
|
internal var s2: Int
|
||||||
|
get() = _s2 ?: throw BadConfigException("AWG: parameter s2 is undefined")
|
||||||
|
private set(value) { _s2 = value}
|
||||||
|
|
||||||
|
private var _h1: Long? = null
|
||||||
|
internal var h1: Long
|
||||||
|
get() = _h1 ?: throw BadConfigException("AWG: parameter h1 is undefined")
|
||||||
|
private set(value) { _h1 = value}
|
||||||
|
|
||||||
|
private var _h2: Long? = null
|
||||||
|
internal var h2: Long
|
||||||
|
get() = _h2 ?: throw BadConfigException("AWG: parameter h2 is undefined")
|
||||||
|
private set(value) { _h2 = value}
|
||||||
|
|
||||||
|
private var _h3: Long? = null
|
||||||
|
internal var h3: Long
|
||||||
|
get() = _h3 ?: throw BadConfigException("AWG: parameter h3 is undefined")
|
||||||
|
private set(value) { _h3 = value}
|
||||||
|
|
||||||
|
private var _h4: Long? = null
|
||||||
|
internal var h4: Long
|
||||||
|
get() = _h4 ?: throw BadConfigException("AWG: parameter h4 is undefined")
|
||||||
|
private set(value) { _h4 = value}
|
||||||
|
|
||||||
|
fun configureWireguard(block: WireguardConfig.Builder.() -> Unit) = apply {
|
||||||
|
wireguardConfigBuilder = WireguardConfig.Builder().apply(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setJc(jc: Int) = apply { this.jc = jc }
|
||||||
|
fun setJmin(jmin: Int) = apply { this.jmin = jmin }
|
||||||
|
fun setJmax(jmax: Int) = apply { this.jmax = jmax }
|
||||||
|
fun setS1(s1: Int) = apply { this.s1 = s1 }
|
||||||
|
fun setS2(s2: Int) = apply { this.s2 = s2 }
|
||||||
|
fun setH1(h1: Long) = apply { this.h1 = h1 }
|
||||||
|
fun setH2(h2: Long) = apply { this.h2 = h2 }
|
||||||
|
fun setH3(h3: Long) = apply { this.h3 = h3 }
|
||||||
|
fun setH4(h4: Long) = apply { this.h4 = h4 }
|
||||||
|
|
||||||
|
fun build(): AwgConfig = AwgConfig(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
inline fun build(block: Builder.() -> Unit): AwgConfig = Builder().apply(block).build()
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,6 +87,7 @@ dependencies {
|
||||||
implementation(project(":utils"))
|
implementation(project(":utils"))
|
||||||
implementation(project(":protocolApi"))
|
implementation(project(":protocolApi"))
|
||||||
implementation(project(":wireguard"))
|
implementation(project(":wireguard"))
|
||||||
|
implementation(project(":awg"))
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
implementation(libs.androidx.activity)
|
implementation(libs.androidx.activity)
|
||||||
implementation(libs.androidx.security.crypto)
|
implementation(libs.androidx.security.crypto)
|
||||||
|
|
|
@ -18,17 +18,17 @@ private const val TAG = "Protocol"
|
||||||
|
|
||||||
const val VPN_SESSION_NAME = "AmneziaVPN"
|
const val VPN_SESSION_NAME = "AmneziaVPN"
|
||||||
|
|
||||||
abstract class Protocol(protected val context: Context) {
|
abstract class Protocol {
|
||||||
|
|
||||||
open lateinit var config: ProtocolConfig
|
|
||||||
|
|
||||||
abstract val statistics: Statistics
|
abstract val statistics: Statistics
|
||||||
|
|
||||||
abstract fun initialize()
|
abstract fun initialize(context: Context)
|
||||||
|
|
||||||
abstract fun parseConfig(config: JSONObject)
|
abstract fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean)
|
||||||
|
|
||||||
protected open fun buildVpnInterface(vpnBuilder: Builder) {
|
abstract fun stopVpn()
|
||||||
|
|
||||||
|
protected open fun buildVpnInterface(config: ProtocolConfig, vpnBuilder: Builder) {
|
||||||
vpnBuilder.setSession(VPN_SESSION_NAME)
|
vpnBuilder.setSession(VPN_SESSION_NAME)
|
||||||
vpnBuilder.allowFamily(OsConstants.AF_INET)
|
vpnBuilder.allowFamily(OsConstants.AF_INET)
|
||||||
vpnBuilder.allowFamily(OsConstants.AF_INET6)
|
vpnBuilder.allowFamily(OsConstants.AF_INET6)
|
||||||
|
@ -49,10 +49,6 @@ abstract class Protocol(protected val context: Context) {
|
||||||
vpnBuilder.setMetered(false)
|
vpnBuilder.setMetered(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun startVpn(vpnBuilder: Builder, protect: (Int) -> Boolean)
|
|
||||||
|
|
||||||
abstract fun stopVpn()
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun extractLibrary(context: Context, libraryName: String, destination: File): Boolean {
|
private fun extractLibrary(context: Context, libraryName: String, destination: File): Boolean {
|
||||||
Log.d(TAG, "Extracting library: $libraryName")
|
Log.d(TAG, "Extracting library: $libraryName")
|
||||||
|
|
|
@ -5,7 +5,7 @@ import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
|
|
||||||
data class ProtocolConfig(
|
open class ProtocolConfig protected constructor(
|
||||||
val addresses: Set<InetNetwork>,
|
val addresses: Set<InetNetwork>,
|
||||||
val dnsServers: Set<InetAddress>,
|
val dnsServers: Set<InetAddress>,
|
||||||
val routes: Set<InetNetwork>,
|
val routes: Set<InetNetwork>,
|
||||||
|
@ -15,7 +15,7 @@ data class ProtocolConfig(
|
||||||
val mtu: Int
|
val mtu: Int
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private constructor(builder: Builder) : this(
|
protected constructor(builder: Builder) : this(
|
||||||
builder.addresses,
|
builder.addresses,
|
||||||
builder.dnsServers,
|
builder.dnsServers,
|
||||||
builder.routes,
|
builder.routes,
|
||||||
|
@ -49,6 +49,7 @@ data class ProtocolConfig(
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||||
fun excludeRoute(route: InetNetwork) = apply { this.excludedRoutes += route }
|
fun excludeRoute(route: InetNetwork) = apply { this.excludedRoutes += route }
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||||
fun excludeRoutes(routes: List<InetNetwork>) = apply { this.excludedRoutes += routes }
|
fun excludeRoutes(routes: List<InetNetwork>) = apply { this.excludedRoutes += routes }
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ include(":qt")
|
||||||
include(":utils")
|
include(":utils")
|
||||||
include(":protocolApi")
|
include(":protocolApi")
|
||||||
include(":wireguard")
|
include(":wireguard")
|
||||||
|
include(":awg")
|
||||||
|
|
||||||
// get values from gradle or local properties
|
// get values from gradle or local properties
|
||||||
val androidBuildToolsVersion: String by gradleProperties
|
val androidBuildToolsVersion: String by gradleProperties
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTING
|
||||||
import org.amnezia.vpn.protocol.Statistics
|
import org.amnezia.vpn.protocol.Statistics
|
||||||
import org.amnezia.vpn.protocol.Status
|
import org.amnezia.vpn.protocol.Status
|
||||||
import org.amnezia.vpn.protocol.VpnStartException
|
import org.amnezia.vpn.protocol.VpnStartException
|
||||||
|
import org.amnezia.vpn.protocol.awg.Awg
|
||||||
import org.amnezia.vpn.protocol.putStatistics
|
import org.amnezia.vpn.protocol.putStatistics
|
||||||
import org.amnezia.vpn.protocol.putStatus
|
import org.amnezia.vpn.protocol.putStatus
|
||||||
import org.amnezia.vpn.protocol.wireguard.Wireguard
|
import org.amnezia.vpn.protocol.wireguard.Wireguard
|
||||||
|
@ -54,6 +55,7 @@ class AmneziaVpnService : VpnService() {
|
||||||
private lateinit var mainScope: CoroutineScope
|
private lateinit var mainScope: CoroutineScope
|
||||||
private var isServiceBound = false
|
private var isServiceBound = false
|
||||||
private var protocol: Protocol? = null
|
private var protocol: Protocol? = null
|
||||||
|
private val protocolCache = mutableMapOf<String, Protocol>()
|
||||||
private var protocolState = MutableStateFlow(DISCONNECTED)
|
private var protocolState = MutableStateFlow(DISCONNECTED)
|
||||||
|
|
||||||
private val isConnected
|
private val isConnected
|
||||||
|
@ -272,11 +274,7 @@ class AmneziaVpnService : VpnService() {
|
||||||
disconnectionJob = null
|
disconnectionJob = null
|
||||||
|
|
||||||
protocol = getProtocol(config.getString("protocol"))
|
protocol = getProtocol(config.getString("protocol"))
|
||||||
protocol?.let { protocol ->
|
protocol?.startVpn(config, Builder(), ::protect)
|
||||||
protocol.initialize()
|
|
||||||
protocol.parseConfig(config)
|
|
||||||
protocol.startVpn(Builder(), ::protect)
|
|
||||||
}
|
|
||||||
protocolState.value = CONNECTED
|
protocolState.value = CONNECTED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,10 +300,12 @@ class AmneziaVpnService : VpnService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getProtocol(protocolName: String): Protocol =
|
private fun getProtocol(protocolName: String): Protocol =
|
||||||
when (protocolName) {
|
protocolCache[protocolName]
|
||||||
"wireguard" -> Wireguard(applicationContext)
|
?: when (protocolName) {
|
||||||
|
"wireguard" -> Wireguard()
|
||||||
|
"awg" -> Awg()
|
||||||
else -> throw IllegalArgumentException("Failed to load $protocolName protocol")
|
else -> throw IllegalArgumentException("Failed to load $protocolName protocol")
|
||||||
}
|
}.apply { initialize(applicationContext) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utils methods
|
* Utils methods
|
||||||
|
|
|
@ -9,17 +9,51 @@ import org.amnezia.vpn.protocol.InetEndpoint
|
||||||
import org.amnezia.vpn.protocol.InetNetwork
|
import org.amnezia.vpn.protocol.InetNetwork
|
||||||
import org.amnezia.vpn.protocol.Protocol
|
import org.amnezia.vpn.protocol.Protocol
|
||||||
import org.amnezia.vpn.protocol.Statistics
|
import org.amnezia.vpn.protocol.Statistics
|
||||||
import org.amnezia.vpn.protocol.VPN_SESSION_NAME
|
|
||||||
import org.amnezia.vpn.protocol.VpnStartException
|
import org.amnezia.vpn.protocol.VpnStartException
|
||||||
import org.amnezia.vpn.protocol.parseInetAddress
|
import org.amnezia.vpn.protocol.parseInetAddress
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config example:
|
||||||
|
* {
|
||||||
|
* "protocol": "wireguard",
|
||||||
|
* "description": "Server 1",
|
||||||
|
* "dns1": "1.1.1.1",
|
||||||
|
* "dns2": "1.0.0.1",
|
||||||
|
* "hostName": "100.100.100.0",
|
||||||
|
* "splitTunnelSites": [
|
||||||
|
* ],
|
||||||
|
* "splitTunnelType": 0,
|
||||||
|
* "wireguard_config_data": {
|
||||||
|
* "client_ip": "10.8.1.1",
|
||||||
|
* "hostName": "100.100.100.0",
|
||||||
|
* "port": 12345,
|
||||||
|
* "client_pub_key": "clientPublicKeyBase64",
|
||||||
|
* "client_priv_key": "privateKeyBase64",
|
||||||
|
* "psk_key": "presharedKeyBase64",
|
||||||
|
* "server_pub_key": "publicKeyBase64",
|
||||||
|
* "config": "[Interface]
|
||||||
|
* Address = 10.8.1.1/32
|
||||||
|
* DNS = 1.1.1.1, 1.0.0.1
|
||||||
|
* PrivateKey = privateKeyBase64
|
||||||
|
*
|
||||||
|
* [Peer]
|
||||||
|
* PublicKey = publicKeyBase64
|
||||||
|
* PresharedKey = presharedKeyBase64
|
||||||
|
* AllowedIPs = 0.0.0.0/0, ::/0
|
||||||
|
* Endpoint = 100.100.100.0:12345
|
||||||
|
* PersistentKeepalive = 25
|
||||||
|
* "
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
private const val TAG = "Wireguard"
|
private const val TAG = "Wireguard"
|
||||||
|
|
||||||
class Wireguard(context: Context) : Protocol(context) {
|
open class Wireguard : Protocol() {
|
||||||
|
|
||||||
private var tunnelHandle: Int = -1
|
private var tunnelHandle: Int = -1
|
||||||
private lateinit var wireguardConfig: WireguardConfig
|
protected open val ifName: String = "amn0"
|
||||||
|
|
||||||
override val statistics: Statistics
|
override val statistics: Statistics
|
||||||
get() {
|
get() {
|
||||||
|
@ -40,14 +74,23 @@ class Wireguard(context: Context) : Protocol(context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initialize() {
|
override fun initialize(context: Context) {
|
||||||
loadSharedLibrary(context, "wg-go")
|
loadSharedLibrary(context, "wg-go")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun parseConfig(config: JSONObject) {
|
override fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
||||||
|
val wireguardConfig = parseConfig(config)
|
||||||
|
start(wireguardConfig, vpnBuilder, protect)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun parseConfig(config: JSONObject): WireguardConfig {
|
||||||
val configDataJson = config.getJSONObject("wireguard_config_data")
|
val configDataJson = config.getJSONObject("wireguard_config_data")
|
||||||
val configData = parseConfigData(configDataJson.getString("config"))
|
val configData = parseConfigData(configDataJson.getString("config"))
|
||||||
wireguardConfig = WireguardConfig.build {
|
return WireguardConfig.build(wireguardConfigBuilder(configData))
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun wireguardConfigBuilder(configData: Map<String, String>): WireguardConfig.Builder.() -> Unit =
|
||||||
|
{
|
||||||
configureBaseProtocol(true) {
|
configureBaseProtocol(true) {
|
||||||
configData["Address"]?.let { addAddress(InetNetwork.parse(it)) }
|
configData["Address"]?.let { addAddress(InetNetwork.parse(it)) }
|
||||||
configData["DNS"]?.split(",")?.map { dns ->
|
configData["DNS"]?.split(",")?.map { dns ->
|
||||||
|
@ -64,10 +107,8 @@ class Wireguard(context: Context) : Protocol(context) {
|
||||||
configData["PublicKey"]?.let { setPublicKeyHex(it.base64ToHex()) }
|
configData["PublicKey"]?.let { setPublicKeyHex(it.base64ToHex()) }
|
||||||
configData["PresharedKey"]?.let { setPreSharedKeyHex(it.base64ToHex()) }
|
configData["PresharedKey"]?.let { setPreSharedKeyHex(it.base64ToHex()) }
|
||||||
}
|
}
|
||||||
this.config = wireguardConfig.baseProtocolConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseConfigData(data: String): Map<String, String> {
|
protected fun parseConfigData(data: String): Map<String, String> {
|
||||||
val parsedData = TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER)
|
val parsedData = TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER)
|
||||||
data.lineSequence()
|
data.lineSequence()
|
||||||
.filter { it.isNotEmpty() && !it.startsWith('[') }
|
.filter { it.isNotEmpty() && !it.startsWith('[') }
|
||||||
|
@ -78,20 +119,20 @@ class Wireguard(context: Context) : Protocol(context) {
|
||||||
return parsedData
|
return parsedData
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startVpn(vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
||||||
if (tunnelHandle != -1) {
|
if (tunnelHandle != -1) {
|
||||||
Log.w(TAG, "Tunnel already up")
|
Log.w(TAG, "Tunnel already up")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buildVpnInterface(vpnBuilder)
|
buildVpnInterface(config, vpnBuilder)
|
||||||
|
|
||||||
vpnBuilder.establish().use { tunFd ->
|
vpnBuilder.establish().use { tunFd ->
|
||||||
if (tunFd == null) {
|
if (tunFd == null) {
|
||||||
throw VpnStartException("Create VPN interface: permission not granted or revoked")
|
throw VpnStartException("Create VPN interface: permission not granted or revoked")
|
||||||
}
|
}
|
||||||
Log.v(TAG, "Wg-go backend ${GoBackend.wgVersion()}")
|
Log.v(TAG, "Wg-go backend ${GoBackend.wgVersion()}")
|
||||||
tunnelHandle = GoBackend.wgTurnOn(VPN_SESSION_NAME, tunFd.detachFd(), wireguardConfig.toWgUserspaceString())
|
tunnelHandle = GoBackend.wgTurnOn(ifName, tunFd.detachFd(), config.toWgUserspaceString())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tunnelHandle < 0) {
|
if (tunnelHandle < 0) {
|
||||||
|
|
|
@ -6,17 +6,17 @@ import org.amnezia.vpn.protocol.ProtocolConfig
|
||||||
|
|
||||||
internal const val WIREGUARD_DEFAULT_MTU = 1280
|
internal const val WIREGUARD_DEFAULT_MTU = 1280
|
||||||
|
|
||||||
data class WireguardConfig(
|
open class WireguardConfig protected constructor(
|
||||||
val baseProtocolConfig: ProtocolConfig,
|
protocolConfigBuilder: ProtocolConfig.Builder,
|
||||||
val endpoint: InetEndpoint,
|
val endpoint: InetEndpoint,
|
||||||
val persistentKeepalive: Int,
|
val persistentKeepalive: Int,
|
||||||
val publicKeyHex: String,
|
val publicKeyHex: String,
|
||||||
val preSharedKeyHex: String,
|
val preSharedKeyHex: String,
|
||||||
val privateKeyHex: String
|
val privateKeyHex: String
|
||||||
) {
|
) : ProtocolConfig(protocolConfigBuilder) {
|
||||||
|
|
||||||
private constructor(builder: Builder) : this(
|
protected constructor(builder: Builder) : this(
|
||||||
builder.baseProtocolConfig,
|
builder.protocolConfigBuilder,
|
||||||
builder.endpoint,
|
builder.endpoint,
|
||||||
builder.persistentKeepalive,
|
builder.persistentKeepalive,
|
||||||
builder.publicKeyHex,
|
builder.publicKeyHex,
|
||||||
|
@ -24,11 +24,11 @@ data class WireguardConfig(
|
||||||
builder.privateKeyHex
|
builder.privateKeyHex
|
||||||
)
|
)
|
||||||
|
|
||||||
fun toWgUserspaceString(): String = with(StringBuilder()) {
|
open fun toWgUserspaceString(): String = with(StringBuilder()) {
|
||||||
appendLine("private_key=$privateKeyHex")
|
appendLine("private_key=$privateKeyHex")
|
||||||
appendLine("replace_peers=true")
|
appendLine("replace_peers=true")
|
||||||
appendLine("public_key=$publicKeyHex")
|
appendLine("public_key=$publicKeyHex")
|
||||||
baseProtocolConfig.routes.forEach { route ->
|
routes.forEach { route ->
|
||||||
appendLine("allowed_ip=$route")
|
appendLine("allowed_ip=$route")
|
||||||
}
|
}
|
||||||
appendLine("endpoint=$endpoint")
|
appendLine("endpoint=$endpoint")
|
||||||
|
@ -39,7 +39,7 @@ data class WireguardConfig(
|
||||||
}
|
}
|
||||||
|
|
||||||
class Builder {
|
class Builder {
|
||||||
internal lateinit var baseProtocolConfig: ProtocolConfig
|
internal lateinit var protocolConfigBuilder: ProtocolConfig.Builder
|
||||||
private set
|
private set
|
||||||
|
|
||||||
internal lateinit var endpoint: InetEndpoint
|
internal lateinit var endpoint: InetEndpoint
|
||||||
|
@ -58,7 +58,7 @@ data class WireguardConfig(
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun configureBaseProtocol(blockingMode: Boolean, block: ProtocolConfig.Builder.() -> Unit) = apply {
|
fun configureBaseProtocol(blockingMode: Boolean, block: ProtocolConfig.Builder.() -> Unit) = apply {
|
||||||
baseProtocolConfig = ProtocolConfig.Builder(blockingMode).apply(block).build()
|
protocolConfigBuilder = ProtocolConfig.Builder(blockingMode).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setEndpoint(endpoint: InetEndpoint) = apply { this.endpoint = endpoint }
|
fun setEndpoint(endpoint: InetEndpoint) = apply { this.endpoint = endpoint }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue