added saving allowed_ips to the array of strings for old configs (#926)

* added saving allowed_ips to the array of strings for old configs

* Remove config string processing, add getting all AWG, WG parameters from JSON

* fixed checking of default routes when adding split tunneling from the application

* added check when processing siteBasedSplitTunneling
This commit is contained in:
Nethius 2024-09-13 13:53:21 +04:00 committed by GitHub
parent 96566f04ee
commit aae3cdcac1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 120 additions and 273 deletions

View file

@ -1,81 +1,28 @@
package org.amnezia.vpn.protocol.awg
import org.amnezia.vpn.protocol.wireguard.Wireguard
import org.amnezia.vpn.util.optStringOrNull
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"))
val configData = config.getJSONObject("awg_config_data")
return AwgConfig.build {
configWireguard(configData, configDataJson)
configWireguard(config, configData)
configSplitTunneling(config)
configAppSplitTunneling(config)
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()) }
configData.optStringOrNull("Jc")?.let { setJc(it.toInt()) }
configData.optStringOrNull("Jmin")?.let { setJmin(it.toInt()) }
configData.optStringOrNull("Jmax")?.let { setJmax(it.toInt()) }
configData.optStringOrNull("S1")?.let { setS1(it.toInt()) }
configData.optStringOrNull("S2")?.let { setS2(it.toInt()) }
configData.optStringOrNull("H1")?.let { setH1(it.toLong()) }
configData.optStringOrNull("H2")?.let { setH2(it.toLong()) }
configData.optStringOrNull("H3")?.let { setH3(it.toLong()) }
configData.optStringOrNull("H4")?.let { setH4(it.toLong()) }
}
}
}

View file

