Add AWG module

This commit is contained in:
albexk 2023-11-26 13:07:31 +03:00
parent 91f44fb394
commit 9297f877c4
11 changed files with 295 additions and 43 deletions

View file

@ -9,17 +9,51 @@ import org.amnezia.vpn.protocol.InetEndpoint
import org.amnezia.vpn.protocol.InetNetwork
import org.amnezia.vpn.protocol.Protocol
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.parseInetAddress
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"
class Wireguard(context: Context) : Protocol(context) {
open class Wireguard : Protocol() {
private var tunnelHandle: Int = -1
private lateinit var wireguardConfig: WireguardConfig
protected open val ifName: String = "amn0"
override val statistics: Statistics
get() {
@ -40,14 +74,23 @@ class Wireguard(context: Context) : Protocol(context) {
}
}
override fun initialize() {
override fun initialize(context: Context) {
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 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) {
configData["Address"]?.let { addAddress(InetNetwork.parse(it)) }
configData["DNS"]?.split(",")?.map { dns ->
@ -64,10 +107,8 @@ class Wireguard(context: Context) : Protocol(context) {
configData["PublicKey"]?.let { setPublicKeyHex(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)
data.lineSequence()
.filter { it.isNotEmpty() && !it.startsWith('[') }
@ -78,20 +119,20 @@ class Wireguard(context: Context) : Protocol(context) {
return parsedData
}
override fun startVpn(vpnBuilder: Builder, protect: (Int) -> Boolean) {
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {
if (tunnelHandle != -1) {
Log.w(TAG, "Tunnel already up")
return
}
buildVpnInterface(vpnBuilder)
buildVpnInterface(config, vpnBuilder)
vpnBuilder.establish().use { tunFd ->
if (tunFd == null) {
throw VpnStartException("Create VPN interface: permission not granted or revoked")
}
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) {

View file

@ -6,17 +6,17 @@ import org.amnezia.vpn.protocol.ProtocolConfig
internal const val WIREGUARD_DEFAULT_MTU = 1280
data class WireguardConfig(
val baseProtocolConfig: ProtocolConfig,
open class WireguardConfig protected constructor(
protocolConfigBuilder: ProtocolConfig.Builder,
val endpoint: InetEndpoint,
val persistentKeepalive: Int,
val publicKeyHex: String,
val preSharedKeyHex: String,
val privateKeyHex: String
) {
) : ProtocolConfig(protocolConfigBuilder) {
private constructor(builder: Builder) : this(
builder.baseProtocolConfig,
protected constructor(builder: Builder) : this(
builder.protocolConfigBuilder,
builder.endpoint,
builder.persistentKeepalive,
builder.publicKeyHex,
@ -24,11 +24,11 @@ data class WireguardConfig(
builder.privateKeyHex
)
fun toWgUserspaceString(): String = with(StringBuilder()) {
open fun toWgUserspaceString(): String = with(StringBuilder()) {
appendLine("private_key=$privateKeyHex")
appendLine("replace_peers=true")
appendLine("public_key=$publicKeyHex")
baseProtocolConfig.routes.forEach { route ->
routes.forEach { route ->
appendLine("allowed_ip=$route")
}
appendLine("endpoint=$endpoint")
@ -39,7 +39,7 @@ data class WireguardConfig(
}
class Builder {
internal lateinit var baseProtocolConfig: ProtocolConfig
internal lateinit var protocolConfigBuilder: ProtocolConfig.Builder
private set
internal lateinit var endpoint: InetEndpoint
@ -58,7 +58,7 @@ data class WireguardConfig(
private set
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 }