mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
Compare commits
8 Commits
shiroow-pa
...
refactorin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc4573ce75 | ||
|
|
ab6f96bb00 | ||
|
|
23a8dad37f | ||
|
|
b5c121258a | ||
|
|
2c45c46a45 | ||
|
|
70daf4c236 | ||
|
|
1ece6fe418 | ||
|
|
b075676be6 |
@@ -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()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
9
client/android/utils/src/main/kotlin/JsonExt.kt
Normal file
9
client/android/utils/src/main/kotlin/JsonExt.kt
Normal 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 }
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.amnezia.vpn.protocol.wireguard
|
||||
|
||||
import android.net.VpnService.Builder
|
||||
import java.util.TreeMap
|
||||
import org.amnezia.awg.GoBackend
|
||||
import org.amnezia.vpn.protocol.Protocol
|
||||
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
|
||||
@@ -9,46 +8,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() {
|
||||
@@ -86,60 +52,49 @@ open class Wireguard : Protocol() {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -187,6 +187,10 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials
|
||||
jConfig[config_key::server_pub_key] = connData.serverPubKey;
|
||||
jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||
|
||||
jConfig[config_key::persistent_keep_alive] = 25;
|
||||
QJsonArray allowedIps { "0.0.0.0/0" };
|
||||
jConfig[config_key::allowed_ips] = allowedIps;
|
||||
|
||||
jConfig[config_key::clientId] = connData.clientPubKey;
|
||||
|
||||
return QJsonDocument(jConfig).toJson();
|
||||
|
||||
@@ -149,9 +149,13 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||
QJsonArray jsAllowedIPAddesses;
|
||||
|
||||
QJsonArray plainAllowedIP = wgConfig.value(amnezia::config_key::allowed_ips).toArray();
|
||||
QJsonArray defaultAllowedIP = QJsonArray::fromStringList(QString("0.0.0.0/0, ::/0").split(","));
|
||||
|
||||
if (plainAllowedIP != defaultAllowedIP && !plainAllowedIP.isEmpty()) {
|
||||
bool allowSplitTunnelFromAppSettings = false;
|
||||
if (!plainAllowedIP.isEmpty() && plainAllowedIP.contains("0.0.0.0/0")) {
|
||||
allowSplitTunnelFromAppSettings = true;
|
||||
}
|
||||
|
||||
if (!allowSplitTunnelFromAppSettings) {
|
||||
// Use AllowedIP list from WG config because of higher priority
|
||||
for (auto v : plainAllowedIP) {
|
||||
QString ipRange = v.toString();
|
||||
@@ -170,7 +174,6 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Use APP split tunnel
|
||||
if (splitTunnelType == 0 || splitTunnelType == 2) {
|
||||
QJsonObject range_ipv4;
|
||||
|
||||
@@ -22,7 +22,7 @@ extension PacketTunnelProvider {
|
||||
|
||||
if tunnelConfiguration.peers.first!.allowedIPs
|
||||
.map({ $0.stringRepresentation })
|
||||
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
||||
.contains("0.0.0.0/0") {
|
||||
if wgConfig.splitTunnelType == 1 {
|
||||
for index in tunnelConfiguration.peers.indices {
|
||||
tunnelConfiguration.peers[index].allowedIPs.removeAll()
|
||||
|
||||
@@ -491,7 +491,7 @@ bool IosController::setupWireGuard()
|
||||
if (config.contains(config_key::allowed_ips) && config[config_key::allowed_ips].isArray()) {
|
||||
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
||||
} else {
|
||||
QJsonArray allowed_ips { "0.0.0.0/0", "::/0" };
|
||||
QJsonArray allowed_ips { "0.0.0.0/0" };
|
||||
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
||||
}
|
||||
|
||||
@@ -576,7 +576,7 @@ bool IosController::setupAwg()
|
||||
if (config.contains(config_key::allowed_ips) && config[config_key::allowed_ips].isArray()) {
|
||||
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
||||
} else {
|
||||
QJsonArray allowed_ips { "0.0.0.0/0", "::/0" };
|
||||
QJsonArray allowed_ips { "0.0.0.0/0" };
|
||||
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,6 @@ H4 = $TRANSPORT_PACKET_MAGIC_HEADER
|
||||
[Peer]
|
||||
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
||||
PresharedKey = $WIREGUARD_PSK
|
||||
AllowedIPs = 0.0.0.0/0, ::/0
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = $SERVER_IP_ADDRESS:$AWG_SERVER_PORT
|
||||
PersistentKeepalive = 25
|
||||
|
||||
@@ -6,6 +6,6 @@ PrivateKey = $WIREGUARD_CLIENT_PRIVATE_KEY
|
||||
[Peer]
|
||||
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
||||
PresharedKey = $WIREGUARD_PSK
|
||||
AllowedIPs = 0.0.0.0/0, ::/0
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = $SERVER_IP_ADDRESS:$WIREGUARD_SERVER_PORT
|
||||
PersistentKeepalive = 25
|
||||
|
||||
@@ -395,7 +395,11 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||
lastConfig[config_key::mtu] = configMap.value("MTU");
|
||||
}
|
||||
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(","));
|
||||
if (!configMap.value("PersistentKeepalive").isEmpty()) {
|
||||
lastConfig[config_key::persistent_keep_alive] = configMap.value("PersistentKeepalive");
|
||||
}
|
||||
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(", "));
|
||||
|
||||
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
|
||||
|
||||
|
||||
@@ -694,7 +694,16 @@ bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
|
||||
QJsonObject serverProtocolConfig = container.value(ContainerProps::containerTypeToString(defaultContainer)).toObject();
|
||||
QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString();
|
||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(clientProtocolConfigString.toUtf8()).object();
|
||||
return (clientProtocolConfigString.contains("AllowedIPs") && !clientProtocolConfigString.contains("AllowedIPs = 0.0.0.0/0, ::/0"))
|
||||
QString nativeProtocolConfigString = clientProtocolConfig.value(config_key::config).toString();
|
||||
|
||||
const static QRegularExpression allowedIpsRegExp("AllowedIPs\\s*=\\s*([^\n]*)");
|
||||
QRegularExpressionMatch allowedIpsMatch = allowedIpsRegExp.match(nativeProtocolConfigString);
|
||||
QString allowedIpsString;
|
||||
if (allowedIpsMatch.hasCaptured(1)) {
|
||||
allowedIpsString = allowedIpsMatch.captured(1);
|
||||
}
|
||||
|
||||
return !allowedIpsString.contains("0.0.0.0/0")
|
||||
|| (!clientProtocolConfig.value(config_key::allowed_ips).toArray().isEmpty()
|
||||
&& !clientProtocolConfig.value(config_key::allowed_ips).toArray().contains("0.0.0.0/0"));
|
||||
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn
|
||||
|
||||
@@ -11,7 +11,7 @@ import "../Config"
|
||||
DrawerType2 {
|
||||
id: root
|
||||
|
||||
property bool isAppSplitTinnelingEnabled: Qt.platform.os === "windows" || Qt.platform.os === "android"
|
||||
property bool isAppSplitTunnelingEnabled: Qt.platform.os === "windows" || Qt.platform.os === "android"
|
||||
|
||||
anchors.fill: parent
|
||||
expandedHeight: parent.height * 0.9
|
||||
@@ -24,6 +24,8 @@ DrawerType2 {
|
||||
anchors.right: parent.right
|
||||
spacing: 0
|
||||
|
||||
property bool isServerSplitTunnelingEnabled: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
enabled: !GC.isMobile()
|
||||
@@ -53,7 +55,7 @@ DrawerType2 {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling
|
||||
visible: isServerSplitTunnelingEnabled
|
||||
|
||||
text: qsTr("Split tunneling on the server")
|
||||
descriptionText: qsTr("Enabled \nCan't be disabled for current server")
|
||||
@@ -68,7 +70,7 @@ DrawerType2 {
|
||||
}
|
||||
|
||||
DividerType {
|
||||
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling
|
||||
visible: isServerSplitTunnelingEnabled
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
@@ -95,7 +97,7 @@ DrawerType2 {
|
||||
|
||||
LabelWithButtonType {
|
||||
id: appSplitTunnelingSwitch
|
||||
visible: isAppSplitTinnelingEnabled
|
||||
visible: isAppSplitTunnelingEnabled
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -112,7 +114,7 @@ DrawerType2 {
|
||||
}
|
||||
|
||||
DividerType {
|
||||
visible: isAppSplitTinnelingEnabled
|
||||
visible: isAppSplitTunnelingEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,43 +291,68 @@ void VpnConnection::appendKillSwitchConfig()
|
||||
|
||||
void VpnConnection::appendSplitTunnelingConfig()
|
||||
{
|
||||
if (m_vpnConfiguration.value(config_key::configVersion).toInt()) {
|
||||
auto protocolName = m_vpnConfiguration.value(config_key::vpnproto).toString();
|
||||
if (protocolName == ProtocolProps::protoToString(Proto::Awg)) {
|
||||
auto configData = m_vpnConfiguration.value(protocolName + "_config_data").toObject();
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configData.value("allowed_ips").toString().split(","));
|
||||
QJsonArray defaultAllowedIP = QJsonArray::fromStringList(QString("0.0.0.0/0, ::/0").split(","));
|
||||
|
||||
if (allowedIpsJsonArray != defaultAllowedIP) {
|
||||
allowedIpsJsonArray.append(m_vpnConfiguration.value(config_key::dns1).toString());
|
||||
allowedIpsJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString());
|
||||
|
||||
m_vpnConfiguration.insert(config_key::splitTunnelType, Settings::RouteMode::VpnOnlyForwardSites);
|
||||
m_vpnConfiguration.insert(config_key::splitTunnelSites, allowedIpsJsonArray);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Settings::RouteMode routeMode = Settings::RouteMode::VpnAllSites;
|
||||
QJsonArray sitesJsonArray;
|
||||
if (m_settings->isSitesSplitTunnelingEnabled()) {
|
||||
routeMode = m_settings->routeMode();
|
||||
|
||||
auto sites = m_settings->getVpnIps(routeMode);
|
||||
for (const auto &site : sites) {
|
||||
sitesJsonArray.append(site);
|
||||
}
|
||||
|
||||
// Allow traffic to Amnezia DNS
|
||||
if (routeMode == Settings::VpnOnlyForwardSites) {
|
||||
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns1).toString());
|
||||
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString());
|
||||
// this block is for old native configs and for old self-hosted configs
|
||||
auto protocolName = m_vpnConfiguration.value(config_key::vpnproto).toString();
|
||||
if (protocolName == ProtocolProps::protoToString(Proto::Awg) || protocolName == ProtocolProps::protoToString(Proto::WireGuard)) {
|
||||
auto configData = m_vpnConfiguration.value(protocolName + "_config_data").toObject();
|
||||
if (configData.value(config_key::allowed_ips).isString()) {
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configData.value(config_key::allowed_ips).toString().split(", "));
|
||||
configData.insert(config_key::allowed_ips, allowedIpsJsonArray);
|
||||
m_vpnConfiguration.insert(protocolName + "_config_data", configData);
|
||||
} else if (configData.value(config_key::allowed_ips).isUndefined()) {
|
||||
auto nativeConfig = configData.value(config_key::config).toString();
|
||||
auto nativeConfigLines = nativeConfig.split("\n");
|
||||
for (auto &line : nativeConfigLines) {
|
||||
if (line.contains("AllowedIPs")) {
|
||||
auto allowedIpsString = line.split(" = ");
|
||||
if (allowedIpsString.size() < 1) {
|
||||
break;
|
||||
}
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(allowedIpsString.at(1).split(", "));
|
||||
configData.insert(config_key::allowed_ips, allowedIpsJsonArray);
|
||||
m_vpnConfiguration.insert(protocolName + "_config_data", configData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_vpnConfiguration.insert(config_key::splitTunnelType, routeMode);
|
||||
m_vpnConfiguration.insert(config_key::splitTunnelSites, sitesJsonArray);
|
||||
if (configData.value(config_key::persistent_keep_alive).isUndefined()) {
|
||||
auto nativeConfig = configData.value(config_key::config).toString();
|
||||
auto nativeConfigLines = nativeConfig.split("\n");
|
||||
for (auto &line : nativeConfigLines) {
|
||||
if (line.contains("PersistentKeepalive")) {
|
||||
auto persistentKeepaliveString = line.split(" = ");
|
||||
if (persistentKeepaliveString.size() < 1) {
|
||||
break;
|
||||
}
|
||||
configData.insert(config_key::persistent_keep_alive, persistentKeepaliveString.at(1));
|
||||
m_vpnConfiguration.insert(protocolName + "_config_data", configData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Settings::RouteMode routeMode = Settings::RouteMode::VpnAllSites;
|
||||
QJsonArray sitesJsonArray;
|
||||
if (m_settings->isSitesSplitTunnelingEnabled()) {
|
||||
routeMode = m_settings->routeMode();
|
||||
|
||||
auto sites = m_settings->getVpnIps(routeMode);
|
||||
for (const auto &site : sites) {
|
||||
sitesJsonArray.append(site);
|
||||
}
|
||||
|
||||
// Allow traffic to Amnezia DNS
|
||||
if (routeMode == Settings::VpnOnlyForwardSites) {
|
||||
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns1).toString());
|
||||
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString());
|
||||
}
|
||||
}
|
||||
|
||||
m_vpnConfiguration.insert(config_key::splitTunnelType, routeMode);
|
||||
m_vpnConfiguration.insert(config_key::splitTunnelSites, sitesJsonArray);
|
||||
|
||||
Settings::AppsRouteMode appsRouteMode = Settings::AppsRouteMode::VpnAllApps;
|
||||
QJsonArray appsJsonArray;
|
||||
if (m_settings->isAppsSplitTunnelingEnabled()) {
|
||||
|
||||
Reference in New Issue
Block a user