@ -5,36 +5,6 @@ import net.openvpn.ovpn3.ClientAPI_Config
import org.amnezia.vpn.protocol.openvpn.OpenVpn
import org.json.JSONObject
/**
* Config Example:
* {
* "protocol": "cloak",
* "description": "Server 1",
* "dns1": "1.1.1.1",
* "dns2": "1.0.0.1",
* "hostName": "100.100.100.0",
* "splitTunnelSites": [
* ],
* "splitTunnelType": 0,
* "openvpn_config_data": {
* "config": "openVpnConfig"
* }
* "cloak_config_data": {
* "BrowserSig": "chrome",
* "EncryptionMethod": "aes-gcm",
* "NumConn": 1,
* "ProxyMethod": "openvpn",
* "PublicKey": "PublicKey=",
* "RemoteHost": "100.100.100.0",
* "RemotePort": "443",
* "ServerName": "servername",
* "StreamTimeout": 300,
* "Transport": "direct",
* "UID": "UID="
* }
* }
*/
class Cloak : OpenVpn() {
override fun parseConfig(config: JSONObject): ClientAPI_Config {

View file

@ -16,23 +16,6 @@ import org.amnezia.vpn.util.net.getLocalNetworks
import org.amnezia.vpn.util.net.parseInetAddress
import org.json.JSONObject
/**
* Config Example:
* {
* "protocol": "openvpn",
* "description": "Server 1",
* "dns1": "1.1.1.1",
* "dns2": "1.0.0.1",
* "hostName": "100.100.100.0",
* "splitTunnelSites": [
* ],
* "splitTunnelType": 0,
* "openvpn_config_data": {
* "config": "openVpnConfig"
* }
* }
*/
open class OpenVpn : Protocol() {
private var openVpnClient: OpenVpnClient? = null

View file

@ -0,0 +1,9 @@
package org.amnezia.vpn.util
import org.json.JSONArray
import org.json.JSONObject
inline fun <reified T> JSONArray.asSequence(): Sequence<T> =
(0..<length()).asSequence().map { get(it) as T }
fun JSONObject.optStringOrNull(name: String) = optString(name).ifEmpty { null }

View file

@ -14,46 +14,13 @@ import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.Statistics
import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.asSequence
import org.amnezia.vpn.util.net.InetEndpoint
import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.parseInetAddress
import org.amnezia.vpn.util.optStringOrNull
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"
open class Wireguard : Protocol() {
@ -123,60 +90,49 @@ open class Wireguard : Protocol() {
.inputStream.reader().readText()
protected open fun parseConfig(config: JSONObject): WireguardConfig {
val configDataJson = config.getJSONObject("wireguard_config_data")
val configData = parseConfigData(configDataJson.getString("config"))
val configData = config.getJSONObject("wireguard_config_data")
return WireguardConfig.build {
configWireguard(configData, configDataJson)
configWireguard(config, configData)
configSplitTunneling(config)
configAppSplitTunneling(config)
}
}
protected fun WireguardConfig.Builder.configWireguard(configData: Map<String, String>, configDataJson: JSONObject) {
configData["Address"]?.split(",")?.map { address ->
protected fun WireguardConfig.Builder.configWireguard(config: JSONObject, configData: JSONObject) {
configData.getString("client_ip").split(",").map { address ->
InetNetwork.parse(address.trim())
}?.forEach(::addAddress)
}.forEach(::addAddress)
configData["DNS"]?.split(",")?.map { dns ->
parseInetAddress(dns.trim())
}?.forEach(::addDnsServer)
config.optStringOrNull("dns1")?.let { dns ->
addDnsServer(parseInetAddress(dns.trim()))
}
config.optStringOrNull("dns2")?.let { dns ->
addDnsServer(parseInetAddress(dns.trim()))
}
val defRoutes = hashSetOf(
InetNetwork("0.0.0.0", 0),
InetNetwork("::", 0)
)
val routes = hashSetOf<InetNetwork>()
configData["AllowedIPs"]?.split(",")?.map { route ->
configData.getJSONArray("allowed_ips").asSequence<String>().map { route ->
InetNetwork.parse(route.trim())
}?.forEach(routes::add)
}.forEach(routes::add)
// if the allowed IPs list contains at least one non-default route, disable global split tunneling
if (routes.any { it !in defRoutes }) disableSplitTunneling()
addRoutes(routes)
configDataJson.optString("mtu").let { mtu ->
if (mtu.isNotEmpty()) {
setMtu(mtu.toInt())
} else {
configData["MTU"]?.let { setMtu(it.toInt()) }
}
}
configData.optStringOrNull("mtu")?.let { setMtu(it.toInt()) }
configData["Endpoint"]?.let { setEndpoint(InetEndpoint.parse(it)) }
configData["PersistentKeepalive"]?.let { setPersistentKeepalive(it.toInt()) }
configData["PrivateKey"]?.let { setPrivateKeyHex(it.base64ToHex()) }
configData["PublicKey"]?.let { setPublicKeyHex(it.base64ToHex()) }
configData["PresharedKey"]?.let { setPreSharedKeyHex(it.base64ToHex()) }
}
val host = configData.getString("hostName").let { parseInetAddress(it.trim()) }
val port = configData.getInt("port")
setEndpoint(InetEndpoint(host, port))
protected fun parseConfigData(data: String): Map<String, String> {
val parsedData = TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER)
data.lineSequence()
.filter { it.isNotEmpty() && !it.startsWith('[') }
.forEach { line ->
val attr = line.split("=", limit = 2)
parsedData[attr.first().trim()] = attr.last().trim()
}
return parsedData
configData.optStringOrNull("persistent_keep_alive")?.let { setPersistentKeepalive(it.toInt()) }
configData.getString("client_priv_key").let { setPrivateKeyHex(it.base64ToHex()) }
configData.getString("server_pub_key").let { setPublicKeyHex(it.base64ToHex()) }
configData.optStringOrNull("psk_key")?.let { setPreSharedKeyHex(it.base64ToHex()) }
}
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {

View file

@ -20,69 +20,6 @@ import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.parseInetAddress
import org.json.JSONObject
/**
* Config example:
* {
* "appSplitTunnelType": 0,
* "config_version": 0,
* "description": "Server 1",
* "dns1": "1.1.1.1",
* "dns2": "1.0.0.1",
* "hostName": "100.100.100.0",
* "protocol": "xray",
* "splitTunnelApps": [],
* "splitTunnelSites": [],
* "splitTunnelType": 0,
* "xray_config_data": {
* "inbounds": [
* {
* "listen": "127.0.0.1",
* "port": 8080,
* "protocol": "socks",
* "settings": {
* "udp": true
* }
* }
* ],
* "log": {
* "loglevel": "error"
* },
* "outbounds": [
* {
* "protocol": "vless",
* "settings": {
* "vnext": [
* {
* "address": "100.100.100.0",
* "port": 443,
* "users": [
* {
* "encryption": "none",
* "flow": "xtls-rprx-vision",
* "id": "id"
* }
* ]
* }
* ]
* },
* "streamSettings": {
* "network": "tcp",
* "realitySettings": {
* "fingerprint": "chrome",
* "publicKey": "publicKey",
* "serverName": "google.com",
* "shortId": "id",
* "spiderX": ""
* },
* "security": "reality"
* }
* }
* ]
* }
* }
*
*/
private const val TAG = "Xray"
private const val LIBXRAY_TAG = "libXray"