From 2380cd5cfbe75b610c2bba4c3748aef5982f50fa Mon Sep 17 00:00:00 2001 From: Nethius Date: Mon, 7 Jul 2025 12:03:25 +0800 Subject: [PATCH] feat: amneziawg 1.5 support (#1692) * Version bump 4.2.1.0 * feat: add special handshake params to ui * feat: finish adding params * feat: android/ios & fix qml * chore: fix android impl & update 3rd-prebuilt branch * chore: trigger build with windows build * fix: special handshake params to client * chore: update submodule * feat: s3, s4 * chore: update submodule * feat: s3 s4 cont * fix: kt set * chore: update submodule * feat: add default values for s3, s4 * fix: make new parameters optional * chore: update submodules * chore: restore translation files * fix: fixed awg native config import with new junk * chore: restore translation files * AWG v1.5 Build * refactoring: removed s3 s4 fileds from ui part * chore: update link to amneziawg-apple --------- Co-authored-by: pokamest Co-authored-by: Mark Puha Co-authored-by: albexk Co-authored-by: Mykola Baibuz --- .gitmodules | 1 + client/3rd-prebuilt | 2 +- client/3rd/amneziawg-apple | 2 +- .../vpn/protocol/wireguard/Wireguard.kt | 11 + .../vpn/protocol/wireguard/WireguardConfig.kt | 59 +++++- client/configurators/awg_configurator.cpp | 15 ++ client/core/controllers/serverController.cpp | 18 +- client/daemon/daemon.cpp | 37 +++- client/daemon/interfaceconfig.cpp | 16 ++ client/daemon/interfaceconfig.h | 5 + client/mozilla/localsocketcontroller.cpp | 39 +++- client/platforms/ios/WGConfig.swift | 22 +- client/platforms/ios/ios_controller.mm | 26 ++- .../linux/daemon/wireguardutilslinux.cpp | 16 ++ .../macos/daemon/wireguardutilsmacos.cpp | 16 ++ client/protocols/protocols_defs.h | 23 ++ client/resources.qrc | 1 + client/server_scripts/awg/Dockerfile | 5 +- .../server_scripts/awg/configure_container.sh | 1 + .../controllers/api/apiConfigsController.cpp | 18 ++ client/ui/controllers/importController.cpp | 56 +++-- client/ui/controllers/installController.cpp | 56 ++++- client/ui/models/protocols/awgConfigModel.cpp | 109 +++++++++- client/ui/models/protocols/awgConfigModel.h | 33 ++- client/ui/qml/Components/AwgTextField.qml | 15 ++ .../Pages2/PageProtocolAwgClientSettings.qml | 198 +++++++++++++----- .../ui/qml/Pages2/PageProtocolAwgSettings.qml | 144 +++++-------- 27 files changed, 758 insertions(+), 186 deletions(-) create mode 100644 client/ui/qml/Components/AwgTextField.qml diff --git a/.gitmodules b/.gitmodules index decab9b7..90edb582 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,7 @@ [submodule "client/3rd-prebuilt"] path = client/3rd-prebuilt url = https://github.com/amnezia-vpn/3rd-prebuilt + branch = feature/special-handshake [submodule "client/3rd/amneziawg-apple"] path = client/3rd/amneziawg-apple url = https://github.com/amnezia-vpn/amneziawg-apple diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt index 0f3748ef..840b7b07 160000 --- a/client/3rd-prebuilt +++ b/client/3rd-prebuilt @@ -1 +1 @@ -Subproject commit 0f3748efd7cc04e0c914304b68931f925bed1259 +Subproject commit 840b7b070e6ac8b90dda2fac6e98859b23727c0c diff --git a/client/3rd/amneziawg-apple b/client/3rd/amneziawg-apple index 76e7db55..811af0a8 160000 --- a/client/3rd/amneziawg-apple +++ b/client/3rd/amneziawg-apple @@ -1 +1 @@ -Subproject commit 76e7db556a6d7e2582f9481df91db188a46c009c +Subproject commit 811af0a83b3faeade89a9093a588595666d32066 diff --git a/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt b/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt index 80cab96d..42a27de4 100644 --- a/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt +++ b/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt @@ -120,10 +120,21 @@ open class Wireguard : Protocol() { configData.optStringOrNull("Jmax")?.let { setJmax(it.toInt()) } configData.optStringOrNull("S1")?.let { setS1(it.toInt()) } configData.optStringOrNull("S2")?.let { setS2(it.toInt()) } + configData.optStringOrNull("S3")?.let { setS3(it.toInt()) } + configData.optStringOrNull("S4")?.let { setS4(it.toInt()) } configData.optStringOrNull("H1")?.let { setH1(it.toLong()) } configData.optStringOrNull("H2")?.let { setH2(it.toLong()) } configData.optStringOrNull("H3")?.let { setH3(it.toLong()) } configData.optStringOrNull("H4")?.let { setH4(it.toLong()) } + configData.optStringOrNull("I1")?.let { setI1(it) } + configData.optStringOrNull("I2")?.let { setI2(it) } + configData.optStringOrNull("I3")?.let { setI3(it) } + configData.optStringOrNull("I4")?.let { setI4(it) } + configData.optStringOrNull("I5")?.let { setI5(it) } + configData.optStringOrNull("J1")?.let { setJ1(it) } + configData.optStringOrNull("J2")?.let { setJ2(it) } + configData.optStringOrNull("J3")?.let { setJ3(it) } + configData.optStringOrNull("Itime")?.let { setItime(it.toInt()) } } private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) { diff --git a/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/WireguardConfig.kt b/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/WireguardConfig.kt index 7ae3d43b..2dfbbae8 100644 --- a/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/WireguardConfig.kt +++ b/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/WireguardConfig.kt @@ -20,10 +20,21 @@ open class WireguardConfig protected constructor( val jmax: Int?, val s1: Int?, val s2: Int?, + val s3: Int?, + val s4: Int?, val h1: Long?, val h2: Long?, val h3: Long?, - val h4: Long? + val h4: Long?, + var i1: String?, + var i2: String?, + var i3: String?, + var i4: String?, + var i5: String?, + var j1: String?, + var j2: String?, + var j3: String?, + var itime: Int? ) : ProtocolConfig(protocolConfigBuilder) { protected constructor(builder: Builder) : this( @@ -39,10 +50,21 @@ open class WireguardConfig protected constructor( builder.jmax, builder.s1, builder.s2, + builder.s3, + builder.s4, builder.h1, builder.h2, builder.h3, - builder.h4 + builder.h4, + builder.i1, + builder.i2, + builder.i3, + builder.i4, + builder.i5, + builder.j1, + builder.j2, + builder.j3, + builder.itime ) fun toWgUserspaceString(): String = with(StringBuilder()) { @@ -61,10 +83,21 @@ open class WireguardConfig protected constructor( appendLine("jmax=$jmax") appendLine("s1=$s1") appendLine("s2=$s2") + s3?.let { appendLine("s3=$it") } + s4?.let { appendLine("s4=$it") } appendLine("h1=$h1") appendLine("h2=$h2") appendLine("h3=$h3") appendLine("h4=$h4") + i1?.let { appendLine("i1=$it") } + i2?.let { appendLine("i2=$it") } + i3?.let { appendLine("i3=$it") } + i4?.let { appendLine("i4=$it") } + i5?.let { appendLine("i5=$it") } + j1?.let { appendLine("j1=$it") } + j2?.let { appendLine("j2=$it") } + j3?.let { appendLine("j3=$it") } + itime?.let { appendLine("itime=$it") } } } @@ -117,10 +150,21 @@ open class WireguardConfig protected constructor( internal var jmax: Int? = null internal var s1: Int? = null internal var s2: Int? = null + internal var s3: Int? = null + internal var s4: Int? = null internal var h1: Long? = null internal var h2: Long? = null internal var h3: Long? = null internal var h4: Long? = null + internal var i1: String? = null + internal var i2: String? = null + internal var i3: String? = null + internal var i4: String? = null + internal var i5: String? = null + internal var j1: String? = null + internal var j2: String? = null + internal var j3: String? = null + internal var itime: Int? = null fun setEndpoint(endpoint: InetEndpoint) = apply { this.endpoint = endpoint } @@ -139,10 +183,21 @@ open class WireguardConfig protected constructor( fun setJmax(jmax: Int) = apply { this.jmax = jmax } fun setS1(s1: Int) = apply { this.s1 = s1 } fun setS2(s2: Int) = apply { this.s2 = s2 } + fun setS3(s3: Int) = apply { this.s3 = s3 } + fun setS4(s4: Int) = apply { this.s4 = s4 } fun setH1(h1: Long) = apply { this.h1 = h1 } fun setH2(h2: Long) = apply { this.h2 = h2 } fun setH3(h3: Long) = apply { this.h3 = h3 } fun setH4(h4: Long) = apply { this.h4 = h4 } + fun setI1(i1: String) = apply { this.i1 = i1 } + fun setI2(i2: String) = apply { this.i2 = i2 } + fun setI3(i3: String) = apply { this.i3 = i3 } + fun setI4(i4: String) = apply { this.i4 = i4 } + fun setI5(i5: String) = apply { this.i5 = i5 } + fun setJ1(j1: String) = apply { this.j1 = j1 } + fun setJ2(j2: String) = apply { this.j2 = j2 } + fun setJ3(j3: String) = apply { this.j3 = j3 } + fun setItime(itime: Int) = apply { this.itime = itime } override fun build(): WireguardConfig = configBuild().run { WireguardConfig(this@Builder) } } diff --git a/client/configurators/awg_configurator.cpp b/client/configurators/awg_configurator.cpp index 21b61ba4..f83acb19 100644 --- a/client/configurators/awg_configurator.cpp +++ b/client/configurators/awg_configurator.cpp @@ -1,4 +1,5 @@ #include "awg_configurator.h" +#include "protocols/protocols_defs.h" #include #include @@ -39,6 +40,20 @@ QString AwgConfigurator::createConfig(const ServerCredentials &credentials, Dock jsonConfig[config_key::responsePacketMagicHeader] = configMap.value(config_key::responsePacketMagicHeader); jsonConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader); jsonConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader); + + // jsonConfig[config_key::cookieReplyPacketJunkSize] = configMap.value(config_key::cookieReplyPacketJunkSize); + // jsonConfig[config_key::transportPacketJunkSize] = configMap.value(config_key::transportPacketJunkSize); + + // jsonConfig[config_key::specialJunk1] = configMap.value(amnezia::config_key::specialJunk1); + // jsonConfig[config_key::specialJunk2] = configMap.value(amnezia::config_key::specialJunk2); + // jsonConfig[config_key::specialJunk3] = configMap.value(amnezia::config_key::specialJunk3); + // jsonConfig[config_key::specialJunk4] = configMap.value(amnezia::config_key::specialJunk4); + // jsonConfig[config_key::specialJunk5] = configMap.value(amnezia::config_key::specialJunk5); + // jsonConfig[config_key::controlledJunk1] = configMap.value(amnezia::config_key::controlledJunk1); + // jsonConfig[config_key::controlledJunk2] = configMap.value(amnezia::config_key::controlledJunk2); + // jsonConfig[config_key::controlledJunk3] = configMap.value(amnezia::config_key::controlledJunk3); + // jsonConfig[config_key::specialHandshakeTimeout] = configMap.value(amnezia::config_key::specialHandshakeTimeout); + jsonConfig[config_key::mtu] = containerConfig.value(ProtocolProps::protoToString(Proto::Awg)).toObject().value(config_key::mtu).toString(protocols::awg::defaultMtu); diff --git a/client/core/controllers/serverController.cpp b/client/core/controllers/serverController.cpp index a61a638b..3c24edea 100644 --- a/client/core/controllers/serverController.cpp +++ b/client/core/controllers/serverController.cpp @@ -349,7 +349,7 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) != newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)) || (oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort) - != newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)) + != newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)) || (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount) != newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)) || (oldProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize) @@ -366,8 +366,13 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c != newProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader)) || (oldProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader) != newProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader)) - || (oldProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader) - != newProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader))) + || (oldProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader)) + != newProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader)) + // || (oldProtoConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize) + // != newProtoConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize)) + // || (oldProtoConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize) + // != newProtoConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize)) + return true; } @@ -375,7 +380,7 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) != newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)) || (oldProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) - != newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort))) + != newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort))) return true; } @@ -455,7 +460,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)), cbReadStdOut, cbReadStdErr); - + if (stdOut.contains("doesn't work on cgroups v2")) return ErrorCode::ServerDockerOnCgroupsV2; if (stdOut.contains("cgroup mountpoint does not exist")) @@ -641,6 +646,9 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential vars.append({ { "$UNDERLOAD_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::underloadPacketMagicHeader).toString() } }); vars.append({ { "$TRANSPORT_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::transportPacketMagicHeader).toString() } }); + vars.append({ { "$COOKIE_REPLY_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::cookieReplyPacketJunkSize).toString() } }); + vars.append({ { "$TRANSPORT_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::transportPacketJunkSize).toString() } }); + // Socks5 proxy vars vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } }); auto username = socks5ProxyConfig.value(config_key::userName).toString(); diff --git a/client/daemon/daemon.cpp b/client/daemon/daemon.cpp index 33ec8cbc..2faff0ef 100644 --- a/client/daemon/daemon.cpp +++ b/client/daemon/daemon.cpp @@ -405,6 +405,13 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) { if (!obj.value("S2").isNull()) { config.m_responsePacketJunkSize = obj.value("S2").toString(); } + if (!obj.value("S3").isNull()) { + config.m_cookieReplyPacketJunkSize = obj.value("S3").toString(); + } + if (!obj.value("S4").isNull()) { + config.m_transportPacketJunkSize = obj.value("S4").toString(); + } + if (!obj.value("H1").isNull()) { config.m_initPacketMagicHeader = obj.value("H1").toString(); } @@ -418,6 +425,34 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) { config.m_transportPacketMagicHeader = obj.value("H4").toString(); } + if (!obj.value("I1").isNull()) { + config.m_specialJunk["I1"] = obj.value("I1").toString(); + } + if (!obj.value("I2").isNull()) { + config.m_specialJunk["I2"] = obj.value("I2").toString(); + } + if (!obj.value("I3").isNull()) { + config.m_specialJunk["I3"] = obj.value("I3").toString(); + } + if (!obj.value("I4").isNull()) { + config.m_specialJunk["I4"] = obj.value("I4").toString(); + } + if (!obj.value("I5").isNull()) { + config.m_specialJunk["I5"] = obj.value("I5").toString(); + } + if (!obj.value("J1").isNull()) { + config.m_controlledJunk["J1"] = obj.value("J1").toString(); + } + if (!obj.value("J2").isNull()) { + config.m_controlledJunk["J2"] = obj.value("J2").toString(); + } + if (!obj.value("J3").isNull()) { + config.m_controlledJunk["J3"] = obj.value("J3").toString(); + } + if (!obj.value("Itime").isNull()) { + config.m_specialHandshakeTimeout = obj.value("Itime").toString(); + } + return true; } @@ -460,7 +495,7 @@ bool Daemon::deactivate(bool emitSignals) { m_connections.clear(); // Delete the interface - return wgutils()->deleteInterface(); + return wgutils()->deleteInterface(); } QString Daemon::logs() { diff --git a/client/daemon/interfaceconfig.cpp b/client/daemon/interfaceconfig.cpp index 846cfebe..53da5d36 100644 --- a/client/daemon/interfaceconfig.cpp +++ b/client/daemon/interfaceconfig.cpp @@ -130,6 +130,12 @@ QString InterfaceConfig::toWgConf(const QMap& extra) const { if (!m_responsePacketJunkSize.isNull()) { out << "S2 = " << m_responsePacketJunkSize << "\n"; } + if (!m_cookieReplyPacketJunkSize.isNull()) { + out << "S3 = " << m_cookieReplyPacketJunkSize << "\n"; + } + if (!m_transportPacketJunkSize.isNull()) { + out << "S4 = " << m_transportPacketJunkSize << "\n"; + } if (!m_initPacketMagicHeader.isNull()) { out << "H1 = " << m_initPacketMagicHeader << "\n"; } @@ -143,6 +149,16 @@ QString InterfaceConfig::toWgConf(const QMap& extra) const { out << "H4 = " << m_transportPacketMagicHeader << "\n"; } + for (const QString& key : m_specialJunk.keys()) { + out << key << " = " << m_specialJunk[key] << "\n"; + } + for (const QString& key : m_controlledJunk.keys()) { + out << key << " = " << m_controlledJunk[key] << "\n"; + } + if (!m_specialHandshakeTimeout.isNull()) { + out << "Itime = " << m_specialHandshakeTimeout << "\n"; + } + // If any extra config was provided, append it now. for (const QString& key : extra.keys()) { out << key << " = " << extra[key] << "\n"; diff --git a/client/daemon/interfaceconfig.h b/client/daemon/interfaceconfig.h index 6ae400c2..06288e80 100644 --- a/client/daemon/interfaceconfig.h +++ b/client/daemon/interfaceconfig.h @@ -50,10 +50,15 @@ class InterfaceConfig { QString m_junkPacketMaxSize; QString m_initPacketJunkSize; QString m_responsePacketJunkSize; + QString m_cookieReplyPacketJunkSize; + QString m_transportPacketJunkSize; QString m_initPacketMagicHeader; QString m_responsePacketMagicHeader; QString m_underloadPacketMagicHeader; QString m_transportPacketMagicHeader; + QMap m_specialJunk; + QMap m_controlledJunk; + QString m_specialHandshakeTimeout; QJsonObject toJson() const; QString toWgConf( diff --git a/client/mozilla/localsocketcontroller.cpp b/client/mozilla/localsocketcontroller.cpp index 67924d47..9abab81c 100644 --- a/client/mozilla/localsocketcontroller.cpp +++ b/client/mozilla/localsocketcontroller.cpp @@ -38,7 +38,7 @@ LocalSocketController::LocalSocketController() { m_socket = new QLocalSocket(this); connect(m_socket, &QLocalSocket::connected, this, &LocalSocketController::daemonConnected); - connect(m_socket, &QLocalSocket::disconnected, this, + connect(m_socket, &QLocalSocket::disconnected, this, [&] { errorOccurred(QLocalSocket::PeerClosedError); }); connect(m_socket, &QLocalSocket::errorOccurred, this, &LocalSocketController::errorOccurred); @@ -135,7 +135,7 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) { // set up IPv6 unique-local-address, ULA, with "fd00::/8" prefix, not globally routable. // this will be default IPv6 gateway, OS recognizes that IPv6 link is local and switches to IPv4. - // Otherwise some OSes (Linux) try IPv6 forever and hang. + // Otherwise some OSes (Linux) try IPv6 forever and hang. // https://en.wikipedia.org/wiki/Unique_local_address (RFC 4193) // https://man7.org/linux/man-pages/man5/gai.conf.5.html json.insert("deviceIpv6Address", "fd58:baa6:dead::1"); // simply "dead::1" is globally-routable, don't use it @@ -244,28 +244,61 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) { json.insert(amnezia::config_key::junkPacketMaxSize, wgConfig.value(amnezia::config_key::junkPacketMaxSize)); json.insert(amnezia::config_key::initPacketJunkSize, wgConfig.value(amnezia::config_key::initPacketJunkSize)); json.insert(amnezia::config_key::responsePacketJunkSize, wgConfig.value(amnezia::config_key::responsePacketJunkSize)); + json.insert(amnezia::config_key::cookieReplyPacketJunkSize, wgConfig.value(amnezia::config_key::cookieReplyPacketJunkSize)); + json.insert(amnezia::config_key::transportPacketJunkSize, wgConfig.value(amnezia::config_key::transportPacketJunkSize)); json.insert(amnezia::config_key::initPacketMagicHeader, wgConfig.value(amnezia::config_key::initPacketMagicHeader)); json.insert(amnezia::config_key::responsePacketMagicHeader, wgConfig.value(amnezia::config_key::responsePacketMagicHeader)); json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader)); json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader)); + json.insert(amnezia::config_key::specialJunk1, wgConfig.value(amnezia::config_key::specialJunk1)); + json.insert(amnezia::config_key::specialJunk2, wgConfig.value(amnezia::config_key::specialJunk2)); + json.insert(amnezia::config_key::specialJunk3, wgConfig.value(amnezia::config_key::specialJunk3)); + json.insert(amnezia::config_key::specialJunk4, wgConfig.value(amnezia::config_key::specialJunk4)); + json.insert(amnezia::config_key::specialJunk5, wgConfig.value(amnezia::config_key::specialJunk5)); + json.insert(amnezia::config_key::controlledJunk1, wgConfig.value(amnezia::config_key::controlledJunk1)); + json.insert(amnezia::config_key::controlledJunk2, wgConfig.value(amnezia::config_key::controlledJunk2)); + json.insert(amnezia::config_key::controlledJunk3, wgConfig.value(amnezia::config_key::controlledJunk3)); + json.insert(amnezia::config_key::specialHandshakeTimeout, wgConfig.value(amnezia::config_key::specialHandshakeTimeout)); } else if (!wgConfig.value(amnezia::config_key::junkPacketCount).isUndefined() && !wgConfig.value(amnezia::config_key::junkPacketMinSize).isUndefined() && !wgConfig.value(amnezia::config_key::junkPacketMaxSize).isUndefined() && !wgConfig.value(amnezia::config_key::initPacketJunkSize).isUndefined() && !wgConfig.value(amnezia::config_key::responsePacketJunkSize).isUndefined() + && !wgConfig.value(amnezia::config_key::cookieReplyPacketJunkSize).isUndefined() + && !wgConfig.value(amnezia::config_key::transportPacketJunkSize).isUndefined() && !wgConfig.value(amnezia::config_key::initPacketMagicHeader).isUndefined() && !wgConfig.value(amnezia::config_key::responsePacketMagicHeader).isUndefined() && !wgConfig.value(amnezia::config_key::underloadPacketMagicHeader).isUndefined() - && !wgConfig.value(amnezia::config_key::transportPacketMagicHeader).isUndefined()) { + && !wgConfig.value(amnezia::config_key::transportPacketMagicHeader).isUndefined() + && !wgConfig.value(amnezia::config_key::specialJunk1).isUndefined() + && !wgConfig.value(amnezia::config_key::specialJunk2).isUndefined() + && !wgConfig.value(amnezia::config_key::specialJunk3).isUndefined() + && !wgConfig.value(amnezia::config_key::specialJunk4).isUndefined() + && !wgConfig.value(amnezia::config_key::specialJunk5).isUndefined() + && !wgConfig.value(amnezia::config_key::controlledJunk1).isUndefined() + && !wgConfig.value(amnezia::config_key::controlledJunk2).isUndefined() + && !wgConfig.value(amnezia::config_key::controlledJunk3).isUndefined() + && !wgConfig.value(amnezia::config_key::specialHandshakeTimeout).isUndefined()) { json.insert(amnezia::config_key::junkPacketCount, wgConfig.value(amnezia::config_key::junkPacketCount)); json.insert(amnezia::config_key::junkPacketMinSize, wgConfig.value(amnezia::config_key::junkPacketMinSize)); json.insert(amnezia::config_key::junkPacketMaxSize, wgConfig.value(amnezia::config_key::junkPacketMaxSize)); json.insert(amnezia::config_key::initPacketJunkSize, wgConfig.value(amnezia::config_key::initPacketJunkSize)); json.insert(amnezia::config_key::responsePacketJunkSize, wgConfig.value(amnezia::config_key::responsePacketJunkSize)); + json.insert(amnezia::config_key::cookieReplyPacketJunkSize, wgConfig.value(amnezia::config_key::cookieReplyPacketJunkSize)); + json.insert(amnezia::config_key::transportPacketJunkSize, wgConfig.value(amnezia::config_key::transportPacketJunkSize)); json.insert(amnezia::config_key::initPacketMagicHeader, wgConfig.value(amnezia::config_key::initPacketMagicHeader)); json.insert(amnezia::config_key::responsePacketMagicHeader, wgConfig.value(amnezia::config_key::responsePacketMagicHeader)); json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader)); json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader)); + json.insert(amnezia::config_key::specialJunk1, wgConfig.value(amnezia::config_key::specialJunk1)); + json.insert(amnezia::config_key::specialJunk2, wgConfig.value(amnezia::config_key::specialJunk2)); + json.insert(amnezia::config_key::specialJunk3, wgConfig.value(amnezia::config_key::specialJunk3)); + json.insert(amnezia::config_key::specialJunk4, wgConfig.value(amnezia::config_key::specialJunk4)); + json.insert(amnezia::config_key::specialJunk5, wgConfig.value(amnezia::config_key::specialJunk5)); + json.insert(amnezia::config_key::controlledJunk1, wgConfig.value(amnezia::config_key::controlledJunk1)); + json.insert(amnezia::config_key::controlledJunk2, wgConfig.value(amnezia::config_key::controlledJunk2)); + json.insert(amnezia::config_key::controlledJunk3, wgConfig.value(amnezia::config_key::controlledJunk3)); + json.insert(amnezia::config_key::specialHandshakeTimeout, wgConfig.value(amnezia::config_key::specialHandshakeTimeout)); } write(json); diff --git a/client/platforms/ios/WGConfig.swift b/client/platforms/ios/WGConfig.swift index e3b67efe..8f693387 100644 --- a/client/platforms/ios/WGConfig.swift +++ b/client/platforms/ios/WGConfig.swift @@ -4,7 +4,10 @@ struct WGConfig: Decodable { let initPacketMagicHeader, responsePacketMagicHeader: String? let underloadPacketMagicHeader, transportPacketMagicHeader: String? let junkPacketCount, junkPacketMinSize, junkPacketMaxSize: String? - let initPacketJunkSize, responsePacketJunkSize: String? + let initPacketJunkSize, responsePacketJunkSize, cookieReplyPacketJunkSize, transportPacketJunkSize: String? + let specialJunk1, specialJunk2, specialJunk3, specialJunk4, specialJunk5: String? + let controlledJunk1, controlledJunk2, controlledJunk3: String? + let specialHandshakeTimeout: String? let dns1: String let dns2: String let mtu: String @@ -23,7 +26,10 @@ struct WGConfig: Decodable { case initPacketMagicHeader = "H1", responsePacketMagicHeader = "H2" case underloadPacketMagicHeader = "H3", transportPacketMagicHeader = "H4" case junkPacketCount = "Jc", junkPacketMinSize = "Jmin", junkPacketMaxSize = "Jmax" - case initPacketJunkSize = "S1", responsePacketJunkSize = "S2" + case initPacketJunkSize = "S1", responsePacketJunkSize = "S2", cookieReplyPacketJunkSize = "S3", transportPacketJunkSize = "S4" + case specialJunk1 = "I1", specialJunk2 = "I2", specialJunk3 = "I3", specialJunk4 = "I4", specialJunk5 = "I5" + case controlledJunk1 = "J1", controlledJunk2 = "J2", controlledJunk3 = "J3" + case specialHandshakeTimeout = "Itime" case dns1 case dns2 case mtu @@ -47,11 +53,21 @@ struct WGConfig: Decodable { Jmax = \(junkPacketMaxSize!) S1 = \(initPacketJunkSize!) S2 = \(responsePacketJunkSize!) + S3 = \(cookieReplyPacketJunkSize!) + S4 = \(transportPacketJunkSize!) H1 = \(initPacketMagicHeader!) H2 = \(responsePacketMagicHeader!) H3 = \(underloadPacketMagicHeader!) H4 = \(transportPacketMagicHeader!) - + I1 = \(specialJunk1!) + I2 = \(specialJunk2!) + I3 = \(specialJunk3!) + I4 = \(specialJunk4!) + I5 = \(specialJunk5!) + J1 = \(controlledJunk1!) + J2 = \(controlledJunk2!) + J3 = \(controlledJunk3!) + Itime = \(specialHandshakeTimeout!) """ } diff --git a/client/platforms/ios/ios_controller.mm b/client/platforms/ios/ios_controller.mm index 85fb50b7..e64c6dce 100644 --- a/client/platforms/ios/ios_controller.mm +++ b/client/platforms/ios/ios_controller.mm @@ -507,6 +507,8 @@ bool IosController::setupWireGuard() wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]); wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]); + wgConfig.insert(config_key::cookieReplyPacketJunkSize, config[config_key::cookieReplyPacketJunkSize]); + wgConfig.insert(config_key::transportPacketJunkSize, config[config_key::transportPacketJunkSize]); wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]); wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]); @@ -605,11 +607,23 @@ bool IosController::setupAwg() wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]); wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]); + wgConfig.insert(config_key::cookieReplyPacketJunkSize, config[config_key::cookieReplyPacketJunkSize]); + wgConfig.insert(config_key::transportPacketJunkSize, config[config_key::transportPacketJunkSize]); wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]); wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]); wgConfig.insert(config_key::junkPacketMaxSize, config[config_key::junkPacketMaxSize]); + wgConfig.insert(config_key::specialJunk1, config[config_key::specialJunk1]); + wgConfig.insert(config_key::specialJunk2, config[config_key::specialJunk2]); + wgConfig.insert(config_key::specialJunk3, config[config_key::specialJunk3]); + wgConfig.insert(config_key::specialJunk4, config[config_key::specialJunk4]); + wgConfig.insert(config_key::specialJunk5, config[config_key::specialJunk5]); + wgConfig.insert(config_key::controlledJunk1, config[config_key::controlledJunk1]); + wgConfig.insert(config_key::controlledJunk2, config[config_key::controlledJunk2]); + wgConfig.insert(config_key::controlledJunk3, config[config_key::controlledJunk3]); + wgConfig.insert(config_key::specialHandshakeTimeout, config[config_key::specialHandshakeTimeout]); + QJsonDocument wgConfigDoc(wgConfig); QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact)); @@ -794,9 +808,9 @@ bool IosController::shareText(const QStringList& filesToSend) { if (!qtController) return; UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil]; - + __block bool isAccepted = false; - + [activityController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) { isAccepted = completed; emit finished(); @@ -808,11 +822,11 @@ bool IosController::shareText(const QStringList& filesToSend) { popController.sourceView = qtController.view; popController.sourceRect = CGRectMake(100, 100, 100, 100); } - + QEventLoop wait; QObject::connect(this, &IosController::finished, &wait, &QEventLoop::quit); wait.exec(); - + return isAccepted; } @@ -826,7 +840,7 @@ QString IosController::openFile() { if (!qtController) return; [qtController presentViewController:documentPicker animated:YES completion:nil]; - + __block QString filePath; documentPickerDelegate.documentPickerClosedCallback = ^(NSString *path) { @@ -841,7 +855,7 @@ QString IosController::openFile() { QEventLoop wait; QObject::connect(this, &IosController::finished, &wait, &QEventLoop::quit); wait.exec(); - + return filePath; } diff --git a/client/platforms/linux/daemon/wireguardutilslinux.cpp b/client/platforms/linux/daemon/wireguardutilslinux.cpp index a12b8582..cfde73e2 100644 --- a/client/platforms/linux/daemon/wireguardutilslinux.cpp +++ b/client/platforms/linux/daemon/wireguardutilslinux.cpp @@ -121,6 +121,12 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) { if (!config.m_responsePacketJunkSize.isEmpty()) { out << "s2=" << config.m_responsePacketJunkSize << "\n"; } + if (!config.m_cookieReplyPacketJunkSize.isEmpty()) { + out << "s3=" << config.m_cookieReplyPacketJunkSize << "\n"; + } + if (!config.m_transportPacketJunkSize.isEmpty()) { + out << "s4=" << config.m_transportPacketJunkSize << "\n"; + } if (!config.m_initPacketMagicHeader.isEmpty()) { out << "h1=" << config.m_initPacketMagicHeader << "\n"; } @@ -134,6 +140,16 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) { out << "h4=" << config.m_transportPacketMagicHeader << "\n"; } + for (const QString& key : config.m_specialJunk.keys()) { + out << key.toLower() << "=" << config.m_specialJunk.value(key) << "\n"; + } + for (const QString& key : config.m_controlledJunk.keys()) { + out << key.toLower() << "=" << config.m_controlledJunk.value(key) << "\n"; + } + if (!config.m_specialHandshakeTimeout.isEmpty()) { + out << "itime=" << config.m_specialHandshakeTimeout << "\n"; + } + int err = uapiErrno(uapiCommand(message)); if (err != 0) { logger.error() << "Interface configuration failed:" << strerror(err); diff --git a/client/platforms/macos/daemon/wireguardutilsmacos.cpp b/client/platforms/macos/daemon/wireguardutilsmacos.cpp index 37170f20..cce4afab 100644 --- a/client/platforms/macos/daemon/wireguardutilsmacos.cpp +++ b/client/platforms/macos/daemon/wireguardutilsmacos.cpp @@ -119,6 +119,12 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) { if (!config.m_responsePacketJunkSize.isEmpty()) { out << "s2=" << config.m_responsePacketJunkSize << "\n"; } + if (!config.m_cookieReplyPacketJunkSize.isEmpty()) { + out << "s3=" << config.m_cookieReplyPacketJunkSize << "\n"; + } + if (!config.m_transportPacketJunkSize.isEmpty()) { + out << "s4=" << config.m_transportPacketJunkSize << "\n"; + } if (!config.m_initPacketMagicHeader.isEmpty()) { out << "h1=" << config.m_initPacketMagicHeader << "\n"; } @@ -132,6 +138,16 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) { out << "h4=" << config.m_transportPacketMagicHeader << "\n"; } + for (const QString& key : config.m_specialJunk.keys()) { + out << key.toLower() << "=" << config.m_specialJunk.value(key) << "\n"; + } + for (const QString& key : config.m_controlledJunk.keys()) { + out << key.toLower() << "=" << config.m_controlledJunk.value(key) << "\n"; + } + if (!config.m_specialHandshakeTimeout.isEmpty()) { + out << "itime=" << config.m_specialHandshakeTimeout << "\n"; + } + int err = uapiErrno(uapiCommand(message)); if (err != 0) { logger.error() << "Interface configuration failed:" << strerror(err); diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index c2d51454..b4cbb6de 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -72,10 +72,21 @@ namespace amnezia constexpr char junkPacketMaxSize[] = "Jmax"; constexpr char initPacketJunkSize[] = "S1"; constexpr char responsePacketJunkSize[] = "S2"; + constexpr char cookieReplyPacketJunkSize[] = "S3"; + constexpr char transportPacketJunkSize[] = "S4"; constexpr char initPacketMagicHeader[] = "H1"; constexpr char responsePacketMagicHeader[] = "H2"; constexpr char underloadPacketMagicHeader[] = "H3"; constexpr char transportPacketMagicHeader[] = "H4"; + constexpr char specialJunk1[] = "I1"; + constexpr char specialJunk2[] = "I2"; + constexpr char specialJunk3[] = "I3"; + constexpr char specialJunk4[] = "I4"; + constexpr char specialJunk5[] = "I5"; + constexpr char controlledJunk1[] = "J1"; + constexpr char controlledJunk2[] = "J2"; + constexpr char controlledJunk3[] = "J3"; + constexpr char specialHandshakeTimeout[] = "Itime"; constexpr char openvpn[] = "openvpn"; constexpr char wireguard[] = "wireguard"; @@ -216,10 +227,22 @@ namespace amnezia constexpr char defaultJunkPacketMaxSize[] = "30"; constexpr char defaultInitPacketJunkSize[] = "15"; constexpr char defaultResponsePacketJunkSize[] = "18"; + constexpr char defaultCookieReplyPacketJunkSize[] = "20"; + constexpr char defaultTransportPacketJunkSize[] = "23"; + constexpr char defaultInitPacketMagicHeader[] = "1020325451"; constexpr char defaultResponsePacketMagicHeader[] = "3288052141"; constexpr char defaultTransportPacketMagicHeader[] = "2528465083"; constexpr char defaultUnderloadPacketMagicHeader[] = "1766607858"; + constexpr char defaultSpecialJunk1[] = ""; + constexpr char defaultSpecialJunk2[] = ""; + constexpr char defaultSpecialJunk3[] = ""; + constexpr char defaultSpecialJunk4[] = ""; + constexpr char defaultSpecialJunk5[] = ""; + constexpr char defaultControlledJunk1[] = ""; + constexpr char defaultControlledJunk2[] = ""; + constexpr char defaultControlledJunk3[] = ""; + constexpr char defaultSpecialHandshakeTimeout[] = ""; } namespace socks5Proxy diff --git a/client/resources.qrc b/client/resources.qrc index 72eb15c7..54b5846c 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -239,6 +239,7 @@ ui/qml/Components/ApiPremV1MigrationDrawer.qml ui/qml/Components/ApiPremV1SubListDrawer.qml ui/qml/Components/OtpCodeDrawer.qml + ui/qml/Components/AwgTextField.qml images/flagKit/ZW.svg diff --git a/client/server_scripts/awg/Dockerfile b/client/server_scripts/awg/Dockerfile index 8c536fc7..a6118a84 100644 --- a/client/server_scripts/awg/Dockerfile +++ b/client/server_scripts/awg/Dockerfile @@ -10,7 +10,7 @@ RUN mkdir -p /opt/amnezia RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh RUN chmod a+x /opt/amnezia/start.sh -# Tune network +# Tune network RUN echo -e " \n\ fs.file-max = 51200 \n\ \n\ @@ -40,7 +40,8 @@ RUN echo -e " \n\ echo -e " \n\ * soft nofile 51200 \n\ * hard nofile 51200 \n\ - " | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf + " | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf ENTRYPOINT [ "dumb-init", "/opt/amnezia/start.sh" ] CMD [ "" ] + diff --git a/client/server_scripts/awg/configure_container.sh b/client/server_scripts/awg/configure_container.sh index 2000c965..e327f080 100644 --- a/client/server_scripts/awg/configure_container.sh +++ b/client/server_scripts/awg/configure_container.sh @@ -23,4 +23,5 @@ H1 = $INIT_PACKET_MAGIC_HEADER H2 = $RESPONSE_PACKET_MAGIC_HEADER H3 = $UNDERLOAD_PACKET_MAGIC_HEADER H4 = $TRANSPORT_PACKET_MAGIC_HEADER + EOF diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp index eb693a9a..0b0a9b92 100644 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ b/client/ui/controllers/api/apiConfigsController.cpp @@ -162,6 +162,9 @@ namespace auto serverProtocolConfig = container.value(containerName).toObject(); auto clientProtocolConfig = QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object(); + + //TODO looks like this block can be removed after v1 configs EOL + serverProtocolConfig[config_key::junkPacketCount] = clientProtocolConfig.value(config_key::junkPacketCount); serverProtocolConfig[config_key::junkPacketMinSize] = clientProtocolConfig.value(config_key::junkPacketMinSize); serverProtocolConfig[config_key::junkPacketMaxSize] = clientProtocolConfig.value(config_key::junkPacketMaxSize); @@ -171,6 +174,21 @@ namespace serverProtocolConfig[config_key::responsePacketMagicHeader] = clientProtocolConfig.value(config_key::responsePacketMagicHeader); serverProtocolConfig[config_key::underloadPacketMagicHeader] = clientProtocolConfig.value(config_key::underloadPacketMagicHeader); serverProtocolConfig[config_key::transportPacketMagicHeader] = clientProtocolConfig.value(config_key::transportPacketMagicHeader); + + serverProtocolConfig[config_key::cookieReplyPacketJunkSize] = clientProtocolConfig.value(config_key::cookieReplyPacketJunkSize); + serverProtocolConfig[config_key::transportPacketJunkSize] = clientProtocolConfig.value(config_key::transportPacketJunkSize); + serverProtocolConfig[config_key::specialJunk1] = clientProtocolConfig.value(config_key::specialJunk1); + serverProtocolConfig[config_key::specialJunk2] = clientProtocolConfig.value(config_key::specialJunk2); + serverProtocolConfig[config_key::specialJunk3] = clientProtocolConfig.value(config_key::specialJunk3); + serverProtocolConfig[config_key::specialJunk4] = clientProtocolConfig.value(config_key::specialJunk4); + serverProtocolConfig[config_key::specialJunk5] = clientProtocolConfig.value(config_key::specialJunk5); + serverProtocolConfig[config_key::controlledJunk1] = clientProtocolConfig.value(config_key::controlledJunk1); + serverProtocolConfig[config_key::controlledJunk2] = clientProtocolConfig.value(config_key::controlledJunk2); + serverProtocolConfig[config_key::controlledJunk3] = clientProtocolConfig.value(config_key::controlledJunk3); + serverProtocolConfig[config_key::specialHandshakeTimeout] = clientProtocolConfig.value(config_key::specialHandshakeTimeout); + + // + container[containerName] = serverProtocolConfig; containers.replace(0, container); newServerConfig[config_key::containers] = containers; diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index fdc06120..ea1d5d8e 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -12,6 +12,7 @@ #include "core/errorstrings.h" #include "core/qrCodeUtils.h" #include "core/serialization/serialization.h" +#include "protocols/protocols_defs.h" #include "systemController.h" #include "utilities.h" @@ -286,6 +287,19 @@ void ImportController::processNativeWireGuardConfig() clientProtocolConfig[config_key::underloadPacketMagicHeader] = "3"; clientProtocolConfig[config_key::transportPacketMagicHeader] = "4"; + // clientProtocolConfig[config_key::cookieReplyPacketJunkSize] = "0"; + // clientProtocolConfig[config_key::transportPacketJunkSize] = "0"; + + // clientProtocolConfig[config_key::specialJunk1] = ""; + // clientProtocolConfig[config_key::specialJunk2] = ""; + // clientProtocolConfig[config_key::specialJunk3] = ""; + // clientProtocolConfig[config_key::specialJunk4] = ""; + // clientProtocolConfig[config_key::specialJunk5] = ""; + // clientProtocolConfig[config_key::controlledJunk1] = ""; + // clientProtocolConfig[config_key::controlledJunk2] = ""; + // clientProtocolConfig[config_key::controlledJunk3] = ""; + // clientProtocolConfig[config_key::specialHandshakeTimeout] = "0"; + clientProtocolConfig[config_key::isObfuscationEnabled] = true; serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(clientProtocolConfig).toJson()); @@ -438,21 +452,33 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data) lastConfig[config_key::allowed_ips] = allowedIpsJsonArray; QString protocolName = "wireguard"; - if (!configMap.value(config_key::junkPacketCount).isEmpty() && !configMap.value(config_key::junkPacketMinSize).isEmpty() - && !configMap.value(config_key::junkPacketMaxSize).isEmpty() && !configMap.value(config_key::initPacketJunkSize).isEmpty() - && !configMap.value(config_key::responsePacketJunkSize).isEmpty() && !configMap.value(config_key::initPacketMagicHeader).isEmpty() - && !configMap.value(config_key::responsePacketMagicHeader).isEmpty() - && !configMap.value(config_key::underloadPacketMagicHeader).isEmpty() - && !configMap.value(config_key::transportPacketMagicHeader).isEmpty()) { - lastConfig[config_key::junkPacketCount] = configMap.value(config_key::junkPacketCount); - lastConfig[config_key::junkPacketMinSize] = configMap.value(config_key::junkPacketMinSize); - lastConfig[config_key::junkPacketMaxSize] = configMap.value(config_key::junkPacketMaxSize); - lastConfig[config_key::initPacketJunkSize] = configMap.value(config_key::initPacketJunkSize); - lastConfig[config_key::responsePacketJunkSize] = configMap.value(config_key::responsePacketJunkSize); - lastConfig[config_key::initPacketMagicHeader] = configMap.value(config_key::initPacketMagicHeader); - lastConfig[config_key::responsePacketMagicHeader] = configMap.value(config_key::responsePacketMagicHeader); - lastConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader); - lastConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader); + + const QStringList requiredJunkFields = { config_key::junkPacketCount, config_key::junkPacketMinSize, + config_key::junkPacketMaxSize, config_key::initPacketJunkSize, + config_key::responsePacketJunkSize, config_key::initPacketMagicHeader, + config_key::responsePacketMagicHeader, config_key::underloadPacketMagicHeader, + config_key::transportPacketMagicHeader }; + + const QStringList optionalJunkFields = { // config_key::cookieReplyPacketJunkSize, + // config_key::transportPacketJunkSize, + config_key::specialJunk1, config_key::specialJunk2, config_key::specialJunk3, + config_key::specialJunk4, config_key::specialJunk5, config_key::controlledJunk1, + config_key::controlledJunk2, config_key::controlledJunk3, config_key::specialHandshakeTimeout + }; + + bool hasAllRequiredFields = std::all_of(requiredJunkFields.begin(), requiredJunkFields.end(), + [&configMap](const QString &field) { return !configMap.value(field).isEmpty(); }); + if (hasAllRequiredFields) { + for (const QString &field : requiredJunkFields) { + lastConfig[field] = configMap.value(field); + } + + for (const QString &field : optionalJunkFields) { + if (!configMap.value(field).isEmpty()) { + lastConfig[field] = configMap.value(field); + } + } + protocolName = "awg"; m_configType = ConfigTypes::Awg; } diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp index eab8979a..d7f9dfbc 100755 --- a/client/ui/controllers/installController.cpp +++ b/client/ui/controllers/installController.cpp @@ -8,6 +8,7 @@ #include #include +#include "core/api/apiUtils.h" #include "core/controllers/serverController.h" #include "core/controllers/vpnConfigurationController.h" #include "core/networkUtilities.h" @@ -15,7 +16,6 @@ #include "ui/models/protocols/awgConfigModel.h" #include "ui/models/protocols/wireguardConfigModel.h" #include "utilities.h" -#include "core/api/apiUtils.h" namespace { @@ -79,12 +79,36 @@ void InstallController::install(DockerContainer container, int port, TransportPr int s1 = QRandomGenerator::global()->bounded(15, 150); int s2 = QRandomGenerator::global()->bounded(15, 150); - while (s1 + AwgConstant::messageInitiationSize == s2 + AwgConstant::messageResponseSize) { + // int s3 = QRandomGenerator::global()->bounded(15, 150); + // int s4 = QRandomGenerator::global()->bounded(15, 150); + + // Ensure all values are unique and don't create equal packet sizes + QSet usedValues; + usedValues.insert(s1); + + while (usedValues.contains(s2) || s1 + AwgConstant::messageInitiationSize == s2 + AwgConstant::messageResponseSize) { s2 = QRandomGenerator::global()->bounded(15, 150); } + usedValues.insert(s2); + + // while (usedValues.contains(s3) + // || s1 + AwgConstant::messageInitiationSize == s3 + AwgConstant::messageCookieReplySize + // || s2 + AwgConstant::messageResponseSize == s3 + AwgConstant::messageCookieReplySize) { + // s3 = QRandomGenerator::global()->bounded(15, 150); + // } + // usedValues.insert(s3); + + // while (usedValues.contains(s4) + // || s1 + AwgConstant::messageInitiationSize == s4 + AwgConstant::messageTransportSize + // || s2 + AwgConstant::messageResponseSize == s4 + AwgConstant::messageTransportSize + // || s3 + AwgConstant::messageCookieReplySize == s4 + AwgConstant::messageTransportSize) { + // s4 = QRandomGenerator::global()->bounded(15, 150); + // } QString initPacketJunkSize = QString::number(s1); QString responsePacketJunkSize = QString::number(s2); + // QString cookieReplyPacketJunkSize = QString::number(s3); + // QString transportPacketJunkSize = QString::number(s4); QSet headersValue; while (headersValue.size() != 4) { @@ -108,6 +132,21 @@ void InstallController::install(DockerContainer container, int port, TransportPr containerConfig[config_key::responsePacketMagicHeader] = responsePacketMagicHeader; containerConfig[config_key::underloadPacketMagicHeader] = underloadPacketMagicHeader; containerConfig[config_key::transportPacketMagicHeader] = transportPacketMagicHeader; + + // TODO: + // containerConfig[config_key::cookieReplyPacketJunkSize] = cookieReplyPacketJunkSize; + // containerConfig[config_key::transportPacketJunkSize] = transportPacketJunkSize; + + // containerConfig[config_key::specialJunk1] = specialJunk1; + // containerConfig[config_key::specialJunk2] = specialJunk2; + // containerConfig[config_key::specialJunk3] = specialJunk3; + // containerConfig[config_key::specialJunk4] = specialJunk4; + // containerConfig[config_key::specialJunk5] = specialJunk5; + // containerConfig[config_key::controlledJunk1] = controlledJunk1; + // containerConfig[config_key::controlledJunk2] = controlledJunk2; + // containerConfig[config_key::controlledJunk3] = controlledJunk3; + // containerConfig[config_key::specialHandshakeTimeout] = specialHandshakeTimeout; + } else if (container == DockerContainer::Sftp) { containerConfig.insert(config_key::userName, protocols::sftp::defaultUserName); containerConfig.insert(config_key::password, Utils::getRandomString(16)); @@ -401,6 +440,19 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia containerConfig[config_key::transportPacketMagicHeader] = serverConfigMap.value(config_key::transportPacketMagicHeader); + // containerConfig[config_key::cookieReplyPacketJunkSize] = serverConfigMap.value(config_key::cookieReplyPacketJunkSize); + // containerConfig[config_key::transportPacketJunkSize] = serverConfigMap.value(config_key::transportPacketJunkSize); + + // containerConfig[config_key::specialJunk1] = serverConfigMap.value(config_key::specialJunk1); + // containerConfig[config_key::specialJunk2] = serverConfigMap.value(config_key::specialJunk2); + // containerConfig[config_key::specialJunk3] = serverConfigMap.value(config_key::specialJunk3); + // containerConfig[config_key::specialJunk4] = serverConfigMap.value(config_key::specialJunk4); + // containerConfig[config_key::specialJunk5] = serverConfigMap.value(config_key::specialJunk5); + // containerConfig[config_key::controlledJunk1] = serverConfigMap.value(config_key::controlledJunk1); + // containerConfig[config_key::controlledJunk2] = serverConfigMap.value(config_key::controlledJunk2); + // containerConfig[config_key::controlledJunk3] = serverConfigMap.value(config_key::controlledJunk3); + // containerConfig[config_key::specialHandshakeTimeout] = serverConfigMap.value(config_key::specialHandshakeTimeout); + } else if (protocol == Proto::WireGuard) { QString serverConfig = serverController->getTextFileFromContainer(container, credentials, protocols::wireguard::serverConfigPath, errorCode); diff --git a/client/ui/models/protocols/awgConfigModel.cpp b/client/ui/models/protocols/awgConfigModel.cpp index 860c8395..e14a3152 100644 --- a/client/ui/models/protocols/awgConfigModel.cpp +++ b/client/ui/models/protocols/awgConfigModel.cpp @@ -28,7 +28,17 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break; case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break; case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break; - + case Roles::ClientSpecialJunk1Role: m_clientProtocolConfig.insert(config_key::specialJunk1, value.toString()); break; + case Roles::ClientSpecialJunk2Role: m_clientProtocolConfig.insert(config_key::specialJunk2, value.toString()); break; + case Roles::ClientSpecialJunk3Role: m_clientProtocolConfig.insert(config_key::specialJunk3, value.toString()); break; + case Roles::ClientSpecialJunk4Role: m_clientProtocolConfig.insert(config_key::specialJunk4, value.toString()); break; + case Roles::ClientSpecialJunk5Role: m_clientProtocolConfig.insert(config_key::specialJunk5, value.toString()); break; + case Roles::ClientControlledJunk1Role: m_clientProtocolConfig.insert(config_key::controlledJunk1, value.toString()); break; + case Roles::ClientControlledJunk2Role: m_clientProtocolConfig.insert(config_key::controlledJunk2, value.toString()); break; + case Roles::ClientControlledJunk3Role: m_clientProtocolConfig.insert(config_key::controlledJunk3, value.toString()); break; + case Roles::ClientSpecialHandshakeTimeoutRole: + m_clientProtocolConfig.insert(config_key::specialHandshakeTimeout, value.toString()); + break; case Roles::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break; case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break; case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break; @@ -36,6 +46,12 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in case Roles::ServerResponsePacketJunkSizeRole: m_serverProtocolConfig.insert(config_key::responsePacketJunkSize, value.toString()); break; + // case Roles::ServerCookieReplyPacketJunkSizeRole: + // m_serverProtocolConfig.insert(config_key::cookieReplyPacketJunkSize, value.toString()); + // break; + // case Roles::ServerTransportPacketJunkSizeRole: + // m_serverProtocolConfig.insert(config_key::transportPacketJunkSize, 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()); @@ -66,12 +82,23 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount); case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize); case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMaxSize); + case Roles::ClientSpecialJunk1Role: return m_clientProtocolConfig.value(config_key::specialJunk1); + case Roles::ClientSpecialJunk2Role: return m_clientProtocolConfig.value(config_key::specialJunk2); + case Roles::ClientSpecialJunk3Role: return m_clientProtocolConfig.value(config_key::specialJunk3); + case Roles::ClientSpecialJunk4Role: return m_clientProtocolConfig.value(config_key::specialJunk4); + case Roles::ClientSpecialJunk5Role: return m_clientProtocolConfig.value(config_key::specialJunk5); + case Roles::ClientControlledJunk1Role: return m_clientProtocolConfig.value(config_key::controlledJunk1); + case Roles::ClientControlledJunk2Role: return m_clientProtocolConfig.value(config_key::controlledJunk2); + case Roles::ClientControlledJunk3Role: return m_clientProtocolConfig.value(config_key::controlledJunk3); + case Roles::ClientSpecialHandshakeTimeoutRole: return m_clientProtocolConfig.value(config_key::specialHandshakeTimeout); case Roles::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount); case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize); case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize); case Roles::ServerInitPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::initPacketJunkSize); case Roles::ServerResponsePacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::responsePacketJunkSize); + // case Roles::ServerCookieReplyPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::cookieReplyPacketJunkSize); + // case Roles::ServerTransportPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::transportPacketJunkSize); 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); @@ -94,7 +121,8 @@ void AwgConfigModel::updateModel(const QJsonObject &config) m_serverProtocolConfig.insert(config_key::transport_proto, serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config); - m_serverProtocolConfig[config_key::subnet_address] = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); + m_serverProtocolConfig[config_key::subnet_address] = + serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort); m_serverProtocolConfig[config_key::junkPacketCount] = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); @@ -106,6 +134,10 @@ void AwgConfigModel::updateModel(const QJsonObject &config) serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); m_serverProtocolConfig[config_key::responsePacketJunkSize] = serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); + // m_serverProtocolConfig[config_key::cookieReplyPacketJunkSize] = + // serverProtocolConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize); + // m_serverProtocolConfig[config_key::transportPacketJunkSize] = + // serverProtocolConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize); m_serverProtocolConfig[config_key::initPacketMagicHeader] = serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); m_serverProtocolConfig[config_key::responsePacketMagicHeader] = @@ -124,6 +156,24 @@ void AwgConfigModel::updateModel(const QJsonObject &config) 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()); + m_clientProtocolConfig[config_key::specialJunk1] = + clientProtocolConfig.value(config_key::specialJunk1).toString(protocols::awg::defaultSpecialJunk1); + m_clientProtocolConfig[config_key::specialJunk2] = + clientProtocolConfig.value(config_key::specialJunk2).toString(protocols::awg::defaultSpecialJunk2); + m_clientProtocolConfig[config_key::specialJunk3] = + clientProtocolConfig.value(config_key::specialJunk3).toString(protocols::awg::defaultSpecialJunk3); + m_clientProtocolConfig[config_key::specialJunk4] = + clientProtocolConfig.value(config_key::specialJunk4).toString(protocols::awg::defaultSpecialJunk4); + m_clientProtocolConfig[config_key::specialJunk5] = + clientProtocolConfig.value(config_key::specialJunk5).toString(protocols::awg::defaultSpecialJunk5); + m_clientProtocolConfig[config_key::controlledJunk1] = + clientProtocolConfig.value(config_key::controlledJunk1).toString(protocols::awg::defaultControlledJunk1); + m_clientProtocolConfig[config_key::controlledJunk2] = + clientProtocolConfig.value(config_key::controlledJunk2).toString(protocols::awg::defaultControlledJunk2); + m_clientProtocolConfig[config_key::controlledJunk3] = + clientProtocolConfig.value(config_key::controlledJunk3).toString(protocols::awg::defaultControlledJunk3); + m_clientProtocolConfig[config_key::specialHandshakeTimeout] = + clientProtocolConfig.value(config_key::specialHandshakeTimeout).toString(protocols::awg::defaultSpecialHandshakeTimeout); endResetModel(); } @@ -141,6 +191,15 @@ QJsonObject AwgConfigModel::getConfig() 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]; + jsonConfig[config_key::specialJunk1] = m_clientProtocolConfig[config_key::specialJunk1]; + jsonConfig[config_key::specialJunk2] = m_clientProtocolConfig[config_key::specialJunk2]; + jsonConfig[config_key::specialJunk3] = m_clientProtocolConfig[config_key::specialJunk3]; + jsonConfig[config_key::specialJunk4] = m_clientProtocolConfig[config_key::specialJunk4]; + jsonConfig[config_key::specialJunk5] = m_clientProtocolConfig[config_key::specialJunk5]; + jsonConfig[config_key::controlledJunk1] = m_clientProtocolConfig[config_key::controlledJunk1]; + jsonConfig[config_key::controlledJunk2] = m_clientProtocolConfig[config_key::controlledJunk2]; + jsonConfig[config_key::controlledJunk3] = m_clientProtocolConfig[config_key::controlledJunk3]; + jsonConfig[config_key::specialHandshakeTimeout] = m_clientProtocolConfig[config_key::specialHandshakeTimeout]; m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); } @@ -159,6 +218,17 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2) return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2); } +// bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2, const int s3, const int s4) +// { +// int initSize = AwgConstant::messageInitiationSize + s1; +// int responseSize = AwgConstant::messageResponseSize + s2; +// int cookieSize = AwgConstant::messageCookieReplySize + s3; +// int transportSize = AwgConstant::messageTransportSize + s4; + +// return (initSize == responseSize || initSize == cookieSize || initSize == transportSize || responseSize == cookieSize +// || responseSize == transportSize || cookieSize == transportSize); +// } + bool AwgConfigModel::isServerSettingsEqual() { const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); @@ -178,12 +248,24 @@ QHash AwgConfigModel::roleNames() const roles[ClientJunkPacketCountRole] = "clientJunkPacketCount"; roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize"; roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize"; + roles[ClientSpecialJunk1Role] = "clientSpecialJunk1"; + roles[ClientSpecialJunk2Role] = "clientSpecialJunk2"; + roles[ClientSpecialJunk3Role] = "clientSpecialJunk3"; + roles[ClientSpecialJunk4Role] = "clientSpecialJunk4"; + roles[ClientSpecialJunk5Role] = "clientSpecialJunk5"; + roles[ClientControlledJunk1Role] = "clientControlledJunk1"; + roles[ClientControlledJunk2Role] = "clientControlledJunk2"; + roles[ClientControlledJunk3Role] = "clientControlledJunk3"; + roles[ClientSpecialHandshakeTimeoutRole] = "clientSpecialHandshakeTimeout"; roles[ServerJunkPacketCountRole] = "serverJunkPacketCount"; roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize"; roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize"; roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize"; roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize"; + roles[ServerCookieReplyPacketJunkSizeRole] = "serverCookieReplyPacketJunkSize"; + roles[ServerTransportPacketJunkSizeRole] = "serverTransportPacketJunkSize"; + roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader"; roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader"; roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader"; @@ -200,6 +282,16 @@ AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig) clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); + clientSpecialJunk1 = clientProtocolConfig.value(config_key::specialJunk1).toString(protocols::awg::defaultSpecialJunk1); + clientSpecialJunk2 = clientProtocolConfig.value(config_key::specialJunk2).toString(protocols::awg::defaultSpecialJunk2); + clientSpecialJunk3 = clientProtocolConfig.value(config_key::specialJunk3).toString(protocols::awg::defaultSpecialJunk3); + clientSpecialJunk4 = clientProtocolConfig.value(config_key::specialJunk4).toString(protocols::awg::defaultSpecialJunk4); + clientSpecialJunk5 = clientProtocolConfig.value(config_key::specialJunk5).toString(protocols::awg::defaultSpecialJunk5); + clientControlledJunk1 = clientProtocolConfig.value(config_key::controlledJunk1).toString(protocols::awg::defaultControlledJunk1); + clientControlledJunk2 = clientProtocolConfig.value(config_key::controlledJunk2).toString(protocols::awg::defaultControlledJunk2); + clientControlledJunk3 = clientProtocolConfig.value(config_key::controlledJunk3).toString(protocols::awg::defaultControlledJunk3); + clientSpecialHandshakeTimeout = + clientProtocolConfig.value(config_key::specialHandshakeTimeout).toString(protocols::awg::defaultSpecialHandshakeTimeout); subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort); @@ -209,6 +301,10 @@ AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig) serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); serverResponsePacketJunkSize = serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); + // serverCookieReplyPacketJunkSize = + // serverProtocolConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize); + // serverTransportPacketJunkSize = + // serverProtocolConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize); serverInitPacketMagicHeader = serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); serverResponsePacketMagicHeader = @@ -224,6 +320,8 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const if (subnetAddress != other.subnetAddress || port != other.port || serverJunkPacketCount != other.serverJunkPacketCount || serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize || serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize + // || serverCookieReplyPacketJunkSize != other.serverCookieReplyPacketJunkSize + // || serverTransportPacketJunkSize != other.serverTransportPacketJunkSize || serverInitPacketMagicHeader != other.serverInitPacketMagicHeader || serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader || serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader @@ -236,7 +334,12 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const { if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount - || clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize) { + || clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize + || clientSpecialJunk1 != other.clientSpecialJunk1 || clientSpecialJunk2 != other.clientSpecialJunk2 + || clientSpecialJunk3 != other.clientSpecialJunk3 || clientSpecialJunk4 != other.clientSpecialJunk4 + || clientSpecialJunk5 != other.clientSpecialJunk5 || clientControlledJunk1 != other.clientControlledJunk1 + || clientControlledJunk2 != other.clientControlledJunk2 || clientControlledJunk3 != other.clientControlledJunk3 + || clientSpecialHandshakeTimeout != other.clientSpecialHandshakeTimeout) { return false; } return true; diff --git a/client/ui/models/protocols/awgConfigModel.h b/client/ui/models/protocols/awgConfigModel.h index c1f8bb27..0c2374fc 100644 --- a/client/ui/models/protocols/awgConfigModel.h +++ b/client/ui/models/protocols/awgConfigModel.h @@ -6,9 +6,12 @@ #include "containers/containers_defs.h" -namespace AwgConstant { +namespace AwgConstant +{ const int messageInitiationSize = 148; const int messageResponseSize = 92; + const int messageCookieReplySize = 64; + const int messageTransportSize = 32; } struct AwgConfig @@ -22,12 +25,23 @@ struct AwgConfig QString clientJunkPacketCount; QString clientJunkPacketMinSize; QString clientJunkPacketMaxSize; + QString clientSpecialJunk1; + QString clientSpecialJunk2; + QString clientSpecialJunk3; + QString clientSpecialJunk4; + QString clientSpecialJunk5; + QString clientControlledJunk1; + QString clientControlledJunk2; + QString clientControlledJunk3; + QString clientSpecialHandshakeTimeout; QString serverJunkPacketCount; QString serverJunkPacketMinSize; QString serverJunkPacketMaxSize; QString serverInitPacketJunkSize; QString serverResponsePacketJunkSize; + QString serverCookieReplyPacketJunkSize; + QString serverTransportPacketJunkSize; QString serverInitPacketMagicHeader; QString serverResponsePacketMagicHeader; QString serverUnderloadPacketMagicHeader; @@ -35,7 +49,6 @@ struct AwgConfig bool hasEqualServerSettings(const AwgConfig &other) const; bool hasEqualClientSettings(const AwgConfig &other) const; - }; class AwgConfigModel : public QAbstractListModel @@ -51,16 +64,28 @@ public: ClientJunkPacketCountRole, ClientJunkPacketMinSizeRole, ClientJunkPacketMaxSizeRole, + ClientSpecialJunk1Role, + ClientSpecialJunk2Role, + ClientSpecialJunk3Role, + ClientSpecialJunk4Role, + ClientSpecialJunk5Role, + ClientControlledJunk1Role, + ClientControlledJunk2Role, + ClientControlledJunk3Role, + ClientSpecialHandshakeTimeoutRole, ServerJunkPacketCountRole, ServerJunkPacketMinSizeRole, ServerJunkPacketMaxSizeRole, ServerInitPacketJunkSizeRole, ServerResponsePacketJunkSizeRole, + ServerCookieReplyPacketJunkSizeRole, + ServerTransportPacketJunkSizeRole, + ServerInitPacketMagicHeaderRole, ServerResponsePacketMagicHeaderRole, ServerUnderloadPacketMagicHeaderRole, - ServerTransportPacketMagicHeaderRole + ServerTransportPacketMagicHeaderRole, }; explicit AwgConfigModel(QObject *parent = nullptr); @@ -75,7 +100,7 @@ public slots: QJsonObject getConfig(); 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/*, const int s3, const int s4*/); bool isServerSettingsEqual(); diff --git a/client/ui/qml/Components/AwgTextField.qml b/client/ui/qml/Components/AwgTextField.qml new file mode 100644 index 00000000..87b023d9 --- /dev/null +++ b/client/ui/qml/Components/AwgTextField.qml @@ -0,0 +1,15 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Layouts + +import "../Controls2" + +TextFieldWithHeaderType { + Layout.fillWidth: true + Layout.topMargin: 16 + + textField.validator: IntValidator { bottom: 0 } + + checkEmptyText: true +} diff --git a/client/ui/qml/Pages2/PageProtocolAwgClientSettings.qml b/client/ui/qml/Pages2/PageProtocolAwgClientSettings.qml index b8cf5f93..d97d09e8 100644 --- a/client/ui/qml/Pages2/PageProtocolAwgClientSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolAwgClientSettings.qml @@ -115,14 +115,10 @@ PageType { KeyNavigation.tab: junkPacketCountTextField.textField } - TextFieldWithHeaderType { + AwgTextField { id: junkPacketCountTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: "Jc - Junk packet count" textField.text: clientJunkPacketCount - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== clientJunkPacketCount) { @@ -130,19 +126,13 @@ PageType { } } - checkEmptyText: true - KeyNavigation.tab: junkPacketMinSizeTextField.textField } - TextFieldWithHeaderType { + AwgTextField { id: junkPacketMinSizeTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: "Jmin - Junk packet minimum size" textField.text: clientJunkPacketMinSize - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== clientJunkPacketMinSize) { @@ -150,28 +140,144 @@ PageType { } } - checkEmptyText: true - KeyNavigation.tab: junkPacketMaxSizeTextField.textField } - TextFieldWithHeaderType { + AwgTextField { id: junkPacketMaxSizeTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: "Jmax - Junk packet maximum size" textField.text: clientJunkPacketMaxSize - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== clientJunkPacketMaxSize) { clientJunkPacketMaxSize = textField.text } } + } - checkEmptyText: true + AwgTextField { + id: specialJunk1TextField + headerText: qsTr("I1 - First special junk packet") + textField.text: clientSpecialJunk1 + textField.validator: null + checkEmptyText: false + textField.onEditingFinished: { + if (textField.text !== clientSpecialJunk1) { + clientSpecialJunk1 = textField.text + } + } + } + + AwgTextField { + id: specialJunk2TextField + headerText: qsTr("I2 - Second special junk packet") + textField.text: clientSpecialJunk2 + textField.validator: null + checkEmptyText: false + + textField.onEditingFinished: { + if (textField.text !== clientSpecialJunk2) { + clientSpecialJunk2 = textField.text + } + } + } + + AwgTextField { + id: specialJunk3TextField + headerText: qsTr("I3 - Third special junk packet") + textField.text: clientSpecialJunk3 + textField.validator: null + checkEmptyText: false + + textField.onEditingFinished: { + if (textField.text !== clientSpecialJunk3) { + clientSpecialJunk3 = textField.text + } + } + } + + AwgTextField { + id: specialJunk4TextField + headerText: qsTr("I4 - Fourth special junk packet") + textField.text: clientSpecialJunk4 + textField.validator: null + checkEmptyText: false + + textField.onEditingFinished: { + if (textField.text !== clientSpecialJunk4) { + clientSpecialJunk4 = textField.text + } + } + } + + AwgTextField { + id: specialJunk5TextField + headerText: qsTr("I5 - Fifth special junk packet") + textField.text: clientSpecialJunk5 + textField.validator: null + checkEmptyText: false + + textField.onEditingFinished: { + if (textField.text !== clientSpecialJunk5 ) { + clientSpecialJunk5 = textField.text + } + } + } + + AwgTextField { + id: controlledJunk1TextField + headerText: qsTr("J1 - First controlled junk packet") + textField.text: clientControlledJunk1 + textField.validator: null + checkEmptyText: false + + textField.onEditingFinished: { + if (textField.text !== clientControlledJunk1) { + clientControlledJunk1 = textField.text + } + } + } + + AwgTextField { + id: controlledJunk2TextField + headerText: qsTr("J2 - Second controlled junk packet") + textField.text: clientControlledJunk2 + textField.validator: null + checkEmptyText: false + + textField.onEditingFinished: { + if (textField.text !== clientControlledJunk2) { + clientControlledJunk2 = textField.text + } + } + } + + AwgTextField { + id: controlledJunk3TextField + headerText: qsTr("J3 - Third controlled junk packet") + textField.text: clientControlledJunk3 + textField.validator: null + checkEmptyText: false + + textField.onEditingFinished: { + if (textField.text !== clientControlledJunk3) { + clientControlledJunk3 = textField.text + } + } + } + + AwgTextField { + id: iTimeTextField + headerText: qsTr("Itime - Special handshake timeout") + textField.text: clientSpecialHandshakeTimeout + checkEmptyText: false + + textField.onEditingFinished: { + if (textField.text !== clientSpecialHandshakeTimeout) { + clientSpecialHandshakeTimeout = textField.text + } + } } Header2TextType { @@ -181,82 +287,78 @@ PageType { text: qsTr("Server settings") } - TextFieldWithHeaderType { + AwgTextField { id: portTextField - Layout.fillWidth: true - Layout.topMargin: 8 - enabled: false headerText: qsTr("Port") textField.text: port } - TextFieldWithHeaderType { + AwgTextField { id: initPacketJunkSizeTextField - Layout.fillWidth: true - Layout.topMargin: 16 - enabled: false headerText: "S1 - Init packet junk size" textField.text: serverInitPacketJunkSize } - TextFieldWithHeaderType { + AwgTextField { id: responsePacketJunkSizeTextField - Layout.fillWidth: true - Layout.topMargin: 16 - enabled: false headerText: "S2 - Response packet junk size" textField.text: serverResponsePacketJunkSize } - TextFieldWithHeaderType { - id: initPacketMagicHeaderTextField - Layout.fillWidth: true - Layout.topMargin: 16 + // AwgTextField { + // id: cookieReplyPacketJunkSizeTextField + // enabled: false + // headerText: "S3 - Cookie Reply packet junk size" + // textField.text: serverCookieReplyPacketJunkSize + // } + + // AwgTextField { + // id: transportPacketJunkSizeTextField + // enabled: false + + // headerText: "S4 - Transport packet junk size" + // textField.text: serverTransportPacketJunkSize + // } + + AwgTextField { + id: initPacketMagicHeaderTextField enabled: false headerText: "H1 - Init packet magic header" textField.text: serverInitPacketMagicHeader } - TextFieldWithHeaderType { + AwgTextField { id: responsePacketMagicHeaderTextField - Layout.fillWidth: true - Layout.topMargin: 16 - enabled: false headerText: "H2 - Response packet magic header" textField.text: serverResponsePacketMagicHeader } - TextFieldWithHeaderType { + AwgTextField { id: underloadPacketMagicHeaderTextField - Layout.fillWidth: true - Layout.topMargin: 16 - enabled: false headerText: "H3 - Underload packet magic header" textField.text: serverUnderloadPacketMagicHeader } - TextFieldWithHeaderType { + AwgTextField { id: transportPacketMagicHeaderTextField - Layout.fillWidth: true - Layout.topMargin: 16 - enabled: false headerText: "H4 - Transport packet magic header" textField.text: serverTransportPacketMagicHeader } + } } } diff --git a/client/ui/qml/Pages2/PageProtocolAwgSettings.qml b/client/ui/qml/Pages2/PageProtocolAwgSettings.qml index e8fd2b94..699ae724 100644 --- a/client/ui/qml/Pages2/PageProtocolAwgSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolAwgSettings.qml @@ -138,184 +138,139 @@ PageType { checkEmptyText: true } - TextFieldWithHeaderType { + AwgTextField { id: junkPacketCountTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: qsTr("Jc - Junk packet count") textField.text: serverJunkPacketCount - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { - if (textField.text === "") { - textField.text = "0" - } - if (textField.text !== serverJunkPacketCount) { serverJunkPacketCount = textField.text } } - - checkEmptyText: true } - TextFieldWithHeaderType { + AwgTextField { id: junkPacketMinSizeTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: qsTr("Jmin - Junk packet minimum size") textField.text: serverJunkPacketMinSize - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== serverJunkPacketMinSize) { serverJunkPacketMinSize = textField.text } } - - checkEmptyText: true } - TextFieldWithHeaderType { + AwgTextField { id: junkPacketMaxSizeTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: qsTr("Jmax - Junk packet maximum size") textField.text: serverJunkPacketMaxSize - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== serverJunkPacketMaxSize) { serverJunkPacketMaxSize = textField.text } } - - checkEmptyText: true } - TextFieldWithHeaderType { + AwgTextField { id: initPacketJunkSizeTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: qsTr("S1 - Init packet junk size") textField.text: serverInitPacketJunkSize - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== serverInitPacketJunkSize) { serverInitPacketJunkSize = textField.text } } - - checkEmptyText: true - - onActiveFocusChanged: { - if(activeFocus) { - listview.positionViewAtEnd() - } - } } - TextFieldWithHeaderType { + AwgTextField { id: responsePacketJunkSizeTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: qsTr("S2 - Response packet junk size") textField.text: serverResponsePacketJunkSize - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== serverResponsePacketJunkSize) { serverResponsePacketJunkSize = textField.text } } - - checkEmptyText: true - - onActiveFocusChanged: { - if(activeFocus) { - listview.positionViewAtEnd() - } - } } - TextFieldWithHeaderType { - id: initPacketMagicHeaderTextField - Layout.fillWidth: true - Layout.topMargin: 16 + // AwgTextField { + // id: cookieReplyPacketJunkSizeTextField + // headerText: qsTr("S3 - Cookie reply packet junk size") + // textField.text: serverCookieReplyPacketJunkSize + // textField.onEditingFinished: { + // if (textField.text !== serverCookieReplyPacketJunkSize) { + // serverCookieReplyPacketJunkSize = textField.text + // } + // } + // } + + // AwgTextField { + // id: transportPacketJunkSizeTextField + // headerText: qsTr("S4 - Transport packet junk size") + // textField.text: serverTransportPacketJunkSize + + // textField.onEditingFinished: { + // if (textField.text !== serverTransportPacketJunkSize) { + // serverTransportPacketJunkSize = textField.text + // } + // } + // } + + AwgTextField { + id: initPacketMagicHeaderTextField headerText: qsTr("H1 - Init packet magic header") textField.text: serverInitPacketMagicHeader - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== serverInitPacketMagicHeader) { serverInitPacketMagicHeader = textField.text } } - - checkEmptyText: true } - TextFieldWithHeaderType { + AwgTextField { id: responsePacketMagicHeaderTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: qsTr("H2 - Response packet magic header") textField.text: serverResponsePacketMagicHeader - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== serverResponsePacketMagicHeader) { serverResponsePacketMagicHeader = textField.text } } - - checkEmptyText: true } - TextFieldWithHeaderType { - id: transportPacketMagicHeaderTextField - Layout.fillWidth: true - Layout.topMargin: 16 - - headerText: qsTr("H4 - Transport packet magic header") - textField.text: serverTransportPacketMagicHeader - textField.validator: IntValidator { bottom: 0 } - - textField.onEditingFinished: { - if (textField.text !== serverTransportPacketMagicHeader) { - serverTransportPacketMagicHeader = textField.text - } - } - - checkEmptyText: true - } - - TextFieldWithHeaderType { + AwgTextField { id: underloadPacketMagicHeaderTextField - Layout.fillWidth: true - Layout.topMargin: 16 - headerText: qsTr("H3 - Underload packet magic header") textField.text: serverUnderloadPacketMagicHeader - textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { if (textField.text !== serverUnderloadPacketMagicHeader) { serverUnderloadPacketMagicHeader = textField.text } } - - checkEmptyText: true } + AwgTextField { + id: transportPacketMagicHeaderTextField + headerText: qsTr("H4 - Transport packet magic header") + textField.text: serverTransportPacketMagicHeader + + textField.onEditingFinished: { + if (textField.text !== serverTransportPacketMagicHeader) { + serverTransportPacketMagicHeader = textField.text + } + } + } + + BasicButtonType { id: saveRestartButton @@ -328,6 +283,8 @@ PageType { responsePacketMagicHeaderTextField.errorText === "" && initPacketMagicHeaderTextField.errorText === "" && responsePacketJunkSizeTextField.errorText === "" && + // cookieReplyHeaderJunkTextField.errorText === "" && + // transportHeaderJunkTextField.errorText === "" && initPacketJunkSizeTextField.errorText === "" && junkPacketMaxSizeTextField.errorText === "" && junkPacketMinSizeTextField.errorText === "" && @@ -360,6 +317,13 @@ PageType { PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)")) return } + // if (AwgConfigModel.isPacketSizeEqual(parseInt(initPacketJunkSizeTextField.textField.text), + // parseInt(responsePacketJunkSizeTextField.textField.text), + // parseInt(cookieReplyPacketJunkSizeTextField.textField.text), + // parseInt(transportPacketJunkSizeTextField.textField.text))) { + // PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92) + S3 + cookie reply size (64) + S4 + transport packet size (32)")) + // return + // } } var headerText = qsTr("Save settings?")