Compare commits

...

20 Commits

Author SHA1 Message Date
albexk a297ef3808 Fix name resolving on Android 2024-09-16 15:35:27 +03:00
vladimir.kuznetsov 75768425ff moved awg/wg domain name processing to WireguardProtocol 2024-09-14 13:42:05 +04:00
vladimir.kuznetsov 8f6fef8552 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/awg-wg-name-resolving 2024-09-13 23:20:13 +04:00
vladimir.kuznetsov 1f72043281 added domain name resolving when connecting via xray 2024-09-13 23:13:19 +04:00
Pokamest Nikak c6b131aa4c Bump version to 4.8.0.1 2024-09-13 18:25:04 +01:00
pokamest 5e72bf945c Merge pull request #1064 from amnezia-vpn/fix/android-window-hiding
Fix window hiding on startup on Android
2024-09-13 18:21:49 +03:00
albexk eebf7eccec Fix window hiding on startup on Android 2024-09-13 18:14:25 +03:00
pokamest 168c293bfe Merge pull request #979 from amnezia-vpn/feature/update-tap
Update TAP-Windows driver
2024-09-13 15:00:31 +03:00
Nethius aae3cdcac1 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
2024-09-13 10:53:21 +01:00
Nethius 96566f04ee feature/mtu connection config (#833)
* added the ability to change mtu for connection-only configs
* added replacing MTU with default when importing awg/wg configs in amnezia
2024-09-13 09:38:48 +01:00
vladimir.kuznetsov a050c36950 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/awg-wg-name-resolving 2024-09-11 21:48:23 +04:00
pokamest fff15fffe2 Bug fix for iOS 2024-09-11 09:51:07 -07:00
pokamest 4e5a03e7f1 Merge pull request #1059 from amnezia-vpn/chore/dev-key 2024-09-10 21:38:45 +03:00
vladimir.kuznetsov 7571bbc36e chore: added dev key to deploy workflow
- added m_isDevEnvironment initialization
2024-09-10 22:03:10 +04:00
Mykola Baibuz b83e74427e Update TAP-Windows driver 2024-08-15 19:51:49 +03:00
vladimir.kuznetsov 460f5eed31 added the ability to enter a domain name when configuring the server 2024-08-09 15:22:10 +04:00
vladimir.kuznetsov 0e4a494d4e added domain name and ipv6 processing when importing awg/wg configs 2024-08-09 15:21:38 +04:00
vladimir.kuznetsov 9184404eda Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/awg-wg-name-resolving 2024-08-09 09:20:15 +04:00
vladimir.kuznetsov 34d363d204 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/awg-wg-name-resolving 2024-08-05 09:56:42 +04:00
vladimir.kuznetsov 61d9a4fa93 added domain name resolving before connection for wg and awg protocols 2024-05-18 22:01:52 +02:00
41 changed files with 1090 additions and 571 deletions
+5
View File
@@ -16,6 +16,7 @@ jobs:
QT_VERSION: 6.6.2 QT_VERSION: 6.6.2
QIF_VERSION: 4.7 QIF_VERSION: 4.7
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps: steps:
- name: 'Install Qt' - name: 'Install Qt'
@@ -82,6 +83,7 @@ jobs:
QIF_VERSION: 4.7 QIF_VERSION: 4.7
BUILD_ARCH: 64 BUILD_ARCH: 64
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps: steps:
- name: 'Get sources' - name: 'Get sources'
@@ -144,6 +146,7 @@ jobs:
CC: cc CC: cc
CXX: c++ CXX: c++
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps: steps:
- name: 'Setup xcode' - name: 'Setup xcode'
@@ -235,6 +238,7 @@ jobs:
QT_VERSION: 6.4.3 QT_VERSION: 6.4.3
QIF_VERSION: 4.6 QIF_VERSION: 4.6
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps: steps:
- name: 'Setup xcode' - name: 'Setup xcode'
@@ -300,6 +304,7 @@ jobs:
QT_VERSION: 6.7.2 QT_VERSION: 6.7.2
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools' QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps: steps:
- name: 'Install desktop Qt' - name: 'Install desktop Qt'
+1
View File
@@ -16,6 +16,7 @@ jobs:
QT_VERSION: 6.4.1 QT_VERSION: 6.4.1
QIF_VERSION: 4.5 QIF_VERSION: 4.5
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps: steps:
- name: 'Install desktop Qt' - name: 'Install desktop Qt'
+2 -2
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN) set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 4.8.0.0 project(${PROJECT} VERSION 4.8.0.1
DESCRIPTION "AmneziaVPN" DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/" HOMEPAGE_URL "https://amnezia.org/"
) )
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}") set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 58) set(APP_ANDROID_VERSION_CODE 59)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux") set(MZ_PLATFORM_NAME "linux")
+12 -65
View File
@@ -1,81 +1,28 @@
package org.amnezia.vpn.protocol.awg package org.amnezia.vpn.protocol.awg
import org.amnezia.vpn.protocol.wireguard.Wireguard import org.amnezia.vpn.protocol.wireguard.Wireguard
import org.amnezia.vpn.util.optStringOrNull
import org.json.JSONObject 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() { class Awg : Wireguard() {
override val ifName: String = "awg0" override val ifName: String = "awg0"
override fun parseConfig(config: JSONObject): AwgConfig { override fun parseConfig(config: JSONObject): AwgConfig {
val configDataJson = config.getJSONObject("awg_config_data") val configData = config.getJSONObject("awg_config_data")
val configData = parseConfigData(configDataJson.getString("config"))
return AwgConfig.build { return AwgConfig.build {
configWireguard(configData, configDataJson) configWireguard(config, configData)
configSplitTunneling(config) configSplitTunneling(config)
configAppSplitTunneling(config) configAppSplitTunneling(config)
configData["Jc"]?.let { setJc(it.toInt()) } configData.optStringOrNull("Jc")?.let { setJc(it.toInt()) }
configData["Jmin"]?.let { setJmin(it.toInt()) } configData.optStringOrNull("Jmin")?.let { setJmin(it.toInt()) }
configData["Jmax"]?.let { setJmax(it.toInt()) } configData.optStringOrNull("Jmax")?.let { setJmax(it.toInt()) }
configData["S1"]?.let { setS1(it.toInt()) } configData.optStringOrNull("S1")?.let { setS1(it.toInt()) }
configData["S2"]?.let { setS2(it.toInt()) } configData.optStringOrNull("S2")?.let { setS2(it.toInt()) }
configData["H1"]?.let { setH1(it.toLong()) } configData.optStringOrNull("H1")?.let { setH1(it.toLong()) }
configData["H2"]?.let { setH2(it.toLong()) } configData.optStringOrNull("H2")?.let { setH2(it.toLong()) }
configData["H3"]?.let { setH3(it.toLong()) } configData.optStringOrNull("H3")?.let { setH3(it.toLong()) }
configData["H4"]?.let { setH4(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.amnezia.vpn.protocol.openvpn.OpenVpn
import org.json.JSONObject 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() { class Cloak : OpenVpn() {
override fun parseConfig(config: JSONObject): ClientAPI_Config { 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.amnezia.vpn.util.net.parseInetAddress
import org.json.JSONObject 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() { open class OpenVpn : Protocol() {
private var openVpnClient: OpenVpnClient? = null private var openVpnClient: OpenVpnClient? = null
@@ -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 }
@@ -35,7 +35,7 @@ fun getLocalNetworks(context: Context, ipv6: Boolean): List<InetNetwork> {
return emptyList() return emptyList()
} }
fun parseInetAddress(address: String): InetAddress = parseNumericAddressCompat(address) fun parseInetAddress(address: String): InetAddress = InetAddress.getByName(address)
private val parseNumericAddressCompat: (String) -> InetAddress = private val parseNumericAddressCompat: (String) -> InetAddress =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
@@ -14,46 +14,13 @@ import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.Statistics import org.amnezia.vpn.protocol.Statistics
import org.amnezia.vpn.protocol.VpnStartException import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.util.Log 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.InetEndpoint
import org.amnezia.vpn.util.net.InetNetwork import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.parseInetAddress import org.amnezia.vpn.util.net.parseInetAddress
import org.amnezia.vpn.util.optStringOrNull
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"
open class Wireguard : Protocol() { open class Wireguard : Protocol() {
@@ -123,60 +90,49 @@ open class Wireguard : Protocol() {
.inputStream.reader().readText() .inputStream.reader().readText()
protected open fun parseConfig(config: JSONObject): WireguardConfig { protected open fun parseConfig(config: JSONObject): WireguardConfig {
val configDataJson = config.getJSONObject("wireguard_config_data") val configData = config.getJSONObject("wireguard_config_data")
val configData = parseConfigData(configDataJson.getString("config"))
return WireguardConfig.build { return WireguardConfig.build {
configWireguard(configData, configDataJson) configWireguard(config, configData)
configSplitTunneling(config) configSplitTunneling(config)
configAppSplitTunneling(config) configAppSplitTunneling(config)
} }
} }
protected fun WireguardConfig.Builder.configWireguard(configData: Map<String, String>, configDataJson: JSONObject) { protected fun WireguardConfig.Builder.configWireguard(config: JSONObject, configData: JSONObject) {
configData["Address"]?.split(",")?.map { address -> configData.getString("client_ip").split(",").map { address ->
InetNetwork.parse(address.trim()) InetNetwork.parse(address.trim())
}?.forEach(::addAddress) }.forEach(::addAddress)
configData["DNS"]?.split(",")?.map { dns -> config.optStringOrNull("dns1")?.let { dns ->
parseInetAddress(dns.trim()) addDnsServer(parseInetAddress(dns.trim()))
}?.forEach(::addDnsServer) }
config.optStringOrNull("dns2")?.let { dns ->
addDnsServer(parseInetAddress(dns.trim()))
}
val defRoutes = hashSetOf( val defRoutes = hashSetOf(
InetNetwork("0.0.0.0", 0), InetNetwork("0.0.0.0", 0),
InetNetwork("::", 0) InetNetwork("::", 0)
) )
val routes = hashSetOf<InetNetwork>() val routes = hashSetOf<InetNetwork>()
configData["AllowedIPs"]?.split(",")?.map { route -> configData.getJSONArray("allowed_ips").asSequence<String>().map { route ->
InetNetwork.parse(route.trim()) 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 the allowed IPs list contains at least one non-default route, disable global split tunneling
if (routes.any { it !in defRoutes }) disableSplitTunneling() if (routes.any { it !in defRoutes }) disableSplitTunneling()
addRoutes(routes) addRoutes(routes)
configDataJson.optString("mtu").let { mtu -> configData.optStringOrNull("mtu")?.let { setMtu(it.toInt()) }
if (mtu.isNotEmpty()) {
setMtu(mtu.toInt())
} else {
configData["MTU"]?.let { setMtu(it.toInt()) }
}
}
configData["Endpoint"]?.let { setEndpoint(InetEndpoint.parse(it)) } val host = configData.getString("hostName").let { parseInetAddress(it.trim()) }
configData["PersistentKeepalive"]?.let { setPersistentKeepalive(it.toInt()) } val port = configData.getInt("port")
configData["PrivateKey"]?.let { setPrivateKeyHex(it.base64ToHex()) } setEndpoint(InetEndpoint(host, port))
configData["PublicKey"]?.let { setPublicKeyHex(it.base64ToHex()) }
configData["PresharedKey"]?.let { setPreSharedKeyHex(it.base64ToHex()) }
}
protected fun parseConfigData(data: String): Map<String, String> { configData.optStringOrNull("persistent_keep_alive")?.let { setPersistentKeepalive(it.toInt()) }
val parsedData = TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER) configData.getString("client_priv_key").let { setPrivateKeyHex(it.base64ToHex()) }
data.lineSequence() configData.getString("server_pub_key").let { setPublicKeyHex(it.base64ToHex()) }
.filter { it.isNotEmpty() && !it.startsWith('[') } configData.optStringOrNull("psk_key")?.let { setPreSharedKeyHex(it.base64ToHex()) }
.forEach { line ->
val attr = line.split("=", limit = 2)
parsedData[attr.first().trim()] = attr.last().trim()
}
return parsedData
} }
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) { 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.amnezia.vpn.util.net.parseInetAddress
import org.json.JSONObject 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 TAG = "Xray"
private const val LIBXRAY_TAG = "libXray" 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::server_pub_key] = connData.serverPubKey;
jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu); 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", "::/0" };
jConfig[config_key::allowed_ips] = allowedIps;
jConfig[config_key::clientId] = connData.clientPubKey; jConfig[config_key::clientId] = connData.clientPubKey;
return QJsonDocument(jConfig).toJson(); return QJsonDocument(jConfig).toJson();
+1 -1
View File
@@ -44,7 +44,7 @@ private:
QString m_gatewayEndpoint; QString m_gatewayEndpoint;
QStringList m_proxyUrls; QStringList m_proxyUrls;
bool m_isDevEnvironment; bool m_isDevEnvironment = false;
}; };
#endif // APICONTROLLER_H #endif // APICONTROLLER_H
+15 -10
View File
@@ -104,7 +104,8 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
if (e) if (e)
return e; return e;
QString runner = QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash")); QString runner =
QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash"));
e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName); QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
@@ -424,7 +425,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
if (errorCode) if (errorCode)
return errorCode; return errorCode;
errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(),dockerFilePath); errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(), dockerFilePath);
if (errorCode) if (errorCode)
return errorCode; return errorCode;
@@ -435,9 +436,10 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
return ErrorCode::NoError; return ErrorCode::NoError;
}; };
errorCode = runScript(credentials, errorCode =
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)), runScript(credentials,
cbReadStdOut); replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
cbReadStdOut);
if (errorCode) if (errorCode)
return errorCode; return errorCode;
@@ -619,13 +621,15 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
// Socks5 proxy vars // Socks5 proxy vars
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } }); vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
auto username = socks5ProxyConfig.value(config_key:: userName).toString(); auto username = socks5ProxyConfig.value(config_key::userName).toString();
auto password = socks5ProxyConfig.value(config_key::password).toString(); auto password = socks5ProxyConfig.value(config_key::password).toString();
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : ""; QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
vars.append({ { "$SOCKS5_USER", socks5user } }); vars.append({ { "$SOCKS5_USER", socks5user } });
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } }); vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
QString serverIp = NetworkUtilities::getIPAddress(credentials.hostName); QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::WireGuard && container != DockerContainer::Xray)
? NetworkUtilities::getIPAddress(credentials.hostName)
: credentials.hostName;
if (!serverIp.isEmpty()) { if (!serverIp.isEmpty()) {
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } }); vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
} else { } else {
@@ -711,7 +715,8 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
udpProtoScript.append("' | grep -i udp"); udpProtoScript.append("' | grep -i udp");
tcpProtoScript.append(" | grep LISTEN"); tcpProtoScript.append(" | grep LISTEN");
ErrorCode errorCode = runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); ErrorCode errorCode =
runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
@@ -100,7 +100,13 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QStr
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString); protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); if (container == DockerContainer::Awg || container == DockerContainer::WireGuard) {
// add mtu for old configs
if (vpnConfigData[config_key::mtu].toString().isEmpty()) {
vpnConfigData[config_key::mtu] = container == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
}
}
vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData); vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData);
} }
+4 -1
View File
@@ -109,7 +109,10 @@ QStringList NetworkUtilities::summarizeRoutes(const QStringList &ips, const QStr
QString NetworkUtilities::getIPAddress(const QString &host) QString NetworkUtilities::getIPAddress(const QString &host)
{ {
if (ipAddressRegExp().match(host).hasMatch()) { QHostAddress address(host);
if (QAbstractSocket::IPv4Protocol == address.protocol()) {
return host;
} else if (QAbstractSocket::IPv6Protocol == address.protocol()) {
return host; return host;
} }
+1 -1
View File
@@ -149,7 +149,7 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
QJsonArray jsAllowedIPAddesses; QJsonArray jsAllowedIPAddesses;
QJsonArray plainAllowedIP = wgConfig.value(amnezia::config_key::allowed_ips).toArray(); QJsonArray plainAllowedIP = wgConfig.value(amnezia::config_key::allowed_ips).toArray();
QJsonArray defaultAllowedIP = QJsonArray::fromStringList(QString("0.0.0.0/0, ::/0").split(",")); QJsonArray defaultAllowedIP = { "0.0.0.0/0", "::/0" };
if (plainAllowedIP != defaultAllowedIP && !plainAllowedIP.isEmpty()) { if (plainAllowedIP != defaultAllowedIP && !plainAllowedIP.isEmpty()) {
// Use AllowedIP list from WG config because of higher priority // Use AllowedIP list from WG config because of higher priority
+1 -4
View File
@@ -351,8 +351,6 @@ void IosController::vpnStatusDidChange(void *pNotification)
} }
} }
} }
} else {
qDebug() << "Disconnect error is absent";
} }
}]; }];
} else { } else {
@@ -835,7 +833,7 @@ QString IosController::openFile() {
void IosController::requestInetAccess() { void IosController::requestInetAccess() {
NSURL *url = [NSURL URLWithString:@"http://captive.apple.com/generate_204"]; NSURL *url = [NSURL URLWithString:@"http://captive.apple.com/generate_204"];
if (url) { if (!url) {
qDebug() << "IosController::requestInetAccess URL error"; qDebug() << "IosController::requestInetAccess URL error";
return; return;
} }
@@ -847,7 +845,6 @@ void IosController::requestInetAccess() {
} else { } else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
QString responseBody = QString::fromUtf8((const char*)data.bytes, data.length); QString responseBody = QString::fromUtf8((const char*)data.bytes, data.length);
qDebug() << "IosController::requestInetAccess server response:" << httpResponse.statusCode << "\n\n" <<responseBody;
} }
}]; }];
[task resume]; [task resume];
+7 -2
View File
@@ -4,9 +4,8 @@
#include <QTcpSocket> #include <QTcpSocket>
#include <QThread> #include <QThread>
#include "logger.h"
#include "utilities.h"
#include "wireguardprotocol.h" #include "wireguardprotocol.h"
#include "core/networkUtilities.h"
#include "mozilla/localsocketcontroller.h" #include "mozilla/localsocketcontroller.h"
@@ -37,6 +36,12 @@ void WireguardProtocol::stop()
ErrorCode WireguardProtocol::startMzImpl() ErrorCode WireguardProtocol::startMzImpl()
{ {
QString protocolName = m_rawConfig.value("protocol").toString();
QJsonObject vpnConfigData = m_rawConfig.value(protocolName + "_config_data").toObject();
vpnConfigData[config_key::hostName] = NetworkUtilities::getIPAddress(vpnConfigData.value(config_key::hostName).toString());
m_rawConfig.insert(protocolName + "_config_data", vpnConfigData);
m_rawConfig[config_key::hostName] = NetworkUtilities::getIPAddress(m_rawConfig[config_key::hostName].toString());
m_impl->activate(m_rawConfig); m_impl->activate(m_rawConfig);
return ErrorCode::NoError; return ErrorCode::NoError;
} }
+5 -2
View File
@@ -43,7 +43,9 @@ ErrorCode XrayProtocol::start()
m_xrayCfgFile.setAutoRemove(false); m_xrayCfgFile.setAutoRemove(false);
#endif #endif
m_xrayCfgFile.open(); m_xrayCfgFile.open();
m_xrayCfgFile.write(QJsonDocument(m_xrayConfig).toJson()); QString config = QJsonDocument(m_xrayConfig).toJson();
config.replace(m_remoteHost, m_remoteAddress);
m_xrayCfgFile.write(config.toUtf8());
m_xrayCfgFile.close(); m_xrayCfgFile.close();
QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json"; QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json";
@@ -238,7 +240,8 @@ void XrayProtocol::readXrayConfiguration(const QJsonObject &configuration)
} }
m_xrayConfig = xrayConfiguration; m_xrayConfig = xrayConfiguration;
m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt(); m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt();
m_remoteAddress = configuration.value(amnezia::config_key::hostName).toString(); m_remoteHost = configuration.value(amnezia::config_key::hostName).toString();
m_remoteAddress = NetworkUtilities::getIPAddress(m_remoteHost);
m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt(); m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt();
m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString(); m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString();
m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString(); m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString();
+1
View File
@@ -26,6 +26,7 @@ private:
static QString tun2SocksExecPath(); static QString tun2SocksExecPath();
private: private:
int m_localPort; int m_localPort;
QString m_remoteHost;
QString m_remoteAddress; QString m_remoteAddress;
int m_routeMode; int m_routeMode;
QJsonObject m_configData; QJsonObject m_configData;
+2
View File
@@ -199,6 +199,8 @@
<file>server_scripts/socks5_proxy/Dockerfile</file> <file>server_scripts/socks5_proxy/Dockerfile</file>
<file>server_scripts/socks5_proxy/configure_container.sh</file> <file>server_scripts/socks5_proxy/configure_container.sh</file>
<file>server_scripts/socks5_proxy/start.sh</file> <file>server_scripts/socks5_proxy/start.sh</file>
<file>ui/qml/Pages2/PageProtocolAwgClientSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml</file>
<file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file> <file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
<file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file> <file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file>
<file>ui/qml/Controls2/CardWithIconsType.qml</file> <file>ui/qml/Controls2/CardWithIconsType.qml</file>
+1 -1
View File
@@ -13,5 +13,5 @@ sudo docker network connect amnezia-dns-net $CONTAINER_NAME
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi' sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
# Prevent to route packets outside of the container in case if server behind of the NAT # Prevent to route packets outside of the container in case if server behind of the NAT
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up" #sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
+1 -1
View File
@@ -3,7 +3,7 @@
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts # This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
echo "Container startup" echo "Container startup"
ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up #ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
+61 -22
View File
@@ -4,12 +4,12 @@
#include <QFileInfo> #include <QFileInfo>
#include <QQuickItem> #include <QQuickItem>
#include <QRandomGenerator> #include <QRandomGenerator>
#include <QUrlQuery>
#include <QStandardPaths> #include <QStandardPaths>
#include <QUrlQuery>
#include "utilities.h"
#include "core/serialization/serialization.h"
#include "core/errorstrings.h" #include "core/errorstrings.h"
#include "core/serialization/serialization.h"
#include "utilities.h"
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
@@ -96,36 +96,40 @@ bool ImportController::extractConfigFromData(QString data)
if (config.startsWith("vless://")) { if (config.startsWith("vless://")) {
m_configType = ConfigTypes::Xray; m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
if (config.startsWith("vmess://") && config.contains("@")) { if (config.startsWith("vmess://") && config.contains("@")) {
m_configType = ConfigTypes::Xray; m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
if (config.startsWith("vmess://")) { if (config.startsWith("vmess://")) {
m_configType = ConfigTypes::Xray; m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
if (config.startsWith("trojan://")) { if (config.startsWith("trojan://")) {
m_configType = ConfigTypes::Xray; m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
if (config.startsWith("ss://") && !config.contains("plugin=")) { if (config.startsWith("ss://") && !config.contains("plugin=")) {
m_configType = ConfigTypes::ShadowSocks; m_configType = ConfigTypes::ShadowSocks;
m_config = extractXrayConfig(Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
@@ -173,6 +177,7 @@ bool ImportController::extractConfigFromData(QString data)
} }
case ConfigTypes::Amnezia: { case ConfigTypes::Amnezia: {
m_config = QJsonDocument::fromJson(config.toUtf8()).object(); m_config = QJsonDocument::fromJson(config.toUtf8()).object();
processAmneziaConfig(m_config);
if (!m_config.empty()) { if (!m_config.empty()) {
checkForMaliciousStrings(m_config); checkForMaliciousStrings(m_config);
return true; return true;
@@ -353,20 +358,19 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
QJsonObject lastConfig; QJsonObject lastConfig;
lastConfig[config_key::config] = data; lastConfig[config_key::config] = data;
const static QRegularExpression hostNameAndPortRegExp("Endpoint = (.*):([0-9]*)"); auto url { QUrl::fromUserInput(configMap.value("Endpoint")) };
QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(data);
QString hostName; QString hostName;
QString port; QString port;
if (hostNameAndPortMatch.hasCaptured(1)) { if (!url.host().isEmpty()) {
hostName = hostNameAndPortMatch.captured(1); hostName = url.host();
} else { } else {
qDebug() << "Key parameter 'Endpoint' is missing"; qDebug() << "Key parameter 'Endpoint' is missing or has an invalid format";
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false); emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
return QJsonObject(); return QJsonObject();
} }
if (hostNameAndPortMatch.hasCaptured(2)) { if (url.port() != -1) {
port = hostNameAndPortMatch.captured(2); port = QString::number(url.port());
} else { } else {
port = protocols::wireguard::defaultPort; port = protocols::wireguard::defaultPort;
} }
@@ -395,7 +399,11 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
lastConfig[config_key::mtu] = configMap.value("MTU"); 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; lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
@@ -419,6 +427,12 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
m_configType = ConfigTypes::Awg; m_configType = ConfigTypes::Awg;
} }
if (!configMap.value("MTU").isEmpty()) {
lastConfig[config_key::mtu] = configMap.value("MTU");
} else {
lastConfig[config_key::mtu] = protocolName == "awg" ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
}
QJsonObject wireguardConfig; QJsonObject wireguardConfig;
wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson()); wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());
wireguardConfig[config_key::isThirdPartyConfig] = true; wireguardConfig[config_key::isThirdPartyConfig] = true;
@@ -488,7 +502,7 @@ QJsonObject ImportController::extractXrayConfig(const QString &data, const QStri
if (m_configType == ConfigTypes::ShadowSocks) { if (m_configType == ConfigTypes::ShadowSocks) {
config[config_key::defaultContainer] = "amnezia-ssxray"; config[config_key::defaultContainer] = "amnezia-ssxray";
} else { } else {
config[config_key::defaultContainer] = "amnezia-xray"; config[config_key::defaultContainer] = "amnezia-xray";
} }
if (description.isEmpty()) { if (description.isEmpty()) {
config[config_key::description] = m_settings->nextAvailableServerName(); config[config_key::description] = m_settings->nextAvailableServerName();
@@ -646,3 +660,28 @@ void ImportController::checkForMaliciousStrings(const QJsonObject &serverConfig)
} }
} }
} }
void ImportController::processAmneziaConfig(QJsonObject &config)
{
auto containers = config.value(config_key::containers).toArray();
for (auto i = 0; i < containers.size(); i++) {
auto container = containers.at(i).toObject();
auto dockerContainer = ContainerProps::containerFromString(container.value(config_key::container).toString());
if (dockerContainer == DockerContainer::Awg || dockerContainer == DockerContainer::WireGuard) {
auto containerConfig = container.value(ContainerProps::containerTypeToString(dockerContainer)).toObject();
auto protocolConfig = containerConfig.value(config_key::last_config).toString();
if (protocolConfig.isEmpty()) {
return;
}
QJsonObject jsonConfig = QJsonDocument::fromJson(protocolConfig.toUtf8()).object();
jsonConfig[config_key::mtu] = dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
containerConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
container[ContainerProps::containerTypeToString(dockerContainer)] = containerConfig;
containers.replace(i, container);
config.insert(config_key::containers, containers);
}
}
}
+2
View File
@@ -68,6 +68,8 @@ private:
void checkForMaliciousStrings(const QJsonObject &protocolConfig); void checkForMaliciousStrings(const QJsonObject &protocolConfig);
void processAmneziaConfig(QJsonObject &config);
#if defined Q_OS_ANDROID || defined Q_OS_IOS #if defined Q_OS_ANDROID || defined Q_OS_IOS
void stopDecodingQr(); void stopDecodingQr();
#endif #endif
+1 -1
View File
@@ -112,7 +112,7 @@ void PageController::showOnStartup()
if (!m_settings->isStartMinimized()) { if (!m_settings->isStartMinimized()) {
emit raiseMainWindow(); emit raiseMainWindow();
} else { } else {
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX) #if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
emit hideMainWindow(); emit hideMainWindow();
#elif defined Q_OS_MACX #elif defined Q_OS_MACX
setDockIconVisible(false); setDockIconVisible(false);
+3
View File
@@ -59,6 +59,9 @@ namespace PageLoader
PageProtocolIKev2Settings, PageProtocolIKev2Settings,
PageProtocolRaw, PageProtocolRaw,
PageProtocolWireGuardClientSettings,
PageProtocolAwgClientSettings,
PageShareFullAccess, PageShareFullAccess,
PageDevMenu PageDevMenu
+136 -82
View File
@@ -21,17 +21,30 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
} }
switch (role) { switch (role) {
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break; case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
case Roles::JunkPacketCountRole: m_protocolConfig.insert(config_key::junkPacketCount, value.toString()); break; case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
case Roles::JunkPacketMinSizeRole: m_protocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break; case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
case Roles::JunkPacketMaxSizeRole: m_protocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break; case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
case Roles::InitPacketJunkSizeRole: m_protocolConfig.insert(config_key::initPacketJunkSize, value.toString()); break; case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
case Roles::ResponsePacketJunkSizeRole: m_protocolConfig.insert(config_key::responsePacketJunkSize, value.toString()); break;
case Roles::InitPacketMagicHeaderRole: m_protocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break; case Roles::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
case Roles::ResponsePacketMagicHeaderRole: m_protocolConfig.insert(config_key::responsePacketMagicHeader, value.toString()); break; case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
case Roles::UnderloadPacketMagicHeaderRole: m_protocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString()); break; case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
case Roles::TransportPacketMagicHeaderRole: m_protocolConfig.insert(config_key::transportPacketMagicHeader, value.toString()); break; case Roles::ServerInitPacketJunkSizeRole: m_serverProtocolConfig.insert(config_key::initPacketJunkSize, value.toString()); break;
case Roles::ServerResponsePacketJunkSizeRole:
m_serverProtocolConfig.insert(config_key::responsePacketJunkSize, value.toString());
break;
case Roles::ServerInitPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break;
case Roles::ServerResponsePacketMagicHeaderRole:
m_serverProtocolConfig.insert(config_key::responsePacketMagicHeader, value.toString());
break;
case Roles::ServerUnderloadPacketMagicHeaderRole:
m_serverProtocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString());
break;
case Roles::ServerTransportPacketMagicHeaderRole:
m_serverProtocolConfig.insert(config_key::transportPacketMagicHeader, value.toString());
break;
} }
emit dataChanged(index, index, QList { role }); emit dataChanged(index, index, QList { role });
@@ -45,17 +58,22 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
} }
switch (role) { switch (role) {
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(); case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
case Roles::JunkPacketCountRole: return m_protocolConfig.value(config_key::junkPacketCount); case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
case Roles::JunkPacketMinSizeRole: return m_protocolConfig.value(config_key::junkPacketMinSize); case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount);
case Roles::JunkPacketMaxSizeRole: return m_protocolConfig.value(config_key::junkPacketMaxSize); case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize);
case Roles::InitPacketJunkSizeRole: return m_protocolConfig.value(config_key::initPacketJunkSize); case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMaxSize);
case Roles::ResponsePacketJunkSizeRole: return m_protocolConfig.value(config_key::responsePacketJunkSize);
case Roles::InitPacketMagicHeaderRole: return m_protocolConfig.value(config_key::initPacketMagicHeader); case Roles::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount);
case Roles::ResponsePacketMagicHeaderRole: return m_protocolConfig.value(config_key::responsePacketMagicHeader); case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize);
case Roles::UnderloadPacketMagicHeaderRole: return m_protocolConfig.value(config_key::underloadPacketMagicHeader); case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize);
case Roles::TransportPacketMagicHeaderRole: return m_protocolConfig.value(config_key::transportPacketMagicHeader); case Roles::ServerInitPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::initPacketJunkSize);
case Roles::ServerResponsePacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::responsePacketJunkSize);
case Roles::ServerInitPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::initPacketMagicHeader);
case Roles::ServerResponsePacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::responsePacketMagicHeader);
case Roles::ServerUnderloadPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::underloadPacketMagicHeader);
case Roles::ServerTransportPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::transportPacketMagicHeader);
} }
return QVariant(); return QVariant();
@@ -68,51 +86,63 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
m_fullConfig = config; m_fullConfig = config;
QJsonObject protocolConfig = config.value(config_key::awg).toObject(); QJsonObject serverProtocolConfig = config.value(config_key::awg).toObject();
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg); auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg);
m_protocolConfig.insert(config_key::transport_proto, protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); m_serverProtocolConfig.insert(config_key::transport_proto,
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config); serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
m_protocolConfig[config_key::port] = protocolConfig.value(config_key::port).toString(protocols::awg::defaultPort); m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
m_protocolConfig[config_key::mtu] = protocolConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu); m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
m_protocolConfig[config_key::junkPacketCount] = m_serverProtocolConfig[config_key::junkPacketCount] =
protocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
m_protocolConfig[config_key::junkPacketMinSize] = m_serverProtocolConfig[config_key::junkPacketMinSize] =
protocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
m_protocolConfig[config_key::junkPacketMaxSize] = m_serverProtocolConfig[config_key::junkPacketMaxSize] =
protocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
m_protocolConfig[config_key::initPacketJunkSize] = m_serverProtocolConfig[config_key::initPacketJunkSize] =
protocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
m_protocolConfig[config_key::responsePacketJunkSize] = m_serverProtocolConfig[config_key::responsePacketJunkSize] =
protocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
m_protocolConfig[config_key::initPacketMagicHeader] = m_serverProtocolConfig[config_key::initPacketMagicHeader] =
protocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
m_protocolConfig[config_key::responsePacketMagicHeader] = m_serverProtocolConfig[config_key::responsePacketMagicHeader] =
protocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader); serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
m_protocolConfig[config_key::underloadPacketMagicHeader] = m_serverProtocolConfig[config_key::underloadPacketMagicHeader] =
protocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader); serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
m_protocolConfig[config_key::transportPacketMagicHeader] = m_serverProtocolConfig[config_key::transportPacketMagicHeader] =
protocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu);
m_clientProtocolConfig[config_key::junkPacketCount] =
clientProtocolConfig.value(config_key::junkPacketCount).toString(m_serverProtocolConfig[config_key::junkPacketCount].toString());
m_clientProtocolConfig[config_key::junkPacketMinSize] =
clientProtocolConfig.value(config_key::junkPacketMinSize).toString(m_serverProtocolConfig[config_key::junkPacketMinSize].toString());
m_clientProtocolConfig[config_key::junkPacketMaxSize] =
clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(m_serverProtocolConfig[config_key::junkPacketMaxSize].toString());
endResetModel(); endResetModel();
} }
QJsonObject AwgConfigModel::getConfig() QJsonObject AwgConfigModel::getConfig()
{ {
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
const AwgConfig newConfig(m_protocolConfig); const AwgConfig newConfig(m_serverProtocolConfig);
if (!oldConfig.hasEqualServerSettings(newConfig)) { if (!oldConfig.hasEqualServerSettings(newConfig)) {
m_protocolConfig.remove(config_key::last_config); m_serverProtocolConfig.remove(config_key::last_config);
} else { } else {
auto lastConfig = m_protocolConfig.value(config_key::last_config).toString(); auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
jsonConfig[config_key::mtu] = newConfig.mtu; jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu];
jsonConfig[config_key::junkPacketCount] = m_clientProtocolConfig[config_key::junkPacketCount];
jsonConfig[config_key::junkPacketMinSize] = m_clientProtocolConfig[config_key::junkPacketMinSize];
jsonConfig[config_key::junkPacketMaxSize] = m_clientProtocolConfig[config_key::junkPacketMaxSize];
m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
} }
m_fullConfig.insert(config_key::awg, m_protocolConfig); m_fullConfig.insert(config_key::awg, m_serverProtocolConfig);
return m_fullConfig; return m_fullConfig;
} }
@@ -126,50 +156,73 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2)
return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2); return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2);
} }
bool AwgConfigModel::isServerSettingsEqual()
{
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
const AwgConfig newConfig(m_serverProtocolConfig);
return oldConfig.hasEqualServerSettings(newConfig);
}
QHash<int, QByteArray> AwgConfigModel::roleNames() const QHash<int, QByteArray> AwgConfigModel::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[PortRole] = "port"; roles[PortRole] = "port";
roles[MtuRole] = "mtu";
roles[JunkPacketCountRole] = "junkPacketCount"; roles[ClientMtuRole] = "clientMtu";
roles[JunkPacketMinSizeRole] = "junkPacketMinSize"; roles[ClientJunkPacketCountRole] = "clientJunkPacketCount";
roles[JunkPacketMaxSizeRole] = "junkPacketMaxSize"; roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize";
roles[InitPacketJunkSizeRole] = "initPacketJunkSize"; roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize";
roles[ResponsePacketJunkSizeRole] = "responsePacketJunkSize";
roles[InitPacketMagicHeaderRole] = "initPacketMagicHeader"; roles[ServerJunkPacketCountRole] = "serverJunkPacketCount";
roles[ResponsePacketMagicHeaderRole] = "responsePacketMagicHeader"; roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize";
roles[UnderloadPacketMagicHeaderRole] = "underloadPacketMagicHeader"; roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize";
roles[TransportPacketMagicHeaderRole] = "transportPacketMagicHeader"; roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize";
roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize";
roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader";
roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader";
roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader";
roles[ServerTransportPacketMagicHeaderRole] = "serverTransportPacketMagicHeader";
return roles; return roles;
} }
AwgConfig::AwgConfig(const QJsonObject &jsonConfig) AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
{ {
port = jsonConfig.value(config_key::port).toString(protocols::awg::defaultPort); auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
mtu = jsonConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu); QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
junkPacketCount = jsonConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu);
junkPacketMinSize = jsonConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
junkPacketMaxSize = jsonConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
initPacketJunkSize = jsonConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
responsePacketJunkSize = jsonConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
initPacketMagicHeader = jsonConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
responsePacketMagicHeader = serverJunkPacketCount = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
jsonConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader); serverJunkPacketMinSize = serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
underloadPacketMagicHeader = serverJunkPacketMaxSize = serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
jsonConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader); serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
transportPacketMagicHeader = serverResponsePacketJunkSize =
jsonConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
serverInitPacketMagicHeader =
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
serverResponsePacketMagicHeader =
serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
serverUnderloadPacketMagicHeader =
serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
serverTransportPacketMagicHeader =
serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
} }
bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
{ {
if (port != other.port || junkPacketCount != other.junkPacketCount || junkPacketMinSize != other.junkPacketMinSize if (port != other.port || serverJunkPacketCount != other.serverJunkPacketCount
|| junkPacketMaxSize != other.junkPacketMaxSize || initPacketJunkSize != other.initPacketJunkSize || serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize
|| responsePacketJunkSize != other.responsePacketJunkSize || initPacketMagicHeader != other.initPacketMagicHeader || serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize
|| responsePacketMagicHeader != other.responsePacketMagicHeader || underloadPacketMagicHeader != other.underloadPacketMagicHeader || serverInitPacketMagicHeader != other.serverInitPacketMagicHeader
|| transportPacketMagicHeader != other.transportPacketMagicHeader) { || serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader
|| serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader
|| serverTransportPacketMagicHeader != other.serverTransportPacketMagicHeader) {
return false; return false;
} }
return true; return true;
@@ -177,7 +230,8 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
{ {
if (mtu != other.mtu) { if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount
|| clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize) {
return false; return false;
} }
return true; return true;
+34 -21
View File
@@ -16,16 +16,21 @@ struct AwgConfig
AwgConfig(const QJsonObject &jsonConfig); AwgConfig(const QJsonObject &jsonConfig);
QString port; QString port;
QString mtu;
QString junkPacketCount; QString clientMtu;
QString junkPacketMinSize; QString clientJunkPacketCount;
QString junkPacketMaxSize; QString clientJunkPacketMinSize;
QString initPacketJunkSize; QString clientJunkPacketMaxSize;
QString responsePacketJunkSize;
QString initPacketMagicHeader; QString serverJunkPacketCount;
QString responsePacketMagicHeader; QString serverJunkPacketMinSize;
QString underloadPacketMagicHeader; QString serverJunkPacketMaxSize;
QString transportPacketMagicHeader; QString serverInitPacketJunkSize;
QString serverResponsePacketJunkSize;
QString serverInitPacketMagicHeader;
QString serverResponsePacketMagicHeader;
QString serverUnderloadPacketMagicHeader;
QString serverTransportPacketMagicHeader;
bool hasEqualServerSettings(const AwgConfig &other) const; bool hasEqualServerSettings(const AwgConfig &other) const;
bool hasEqualClientSettings(const AwgConfig &other) const; bool hasEqualClientSettings(const AwgConfig &other) const;
@@ -39,16 +44,21 @@ class AwgConfigModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
PortRole = Qt::UserRole + 1, PortRole = Qt::UserRole + 1,
MtuRole,
JunkPacketCountRole, ClientMtuRole,
JunkPacketMinSizeRole, ClientJunkPacketCountRole,
JunkPacketMaxSizeRole, ClientJunkPacketMinSizeRole,
InitPacketJunkSizeRole, ClientJunkPacketMaxSizeRole,
ResponsePacketJunkSizeRole,
InitPacketMagicHeaderRole, ServerJunkPacketCountRole,
ResponsePacketMagicHeaderRole, ServerJunkPacketMinSizeRole,
UnderloadPacketMagicHeaderRole, ServerJunkPacketMaxSizeRole,
TransportPacketMagicHeaderRole ServerInitPacketJunkSizeRole,
ServerResponsePacketJunkSizeRole,
ServerInitPacketMagicHeaderRole,
ServerResponsePacketMagicHeaderRole,
ServerUnderloadPacketMagicHeaderRole,
ServerTransportPacketMagicHeaderRole
}; };
explicit AwgConfigModel(QObject *parent = nullptr); explicit AwgConfigModel(QObject *parent = nullptr);
@@ -65,12 +75,15 @@ public slots:
bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4); bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4);
bool isPacketSizeEqual(const int s1, const int s2); bool isPacketSizeEqual(const int s1, const int s2);
bool isServerSettingsEqual();
protected: protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
private: private:
DockerContainer m_container; DockerContainer m_container;
QJsonObject m_protocolConfig; QJsonObject m_serverProtocolConfig;
QJsonObject m_clientProtocolConfig;
QJsonObject m_fullConfig; QJsonObject m_fullConfig;
}; };
@@ -21,8 +21,8 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val
} }
switch (role) { switch (role) {
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break; case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break; case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
} }
emit dataChanged(index, index, QList { role }); emit dataChanged(index, index, QList { role });
@@ -36,8 +36,8 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const
} }
switch (role) { switch (role) {
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(); case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString(); case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
} }
return QVariant(); return QVariant();
@@ -49,17 +49,18 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString()); m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
m_fullConfig = config; m_fullConfig = config;
QJsonObject protocolConfig = config.value(config_key::wireguard).toObject(); QJsonObject serverProtocolConfig = config.value(config_key::wireguard).toObject();
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard); auto defaultTransportProto =
m_protocolConfig.insert(config_key::transport_proto, ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard);
protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); m_serverProtocolConfig.insert(config_key::transport_proto,
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config); serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
m_protocolConfig[config_key::port] = m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
protocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
m_protocolConfig[config_key::mtu] = auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
protocolConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu); QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
endResetModel(); endResetModel();
} }
@@ -67,36 +68,47 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
QJsonObject WireGuardConfigModel::getConfig() QJsonObject WireGuardConfigModel::getConfig()
{ {
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject()); const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
const WgConfig newConfig(m_protocolConfig); const WgConfig newConfig(m_serverProtocolConfig);
if (!oldConfig.hasEqualServerSettings(newConfig)) { if (!oldConfig.hasEqualServerSettings(newConfig)) {
m_protocolConfig.remove(config_key::last_config); m_serverProtocolConfig.remove(config_key::last_config);
} else { } else {
auto lastConfig = m_protocolConfig.value(config_key::last_config).toString(); auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
jsonConfig[config_key::mtu] = newConfig.mtu; jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu];
m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
} }
m_fullConfig.insert(config_key::wireguard, m_protocolConfig); m_fullConfig.insert(config_key::wireguard, m_serverProtocolConfig);
return m_fullConfig; return m_fullConfig;
} }
bool WireGuardConfigModel::isServerSettingsEqual()
{
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
const WgConfig newConfig(m_serverProtocolConfig);
return oldConfig.hasEqualServerSettings(newConfig);
}
QHash<int, QByteArray> WireGuardConfigModel::roleNames() const QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[PortRole] = "port"; roles[PortRole] = "port";
roles[MtuRole] = "mtu"; roles[ClientMtuRole] = "clientMtu";
return roles; return roles;
} }
WgConfig::WgConfig(const QJsonObject &jsonConfig) WgConfig::WgConfig(const QJsonObject &serverProtocolConfig)
{ {
port = jsonConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
mtu = jsonConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu); QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
port = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
} }
bool WgConfig::hasEqualServerSettings(const WgConfig &other) const bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
@@ -109,7 +121,7 @@ bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
bool WgConfig::hasEqualClientSettings(const WgConfig &other) const bool WgConfig::hasEqualClientSettings(const WgConfig &other) const
{ {
if (mtu != other.mtu) { if (clientMtu != other.clientMtu) {
return false; return false;
} }
return true; return true;
@@ -11,7 +11,7 @@ struct WgConfig
WgConfig(const QJsonObject &jsonConfig); WgConfig(const QJsonObject &jsonConfig);
QString port; QString port;
QString mtu; QString clientMtu;
bool hasEqualServerSettings(const WgConfig &other) const; bool hasEqualServerSettings(const WgConfig &other) const;
bool hasEqualClientSettings(const WgConfig &other) const; bool hasEqualClientSettings(const WgConfig &other) const;
@@ -25,7 +25,7 @@ class WireGuardConfigModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
PortRole = Qt::UserRole + 1, PortRole = Qt::UserRole + 1,
MtuRole ClientMtuRole
}; };
explicit WireGuardConfigModel(QObject *parent = nullptr); explicit WireGuardConfigModel(QObject *parent = nullptr);
@@ -39,12 +39,15 @@ public slots:
void updateModel(const QJsonObject &config); void updateModel(const QJsonObject &config);
QJsonObject getConfig(); QJsonObject getConfig();
bool isServerSettingsEqual();
protected: protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
private: private:
DockerContainer m_container; DockerContainer m_container;
QJsonObject m_protocolConfig; QJsonObject m_serverProtocolConfig;
QJsonObject m_clientProtocolConfig;
QJsonObject m_fullConfig; QJsonObject m_fullConfig;
}; };
+26 -4
View File
@@ -16,9 +16,11 @@ QHash<int, QByteArray> ProtocolsModel::roleNames() const
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[ProtocolNameRole] = "protocolName"; roles[ProtocolNameRole] = "protocolName";
roles[ProtocolPageRole] = "protocolPage"; roles[ServerProtocolPageRole] = "serverProtocolPage";
roles[ClientProtocolPageRole] = "clientProtocolPage";
roles[ProtocolIndexRole] = "protocolIndex"; roles[ProtocolIndexRole] = "protocolIndex";
roles[RawConfigRole] = "rawConfig"; roles[RawConfigRole] = "rawConfig";
roles[IsClientProtocolExistsRole] = "isClientProtocolExists";
return roles; return roles;
} }
@@ -34,8 +36,10 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row())); amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row()));
return ProtocolProps::protocolHumanNames().value(proto); return ProtocolProps::protocolHumanNames().value(proto);
} }
case ProtocolPageRole: case ServerProtocolPageRole:
return static_cast<int>(protocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row())))); return static_cast<int>(serverProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
case ClientProtocolPageRole:
return static_cast<int>(clientProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row())); case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row()));
case RawConfigRole: { case RawConfigRole: {
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject(); auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
@@ -50,6 +54,15 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
} }
return rawConfig; return rawConfig;
} }
case IsClientProtocolExistsRole: {
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
auto lastConfigJsonDoc =
QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8());
auto lastConfigJson = lastConfigJsonDoc.object();
auto configString = lastConfigJson.value(config_key::config).toString();
return !configString.isEmpty();
}
} }
return QVariant(); return QVariant();
@@ -70,7 +83,7 @@ QJsonObject ProtocolsModel::getConfig()
return config; return config;
} }
PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const
{ {
switch (protocol) { switch (protocol) {
case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings; case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
@@ -90,3 +103,12 @@ PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings; default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
} }
} }
PageLoader::PageEnum ProtocolsModel::clientProtocolPage(Proto protocol) const
{
switch (protocol) {
case Proto::WireGuard: return PageLoader::PageEnum::PageProtocolWireGuardClientSettings;
case Proto::Awg: return PageLoader::PageEnum::PageProtocolAwgClientSettings;
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
}
}
+6 -3
View File
@@ -13,9 +13,11 @@ class ProtocolsModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
ProtocolNameRole = Qt::UserRole + 1, ProtocolNameRole = Qt::UserRole + 1,
ProtocolPageRole, ServerProtocolPageRole,
ClientProtocolPageRole,
ProtocolIndexRole, ProtocolIndexRole,
RawConfigRole RawConfigRole,
IsClientProtocolExistsRole
}; };
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr); ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
@@ -33,7 +35,8 @@ protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
private: private:
PageLoader::PageEnum protocolPage(Proto protocol) const; PageLoader::PageEnum serverProtocolPage(Proto protocol) const;
PageLoader::PageEnum clientProtocolPage(Proto protocol) const;
std::shared_ptr<Settings> m_settings; std::shared_ptr<Settings> m_settings;
@@ -0,0 +1,312 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
defaultActiveFocusItem: listview.currentItem.mtuTextField.textField
Item {
id: focusItem
onFocusChanged: {
if (activeFocus) {
fl.ensureVisible(focusItem)
}
}
KeyNavigation.tab: backButton
}
ColumnLayout {
id: backButtonLayout
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
id: backButton
KeyNavigation.tab: listview.currentItem.mtuTextField.textField
}
}
FlickableType {
id: fl
anchors.top: backButtonLayout.bottom
anchors.bottom: parent.bottom
contentHeight: content.implicitHeight + saveButton.implicitHeight + saveButton.anchors.bottomMargin + saveButton.anchors.topMargin
Column {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
ListView {
id: listview
width: parent.width
height: listview.contentItem.height
clip: true
interactive: false
model: AwgConfigModel
delegate: Item {
id: delegateItem
implicitWidth: listview.width
implicitHeight: col.implicitHeight
property alias mtuTextField: mtuTextField
property bool isSaveButtonEnabled: mtuTextField.errorText === "" &&
junkPacketMaxSizeTextField.errorText === "" &&
junkPacketMinSizeTextField.errorText === "" &&
junkPacketCountTextField.errorText === ""
ColumnLayout {
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 0
HeaderType {
Layout.fillWidth: true
headerText: qsTr("AmneziaWG settings")
}
TextFieldWithHeaderType {
id: mtuTextField
Layout.fillWidth: true
Layout.topMargin: 40
headerText: qsTr("MTU")
textFieldText: clientMtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textFieldText !== clientMtu) {
clientMtu = textFieldText
}
}
checkEmptyText: true
KeyNavigation.tab: junkPacketCountTextField.textField
}
TextFieldWithHeaderType {
id: junkPacketCountTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: "Jc - Junk packet count"
textFieldText: clientJunkPacketCount
textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl
textField.onEditingFinished: {
if (textFieldText !== clientJunkPacketCount) {
clientJunkPacketCount = textFieldText
}
}
checkEmptyText: true
KeyNavigation.tab: junkPacketMinSizeTextField.textField
}
TextFieldWithHeaderType {
id: junkPacketMinSizeTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: "Jmin - Junk packet minimum size"
textFieldText: clientJunkPacketMinSize
textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl
textField.onEditingFinished: {
if (textFieldText !== clientJunkPacketMinSize) {
clientJunkPacketMinSize = textFieldText
}
}
checkEmptyText: true
KeyNavigation.tab: junkPacketMaxSizeTextField.textField
}
TextFieldWithHeaderType {
id: junkPacketMaxSizeTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: "Jmax - Junk packet maximum size"
textFieldText: clientJunkPacketMaxSize
textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl
textField.onEditingFinished: {
if (textFieldText !== clientJunkPacketMaxSize) {
clientJunkPacketMaxSize = textFieldText
}
}
checkEmptyText: true
Keys.onTabPressed: saveButton.forceActiveFocus()
}
Header2TextType {
Layout.fillWidth: true
Layout.topMargin: 16
text: qsTr("Server settings")
}
TextFieldWithHeaderType {
id: portTextField
Layout.fillWidth: true
Layout.topMargin: 8
enabled: false
headerText: qsTr("Port")
textFieldText: port
}
TextFieldWithHeaderType {
id: initPacketJunkSizeTextField
Layout.fillWidth: true
Layout.topMargin: 16
enabled: false
headerText: "S1 - Init packet junk size"
textFieldText: serverInitPacketJunkSize
}
TextFieldWithHeaderType {
id: responsePacketJunkSizeTextField
Layout.fillWidth: true
Layout.topMargin: 16
enabled: false
headerText: "S2 - Response packet junk size"
textFieldText: serverResponsePacketJunkSize
}
TextFieldWithHeaderType {
id: initPacketMagicHeaderTextField
Layout.fillWidth: true
Layout.topMargin: 16
enabled: false
headerText: "H1 - Init packet magic header"
textFieldText: serverInitPacketMagicHeader
}
TextFieldWithHeaderType {
id: responsePacketMagicHeaderTextField
Layout.fillWidth: true
Layout.topMargin: 16
enabled: false
headerText: "H2 - Response packet magic header"
textFieldText: serverResponsePacketMagicHeader
}
TextFieldWithHeaderType {
id: underloadPacketMagicHeaderTextField
Layout.fillWidth: true
Layout.topMargin: 16
parentFlickable: fl
enabled: false
headerText: "H3 - Underload packet magic header"
textFieldText: serverUnderloadPacketMagicHeader
}
TextFieldWithHeaderType {
id: transportPacketMagicHeaderTextField
Layout.fillWidth: true
Layout.topMargin: 16
enabled: false
headerText: "H4 - Transport packet magic header"
textFieldText: serverTransportPacketMagicHeader
}
}
}
}
}
}
BasicButtonType {
id: saveButton
anchors.right: root.right
anchors.left: root.left
anchors.bottom: root.bottom
anchors.topMargin: 24
anchors.bottomMargin: 24
anchors.rightMargin: 16
anchors.leftMargin: 16
enabled: listview.currentItem.isSaveButtonEnabled
text: qsTr("Save")
Keys.onTabPressed: lastItemTabClicked(focusItem)
clickedFunc: function() {
forceActiveFocus()
var headerText = qsTr("Save settings?")
var descriptionText = qsTr("Only the settings for this device will be changed")
var yesButtonText = qsTr("Continue")
var noButtonText = qsTr("Cancel")
var yesButtonFunction = function() {
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
return
}
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(AwgConfigModel.getConfig())
}
var noButtonFunction = function() {
if (!GC.isMobile()) {
saveButton.forceActiveFocus()
}
}
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
}
}
}
@@ -57,8 +57,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
enabled: ServersModel.isProcessedServerHasWriteAccess()
ListView { ListView {
id: listview id: listview
@@ -71,12 +69,12 @@ PageType {
model: AwgConfigModel model: AwgConfigModel
delegate: Item { delegate: Item {
id: _delegate id: delegateItem
implicitWidth: listview.width implicitWidth: listview.width
implicitHeight: col.implicitHeight implicitHeight: col.implicitHeight
property alias portTextField:portTextField property alias portTextField: portTextField
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
ColumnLayout { ColumnLayout {
id: col id: col
@@ -101,6 +99,8 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 40 Layout.topMargin: 40
enabled: delegateItem.isEnabled
headerText: qsTr("Port") headerText: qsTr("Port")
textFieldText: port textFieldText: port
textField.maximumLength: 5 textField.maximumLength: 5
@@ -115,27 +115,6 @@ PageType {
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: mtuTextField.textField
}
TextFieldWithHeaderType {
id: mtuTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("MTU")
textFieldText: mtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textFieldText === "") {
textFieldText = "0"
}
if (textFieldText !== mtu) {
mtu = textFieldText
}
}
checkEmptyText: true
KeyNavigation.tab: junkPacketCountTextField.textField KeyNavigation.tab: junkPacketCountTextField.textField
} }
@@ -145,7 +124,7 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
headerText: qsTr("Jc - Junk packet count") headerText: qsTr("Jc - Junk packet count")
textFieldText: junkPacketCount textFieldText: serverJunkPacketCount
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl parentFlickable: fl
@@ -154,8 +133,8 @@ PageType {
textFieldText = "0" textFieldText = "0"
} }
if (textFieldText !== junkPacketCount) { if (textFieldText !== serverJunkPacketCount) {
junkPacketCount = textFieldText serverJunkPacketCount = textFieldText
} }
} }
@@ -170,13 +149,13 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
headerText: qsTr("Jmin - Junk packet minimum size") headerText: qsTr("Jmin - Junk packet minimum size")
textFieldText: junkPacketMinSize textFieldText: serverJunkPacketMinSize
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl parentFlickable: fl
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== junkPacketMinSize) { if (textFieldText !== serverJunkPacketMinSize) {
junkPacketMinSize = textFieldText serverJunkPacketMinSize = textFieldText
} }
} }
@@ -191,13 +170,13 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
headerText: qsTr("Jmax - Junk packet maximum size") headerText: qsTr("Jmax - Junk packet maximum size")
textFieldText: junkPacketMaxSize textFieldText: serverJunkPacketMaxSize
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl parentFlickable: fl
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== junkPacketMaxSize) { if (textFieldText !== serverJunkPacketMaxSize) {
junkPacketMaxSize = textFieldText serverJunkPacketMaxSize = textFieldText
} }
} }
@@ -212,13 +191,13 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
headerText: qsTr("S1 - Init packet junk size") headerText: qsTr("S1 - Init packet junk size")
textFieldText: initPacketJunkSize textFieldText: serverInitPacketJunkSize
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl parentFlickable: fl
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== initPacketJunkSize) { if (textFieldText !== serverInitPacketJunkSize) {
initPacketJunkSize = textFieldText serverInitPacketJunkSize = textFieldText
} }
} }
@@ -233,13 +212,13 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
headerText: qsTr("S2 - Response packet junk size") headerText: qsTr("S2 - Response packet junk size")
textFieldText: responsePacketJunkSize textFieldText: serverResponsePacketJunkSize
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl parentFlickable: fl
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== responsePacketJunkSize) { if (textFieldText !== serverResponsePacketJunkSize) {
responsePacketJunkSize = textFieldText serverResponsePacketJunkSize = textFieldText
} }
} }
@@ -254,13 +233,13 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
headerText: qsTr("H1 - Init packet magic header") headerText: qsTr("H1 - Init packet magic header")
textFieldText: initPacketMagicHeader textFieldText: serverInitPacketMagicHeader
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl parentFlickable: fl
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== initPacketMagicHeader) { if (textFieldText !== serverInitPacketMagicHeader) {
initPacketMagicHeader = textFieldText serverInitPacketMagicHeader = textFieldText
} }
} }
@@ -275,13 +254,13 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
headerText: qsTr("H2 - Response packet magic header") headerText: qsTr("H2 - Response packet magic header")
textFieldText: responsePacketMagicHeader textFieldText: serverResponsePacketMagicHeader
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl parentFlickable: fl
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== responsePacketMagicHeader) { if (textFieldText !== serverResponsePacketMagicHeader) {
responsePacketMagicHeader = textFieldText serverResponsePacketMagicHeader = textFieldText
} }
} }
@@ -296,13 +275,13 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
headerText: qsTr("H4 - Transport packet magic header") headerText: qsTr("H4 - Transport packet magic header")
textFieldText: transportPacketMagicHeader textFieldText: serverTransportPacketMagicHeader
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
parentFlickable: fl parentFlickable: fl
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== transportPacketMagicHeader) { if (textFieldText !== serverTransportPacketMagicHeader) {
transportPacketMagicHeader = textFieldText serverTransportPacketMagicHeader = textFieldText
} }
} }
@@ -318,12 +297,12 @@ PageType {
parentFlickable: fl parentFlickable: fl
headerText: qsTr("H3 - Underload packet magic header") headerText: qsTr("H3 - Underload packet magic header")
textFieldText: underloadPacketMagicHeader textFieldText: serverUnderloadPacketMagicHeader
textField.validator: IntValidator { bottom: 0 } textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== underloadPacketMagicHeader) { if (textFieldText !== serverUnderloadPacketMagicHeader) {
underloadPacketMagicHeader = textFieldText serverUnderloadPacketMagicHeader = textFieldText
} }
} }
@@ -356,18 +335,22 @@ PageType {
Keys.onTabPressed: lastItemTabClicked(focusItem) Keys.onTabPressed: lastItemTabClicked(focusItem)
clickedFunc: function() { clickedFunc: function() {
if (AwgConfigModel.isHeadersEqual(underloadPacketMagicHeaderTextField.textField.text, forceActiveFocus()
transportPacketMagicHeaderTextField.textField.text,
responsePacketMagicHeaderTextField.textField.text,
initPacketMagicHeaderTextField.textField.text)) {
PageController.showErrorMessage(qsTr("The values of the H1-H4 fields must be unique"))
return
}
if (AwgConfigModel.isPacketSizeEqual(parseInt(initPacketJunkSizeTextField.textField.text), if (delegateItem.isEnabled) {
parseInt(responsePacketJunkSizeTextField.textField.text))) { if (AwgConfigModel.isHeadersEqual(underloadPacketMagicHeaderTextField.textField.text,
PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)")) transportPacketMagicHeaderTextField.textField.text,
return responsePacketMagicHeaderTextField.textField.text,
initPacketMagicHeaderTextField.textField.text)) {
PageController.showErrorMessage(qsTr("The values of the H1-H4 fields must be unique"))
return
}
if (AwgConfigModel.isPacketSizeEqual(parseInt(initPacketJunkSizeTextField.textField.text),
parseInt(responsePacketJunkSizeTextField.textField.text))) {
PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)"))
return
}
} }
var headerText = qsTr("Save settings?") var headerText = qsTr("Save settings?")
@@ -376,8 +359,6 @@ PageType {
var noButtonText = qsTr("Cancel") var noButtonText = qsTr("Cancel")
var yesButtonFunction = function() { var yesButtonFunction = function() {
forceActiveFocus()
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) { if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection")) PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
return return
@@ -0,0 +1,179 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
defaultActiveFocusItem: listview.currentItem.mtuTextField.textField
Item {
id: focusItem
onFocusChanged: {
if (activeFocus) {
fl.ensureVisible(focusItem)
}
}
KeyNavigation.tab: backButton
}
ColumnLayout {
id: backButtonLayout
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
id: backButton
KeyNavigation.tab: listview.currentItem.mtuTextField.textField
}
}
FlickableType {
id: fl
anchors.top: backButtonLayout.bottom
anchors.bottom: parent.bottom
contentHeight: content.implicitHeight + saveButton.implicitHeight + saveButton.anchors.bottomMargin + saveButton.anchors.topMargin
Column {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
ListView {
id: listview
width: parent.width
height: listview.contentItem.height
clip: true
interactive: false
model: WireGuardConfigModel
delegate: Item {
id: delegateItem
implicitWidth: listview.width
implicitHeight: col.implicitHeight
property alias mtuTextField: mtuTextField
property bool isSaveButtonEnabled: mtuTextField.errorText === ""
ColumnLayout {
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 0
HeaderType {
Layout.fillWidth: true
headerText: qsTr("WG settings")
}
TextFieldWithHeaderType {
id: mtuTextField
Layout.fillWidth: true
Layout.topMargin: 40
headerText: qsTr("MTU")
textFieldText: clientMtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textFieldText !== clientMtu) {
clientMtu = textFieldText
}
}
checkEmptyText: true
KeyNavigation.tab: saveButton
}
Header2TextType {
Layout.fillWidth: true
Layout.topMargin: 16
text: qsTr("Server settings")
}
TextFieldWithHeaderType {
id: portTextField
Layout.fillWidth: true
Layout.topMargin: 8
enabled: false
headerText: qsTr("Port")
textFieldText: port
}
}
}
}
}
}
BasicButtonType {
id: saveButton
anchors.right: root.right
anchors.left: root.left
anchors.bottom: root.bottom
anchors.topMargin: 24
anchors.bottomMargin: 24
anchors.rightMargin: 16
anchors.leftMargin: 16
enabled: listview.currentItem.isSaveButtonEnabled
text: qsTr("Save")
Keys.onTabPressed: lastItemTabClicked(focusItem)
clickedFunc: function() {
forceActiveFocus()
var headerText = qsTr("Save settings?")
var descriptionText = qsTr("Only the settings for this device will be changed")
var yesButtonText = qsTr("Continue")
var noButtonText = qsTr("Cancel")
var yesButtonFunction = function() {
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
return
}
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(WireGuardConfigModel.getConfig())
}
var noButtonFunction = function() {
if (!GC.isMobile()) {
saveButton.forceActiveFocus()
}
}
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
}
}
}
@@ -72,7 +72,10 @@ PageType {
} }
delegate: Item { delegate: Item {
id: delegateItem
property alias focusItemId: portTextField.textField property alias focusItemId: portTextField.textField
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
implicitWidth: listview.width implicitWidth: listview.width
implicitHeight: col.implicitHeight implicitHeight: col.implicitHeight
@@ -99,12 +102,14 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 40 Layout.topMargin: 40
enabled: delegateItem.isEnabled
headerText: qsTr("Port") headerText: qsTr("Port")
textFieldText: port textFieldText: port
textField.maximumLength: 5 textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 } textField.validator: IntValidator { bottom: 1; top: 65535 }
KeyNavigation.tab: mtuTextField.textField KeyNavigation.tab: saveButton
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== port) { if (textFieldText !== port) {
@@ -115,52 +120,41 @@ PageType {
checkEmptyText: true checkEmptyText: true
} }
TextFieldWithHeaderType {
id: mtuTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("MTU")
textFieldText: mtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
KeyNavigation.tab: saveButton
textField.onEditingFinished: {
if (textFieldText === "") {
textFieldText = "0"
}
if (textFieldText !== mtu) {
mtu = textFieldText
}
}
checkEmptyText: true
}
BasicButtonType { BasicButtonType {
id: saveButton id: saveButton
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 24 Layout.topMargin: 24
Layout.bottomMargin: 24 Layout.bottomMargin: 24
enabled: mtuTextField.errorText === "" && enabled: portTextField.errorText === ""
portTextField.errorText === ""
text: qsTr("Save") text: qsTr("Save")
Keys.onTabPressed: lastItemTabClicked(focusItem) Keys.onTabPressed: lastItemTabClicked(focusItem)
onClicked: { onClicked: function() {
forceActiveFocus() forceActiveFocus()
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) { var headerText = qsTr("Save settings?")
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection")) var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
return var yesButtonText = qsTr("Continue")
} var noButtonText = qsTr("Cancel")
PageController.goToPage(PageEnum.PageSetupWizardInstalling); var yesButtonFunction = function() {
InstallController.updateContainer(WireGuardConfigModel.getConfig()) if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
focusItem.forceActiveFocus() PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
return
}
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(WireGuardConfigModel.getConfig())
}
var noButtonFunction = function() {
if (!GC.isMobile()) {
saveRestartButton.forceActiveFocus()
}
}
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
} }
Keys.onEnterPressed: saveButton.clicked() Keys.onEnterPressed: saveButton.clicked()
@@ -79,7 +79,7 @@ PageType {
} }
delegate: Item { delegate: Item {
property var focusItem: button.rightButton property var focusItem: clientSettings.rightButton
implicitWidth: protocols.width implicitWidth: protocols.width
implicitHeight: delegateContent.implicitHeight implicitHeight: delegateContent.implicitHeight
@@ -89,13 +89,49 @@ PageType {
anchors.fill: parent anchors.fill: parent
property bool isClientSettingsVisible: protocolIndex === ProtocolEnum.WireGuard || protocolIndex === ProtocolEnum.Awg
property bool isServerSettingsVisible: ServersModel.isProcessedServerHasWriteAccess()
LabelWithButtonType { LabelWithButtonType {
id: button id: clientSettings
Layout.fillWidth: true Layout.fillWidth: true
text: protocolName text: protocolName + qsTr(" connection settings")
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
visible: delegateContent.isClientSettingsVisible
clickedFunction: function() {
if (isClientProtocolExists) {
switch (protocolIndex) {
case ProtocolEnum.WireGuard: WireGuardConfigModel.updateModel(ProtocolsModel.getConfig()); break;
case ProtocolEnum.Awg: AwgConfigModel.updateModel(ProtocolsModel.getConfig()); break;
}
PageController.goToPage(clientProtocolPage);
} else {
PageController.showNotificationMessage(qsTr("Click the \"connect\" button to create a connection configuration"))
}
}
MouseArea {
anchors.fill: clientSettings
cursorShape: Qt.PointingHandCursor
enabled: false
}
}
DividerType {
visible: delegateContent.isClientSettingsVisible
}
LabelWithButtonType {
id: serverSettings
Layout.fillWidth: true
text: protocolName + qsTr(" server settings")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
visible: delegateContent.isServerSettingsVisible
clickedFunction: function() { clickedFunction: function() {
switch (protocolIndex) { switch (protocolIndex) {
@@ -109,17 +145,19 @@ PageType {
case ProtocolEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break; case ProtocolEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break;
case ProtocolEnum.Socks5Proxy: Socks5ProxyConfigModel.updateModel(ProtocolsModel.getConfig()); break; case ProtocolEnum.Socks5Proxy: Socks5ProxyConfigModel.updateModel(ProtocolsModel.getConfig()); break;
} }
PageController.goToPage(protocolPage); PageController.goToPage(serverProtocolPage);
} }
MouseArea { MouseArea {
anchors.fill: button anchors.fill: serverSettings
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
enabled: false enabled: false
} }
} }
DividerType {} DividerType {
visible: delegateContent.isServerSettingsVisible
}
} }
} }
} }
@@ -132,11 +170,11 @@ PageType {
visible: root.isClearCacheVisible visible: root.isClearCacheVisible
KeyNavigation.tab: removeButton KeyNavigation.tab: removeButton
text: qsTr("Clear %1 profile").arg(ContainersModel.getProcessedContainerName()) text: qsTr("Clear profile")
clickedFunction: function() { clickedFunction: function() {
var headerText = qsTr("Clear %1 profile?").arg(ContainersModel.getProcessedContainerName()) var headerText = qsTr("Clear %1 profile?").arg(ContainersModel.getProcessedContainerName())
var descriptionText = qsTr("") var descriptionText = qsTr("The connection configuration will be deleted for this device only")
var yesButtonText = qsTr("Continue") var yesButtonText = qsTr("Continue")
var noButtonText = qsTr("Cancel") var noButtonText = qsTr("Cancel")
@@ -183,7 +221,7 @@ PageType {
visible: ServersModel.isProcessedServerHasWriteAccess() visible: ServersModel.isProcessedServerHasWriteAccess()
Keys.onTabPressed: lastItemTabClicked(focusItem) Keys.onTabPressed: lastItemTabClicked(focusItem)
text: qsTr("Remove ") + ContainersModel.getProcessedContainerName() text: qsTr("Remove ")
textColor: AmneziaStyle.color.vibrantRed textColor: AmneziaStyle.color.vibrantRed
clickedFunction: function() { clickedFunction: function() {
@@ -60,9 +60,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
headerText: qsTr("Server IP address [:port]") headerText: qsTr("Server IP address [:port]")
textFieldPlaceholderText: qsTr("255.255.255.255:22") textFieldPlaceholderText: qsTr("255.255.255.255:22")
textField.validator: RegularExpressionValidator {
regularExpression: InstallController.ipAddressPortRegExp()
}
textField.onFocusChanged: { textField.onFocusChanged: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '') textField.text = textField.text.replace(/^\s+|\s+$/g, '')
+62 -29
View File
@@ -1,16 +1,16 @@
#include "qtimer.h" #include "qtimer.h"
#include <QDebug> #include <QDebug>
#include <QEventLoop>
#include <QFile> #include <QFile>
#include <QHostInfo> #include <QHostInfo>
#include <QJsonObject> #include <QJsonObject>
#include <QEventLoop>
#include "core/controllers/serverController.h"
#include <configurators/cloak_configurator.h> #include <configurators/cloak_configurator.h>
#include <configurators/openvpn_configurator.h> #include <configurators/openvpn_configurator.h>
#include <configurators/shadowsocks_configurator.h> #include <configurators/shadowsocks_configurator.h>
#include <configurators/wireguard_configurator.h> #include <configurators/wireguard_configurator.h>
#include "core/controllers/serverController.h"
#ifdef AMNEZIA_DESKTOP #ifdef AMNEZIA_DESKTOP
#include "core/ipcclient.h" #include "core/ipcclient.h"
@@ -34,8 +34,7 @@ VpnConnection::VpnConnection(std::shared_ptr<Settings> settings, QObject *parent
{ {
m_checkTimer.setInterval(1000); m_checkTimer.setInterval(1000);
#ifdef Q_OS_IOS #ifdef Q_OS_IOS
connect(IosController::Instance(), &IosController::connectionStateChanged, this, connect(IosController::Instance(), &IosController::connectionStateChanged, this, &VpnConnection::onConnectionStateChanged);
&VpnConnection::onConnectionStateChanged);
connect(IosController::Instance(), &IosController::bytesChanged, this, &VpnConnection::onBytesChanged); connect(IosController::Instance(), &IosController::bytesChanged, this, &VpnConnection::onBytesChanged);
#endif #endif
@@ -58,7 +57,7 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state)
#ifdef AMNEZIA_DESKTOP #ifdef AMNEZIA_DESKTOP
QString proto = m_settings->defaultContainerName(m_settings->defaultServerIndex()); QString proto = m_settings->defaultContainerName(m_settings->defaultServerIndex());
if (IpcClient::Interface()) { if (IpcClient::Interface()) {
if (state == Vpn::ConnectionState::Connected) { if (state == Vpn::ConnectionState::Connected) {
IpcClient::Interface()->resetIpStack(); IpcClient::Interface()->resetIpStack();
@@ -72,7 +71,7 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state)
if (m_settings->isSitesSplitTunnelingEnabled()) { if (m_settings->isSitesSplitTunnelingEnabled()) {
IpcClient::Interface()->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0"); IpcClient::Interface()->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0");
// qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size(); // qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size();
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) { if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
QTimer::singleShot(1000, m_vpnProtocol.data(), QTimer::singleShot(1000, m_vpnProtocol.data(),
[this]() { addSitesRoutes(m_vpnProtocol->vpnGateway(), m_settings->routeMode()); }); [this]() { addSitesRoutes(m_vpnProtocol->vpnGateway(), m_settings->routeMode()); });
@@ -234,7 +233,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede
} }
#endif #endif
m_remoteAddress = credentials.hostName; m_remoteAddress = NetworkUtilities::getIPAddress(credentials.hostName);
emit connectionStateChanged(Vpn::ConnectionState::Connecting); emit connectionStateChanged(Vpn::ConnectionState::Connecting);
m_vpnConfiguration = vpnConfiguration; m_vpnConfiguration = vpnConfiguration;
@@ -291,27 +290,62 @@ void VpnConnection::appendKillSwitchConfig()
void VpnConnection::appendSplitTunnelingConfig() void VpnConnection::appendSplitTunnelingConfig()
{ {
if (m_vpnConfiguration.value(config_key::configVersion).toInt()) { bool allowSiteBasedSplitTunneling = true;
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) { // this block is for old native configs and for old self-hosted configs
allowedIpsJsonArray.append(m_vpnConfiguration.value(config_key::dns1).toString()); auto protocolName = m_vpnConfiguration.value(config_key::vpnproto).toString();
allowedIpsJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString()); if (protocolName == ProtocolProps::protoToString(Proto::Awg) || protocolName == ProtocolProps::protoToString(Proto::WireGuard)) {
allowSiteBasedSplitTunneling = false;
m_vpnConfiguration.insert(config_key::splitTunnelType, Settings::RouteMode::VpnOnlyForwardSites); auto configData = m_vpnConfiguration.value(protocolName + "_config_data").toObject();
m_vpnConfiguration.insert(config_key::splitTunnelSites, allowedIpsJsonArray); 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;
}
} }
} }
} else {
Settings::RouteMode routeMode = Settings::RouteMode::VpnAllSites;
QJsonArray sitesJsonArray;
if (m_settings->isSitesSplitTunnelingEnabled()) {
routeMode = m_settings->routeMode();
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;
}
}
}
QJsonArray allowedIpsJsonArray = configData.value(config_key::allowed_ips).toArray();
if (allowedIpsJsonArray.contains("0.0.0.0/0") && allowedIpsJsonArray.contains("::/0")) {
allowSiteBasedSplitTunneling = true;
}
}
Settings::RouteMode routeMode = Settings::RouteMode::VpnAllSites;
QJsonArray sitesJsonArray;
if (m_settings->isSitesSplitTunnelingEnabled()) {
routeMode = m_settings->routeMode();
if (allowSiteBasedSplitTunneling) {
auto sites = m_settings->getVpnIps(routeMode); auto sites = m_settings->getVpnIps(routeMode);
for (const auto &site : sites) { for (const auto &site : sites) {
sitesJsonArray.append(site); sitesJsonArray.append(site);
@@ -323,11 +357,11 @@ void VpnConnection::appendSplitTunnelingConfig()
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString()); sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString());
} }
} }
m_vpnConfiguration.insert(config_key::splitTunnelType, routeMode);
m_vpnConfiguration.insert(config_key::splitTunnelSites, sitesJsonArray);
} }
m_vpnConfiguration.insert(config_key::splitTunnelType, routeMode);
m_vpnConfiguration.insert(config_key::splitTunnelSites, sitesJsonArray);
Settings::AppsRouteMode appsRouteMode = Settings::AppsRouteMode::VpnAllApps; Settings::AppsRouteMode appsRouteMode = Settings::AppsRouteMode::VpnAllApps;
QJsonArray appsJsonArray; QJsonArray appsJsonArray;
if (m_settings->isAppsSplitTunnelingEnabled()) { if (m_settings->isAppsSplitTunnelingEnabled()) {
@@ -359,8 +393,7 @@ void VpnConnection::createAndroidConnections()
connect(AndroidController::instance(), &AndroidController::connectionStateChanged, androidVpnProtocol, connect(AndroidController::instance(), &AndroidController::connectionStateChanged, androidVpnProtocol,
&AndroidVpnProtocol::setConnectionState); &AndroidVpnProtocol::setConnectionState);
connect(AndroidController::instance(), &AndroidController::statisticsUpdated, androidVpnProtocol, connect(AndroidController::instance(), &AndroidController::statisticsUpdated, androidVpnProtocol, &AndroidVpnProtocol::setBytesChanged);
&AndroidVpnProtocol::setBytesChanged);
} }
AndroidVpnProtocol *VpnConnection::createDefaultAndroidVpnProtocol() AndroidVpnProtocol *VpnConnection::createDefaultAndroidVpnProtocol()