From 46ce22b85cd004835d5ce528a2005eba2337cdae Mon Sep 17 00:00:00 2001 From: vkamn Date: Thu, 18 Dec 2025 22:25:20 +0800 Subject: [PATCH] fix: fixed awg2 container processing (#2067) --- client/containers/containers_defs.cpp | 36 ++---- client/containers/containers_defs.h | 4 +- client/protocols/protocols_defs.cpp | 15 +++ client/protocols/protocols_defs.h | 10 +- .../server_scripts/awg/configure_container.sh | 6 +- .../awg_legacy/configure_container.sh | 5 + .../server_scripts/awg_legacy/template.conf | 5 + client/ui/controllers/exportController.cpp | 17 ++- client/ui/controllers/importController.cpp | 13 ++- client/ui/controllers/installController.cpp | 69 ++++++----- client/ui/models/containers_model.cpp | 30 +++-- client/ui/models/protocols/awgConfigModel.cpp | 85 +++++++++++--- client/ui/models/protocols/awgConfigModel.h | 14 ++- client/ui/models/servers_model.cpp | 42 +++++-- .../ui/qml/Pages2/PageProtocolAwgSettings.qml | 110 ++++++++++++++++++ client/ui/qml/Pages2/PageShare.qml | 2 - 16 files changed, 347 insertions(+), 116 deletions(-) diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index ad63c9395..11be4d5ab 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -30,11 +30,8 @@ QString ContainerProps::containerToString(amnezia::DockerContainer c) return "amnezia-openvpn-cloak"; if (c == DockerContainer::Awg) return "amnezia-awg"; - if (c == DockerContainer::Awg1_5) - return "amnezia-awg1.5"; if (c == DockerContainer::Awg2) return "amnezia-awg2"; - QMetaEnum metaEnum = QMetaEnum::fromType(); QString containerKey = metaEnum.valueToKey(static_cast(c)); @@ -49,11 +46,8 @@ QString ContainerProps::containerTypeToString(amnezia::DockerContainer c) return "ikev2"; if (c == DockerContainer::Awg) return "awg"; - if (c == DockerContainer::Awg1_5) - return "awg1.5"; if (c == DockerContainer::Awg2) - return "awg2"; - + return "awg"; QMetaEnum metaEnum = QMetaEnum::fromType(); QString containerKey = metaEnum.valueToKey(static_cast(c)); @@ -84,7 +78,6 @@ QVector ContainerProps::protocolsForContainer(amnezia::DockerCon case DockerContainer::Socks5Proxy: return { Proto::Socks5Proxy }; case DockerContainer::Awg: return { Proto::Awg }; - case DockerContainer::Awg1_5: return { Proto::Awg }; case DockerContainer::Awg2: return { Proto::Awg }; default: return { defaultProtocol(container) }; } @@ -108,9 +101,8 @@ QMap ContainerProps::containerHumanNames() { DockerContainer::ShadowSocks, "OpenVPN over SS" }, { DockerContainer::Cloak, "OpenVPN over Cloak" }, { DockerContainer::WireGuard, "WireGuard" }, - { DockerContainer::Awg2, "AmneziaWG 2" }, - { DockerContainer::Awg1_5, "AmneziaWG 1.5" }, { DockerContainer::Awg, "AmneziaWG" }, + { DockerContainer::Awg2, "AmneziaWG" }, { DockerContainer::Xray, "XRay" }, { DockerContainer::Ipsec, QObject::tr("IPsec") }, { DockerContainer::SSXray, "Shadowsocks"}, @@ -134,10 +126,9 @@ QMap ContainerProps::containerDescriptions() { DockerContainer::WireGuard, QObject::tr("WireGuard - popular VPN protocol with high performance, high speed and low power " "consumption.") }, - { DockerContainer::Awg2, - QObject::tr("AmneziaWG is a special protocol from Amnezia based on WireGuard. " - "It provides high connection speed and ensures stable operation even in the most challenging network conditions.") }, { DockerContainer::Awg, + QObject::tr("AmneziaWG Legacy is a outdated version of AmneziaWG protocol. To upgrade, install AmneziaWG and recreate users.") }, + { DockerContainer::Awg2, QObject::tr("AmneziaWG is a special protocol from Amnezia based on WireGuard. " "It provides high connection speed and ensures stable operation even in the most challenging network conditions.") }, { DockerContainer::Xray, @@ -214,17 +205,6 @@ QMap ContainerProps::containerDetailedDescriptions() "* Minimal settings required\n" "* Undetectable by traffic analysis systems (DPI)\n" "* Operates over UDP protocol") }, - { DockerContainer::Awg, - QObject::tr("AmneziaWG is an older version of the AmneziaWG protocol based on WireGuard." - "It addresses WireGuard's main vulnerability (easy detection by DPI systems) through advanced obfuscation techniques, " - "making VPN traffic indistinguishable from regular internet traffic.\n" - "\nAmneziaWG is an excellent choice for those seeking a fast, stealthy VPN connection.\n" - "\nFeatures:\n" - "* Available on all AmneziaVPN platforms\n" - "* Low battery consumption on mobile devices\n" - "* Minimal settings required\n" - "* Undetectable by traffic analysis systems (DPI)\n" - "* Operates over UDP protocol") }, { DockerContainer::Xray, QObject::tr("REALITY is an innovative protocol developed by the creators of XRay, designed specifically to combat high levels of internet censorship. " "REALITY identifies censorship systems during the TLS handshake, " @@ -274,7 +254,6 @@ Proto ContainerProps::defaultProtocol(DockerContainer c) case DockerContainer::ShadowSocks: return Proto::ShadowSocks; case DockerContainer::WireGuard: return Proto::WireGuard; case DockerContainer::Awg2: return Proto::Awg; - case DockerContainer::Awg1_5: return Proto::Awg; case DockerContainer::Awg: return Proto::Awg; case DockerContainer::Xray: return Proto::Xray; case DockerContainer::Ipsec: return Proto::Ikev2; @@ -308,7 +287,6 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c) case DockerContainer::WireGuard: return true; case DockerContainer::OpenVpn: return true; case DockerContainer::Awg2: return true; - case DockerContainer::Awg1_5: return true; case DockerContainer::Awg: return true; case DockerContainer::Xray: return true; case DockerContainer::Cloak: return true; @@ -323,7 +301,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c) switch (c) { case DockerContainer::WireGuard: return true; case DockerContainer::Awg2: return true; - case DockerContainer::Awg1_5: return true; + case DockerContainer::Awg: return true; case DockerContainer::Xray: return true; case DockerContainer::SSXray: return true; case DockerContainer::OpenVpn: @@ -346,7 +324,6 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c) case DockerContainer::OpenVpn: return true; case DockerContainer::ShadowSocks: return false; case DockerContainer::Awg2: return true; - case DockerContainer::Awg1_5: return true; case DockerContainer::Awg: return true; case DockerContainer::Cloak: return true; case DockerContainer::Xray: return true; @@ -419,9 +396,10 @@ bool ContainerProps::isShareable(DockerContainer container) bool ContainerProps::isAwgContainer(DockerContainer container) { - return container == DockerContainer::Awg2 || container == DockerContainer::Awg || container == DockerContainer::Awg1_5; + return container == DockerContainer::Awg || container == DockerContainer::Awg2; } + QJsonObject ContainerProps::getProtocolConfigFromContainer(const Proto protocol, const QJsonObject &containerConfig) { QString protocolConfigString = containerConfig.value(ProtocolProps::protoToString(protocol)) diff --git a/client/containers/containers_defs.h b/client/containers/containers_defs.h index cf85205ca..182a402b8 100644 --- a/client/containers/containers_defs.h +++ b/client/containers/containers_defs.h @@ -16,9 +16,8 @@ namespace amnezia Q_NAMESPACE enum DockerContainer { None = 0, - Awg2, - Awg1_5, Awg, + Awg2, WireGuard, OpenVpn, Cloak, @@ -76,6 +75,7 @@ namespace amnezia static bool isAwgContainer(amnezia::DockerContainer container); + static QJsonObject getProtocolConfigFromContainer(const amnezia::Proto protocol, const QJsonObject &containerConfig); static int installPageOrder(amnezia::DockerContainer container); diff --git a/client/protocols/protocols_defs.cpp b/client/protocols/protocols_defs.cpp index ac5bb1ad8..dce8fede4 100644 --- a/client/protocols/protocols_defs.cpp +++ b/client/protocols/protocols_defs.cpp @@ -1,6 +1,7 @@ #include "protocols_defs.h" #include +#include using namespace amnezia; @@ -217,3 +218,17 @@ QString ProtocolProps::key_proto_config_path(Proto p) { return protoToString(p) + "_config_path"; } + +QString ProtocolProps::getProtocolVersion(const QJsonObject &protocolConfig) +{ + return protocolConfig.value(config_key::protocolVersion).toString(); +} + +QString ProtocolProps::getProtocolVersionString(const QJsonObject &protocolConfig) +{ + auto version = getProtocolVersion(protocolConfig); + + if (version == protocols::awg::awgV2) return QObject::tr(" (version 2)"); + if (version == protocols::awg::awgV1_5) return QObject::tr(" (version 1.5)"); + return ""; +} diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 993b5bc3d..869afd92f 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -84,6 +84,8 @@ namespace amnezia constexpr char specialJunk4[] = "I4"; constexpr char specialJunk5[] = "I5"; + constexpr char protocolVersion[] = "protocol_version"; + constexpr char openvpn[] = "openvpn"; constexpr char wireguard[] = "wireguard"; constexpr char shadowsocks[] = "shadowsocks"; @@ -231,11 +233,14 @@ namespace amnezia constexpr char defaultResponsePacketMagicHeader[] = "3288052141"; constexpr char defaultTransportPacketMagicHeader[] = "2528465083"; constexpr char defaultUnderloadPacketMagicHeader[] = "1766607858"; - constexpr char defaultSpecialJunk1[] = ""; + constexpr char defaultSpecialJunk1[] = ""; constexpr char defaultSpecialJunk2[] = ""; constexpr char defaultSpecialJunk3[] = ""; constexpr char defaultSpecialJunk4[] = ""; constexpr char defaultSpecialJunk5[] = ""; + + constexpr char awgV1_5[] = "1.5"; + constexpr char awgV2[] = "2"; } namespace socks5Proxy @@ -318,6 +323,9 @@ namespace amnezia Q_INVOKABLE static QString key_proto_config_data(Proto p); Q_INVOKABLE static QString key_proto_config_path(Proto p); + + static QString getProtocolVersion(const QJsonObject &protocolConfig); + static QString getProtocolVersionString(const QJsonObject &protocolConfig); }; } // namespace amnezia diff --git a/client/server_scripts/awg/configure_container.sh b/client/server_scripts/awg/configure_container.sh index 8e61ab20b..e3981bff7 100644 --- a/client/server_scripts/awg/configure_container.sh +++ b/client/server_scripts/awg/configure_container.sh @@ -25,5 +25,9 @@ H1 = $INIT_PACKET_MAGIC_HEADER H2 = $RESPONSE_PACKET_MAGIC_HEADER H3 = $UNDERLOAD_PACKET_MAGIC_HEADER H4 = $TRANSPORT_PACKET_MAGIC_HEADER - +# I1 = $SPECIAL_JUNK_1 +# I2 = $SPECIAL_JUNK_2 +# I3 = $SPECIAL_JUNK_3 +# I4 = $SPECIAL_JUNK_4 +# I5 = $SPECIAL_JUNK_5 EOF diff --git a/client/server_scripts/awg_legacy/configure_container.sh b/client/server_scripts/awg_legacy/configure_container.sh index 2000c9656..7059f6c0d 100644 --- a/client/server_scripts/awg_legacy/configure_container.sh +++ b/client/server_scripts/awg_legacy/configure_container.sh @@ -23,4 +23,9 @@ H1 = $INIT_PACKET_MAGIC_HEADER H2 = $RESPONSE_PACKET_MAGIC_HEADER H3 = $UNDERLOAD_PACKET_MAGIC_HEADER H4 = $TRANSPORT_PACKET_MAGIC_HEADER +# I1 = $SPECIAL_JUNK_1 +# I2 = $SPECIAL_JUNK_2 +# I3 = $SPECIAL_JUNK_3 +# I4 = $SPECIAL_JUNK_4 +# I5 = $SPECIAL_JUNK_5 EOF diff --git a/client/server_scripts/awg_legacy/template.conf b/client/server_scripts/awg_legacy/template.conf index 79932806b..323554f27 100644 --- a/client/server_scripts/awg_legacy/template.conf +++ b/client/server_scripts/awg_legacy/template.conf @@ -11,6 +11,11 @@ H1 = $INIT_PACKET_MAGIC_HEADER H2 = $RESPONSE_PACKET_MAGIC_HEADER H3 = $UNDERLOAD_PACKET_MAGIC_HEADER H4 = $TRANSPORT_PACKET_MAGIC_HEADER +I1 = $SPECIAL_JUNK_1 +I2 = $SPECIAL_JUNK_2 +I3 = $SPECIAL_JUNK_3 +I4 = $SPECIAL_JUNK_4 +I5 = $SPECIAL_JUNK_5 [Peer] PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY diff --git a/client/ui/controllers/exportController.cpp b/client/ui/controllers/exportController.cpp index d11c6a50a..993ff7c78 100644 --- a/client/ui/controllers/exportController.cpp +++ b/client/ui/controllers/exportController.cpp @@ -179,7 +179,8 @@ void ExportController::generateWireGuardConfig(const QString &clientName) void ExportController::generateAwgConfig(const QString &clientName) { QJsonObject nativeConfig; - ErrorCode errorCode = generateNativeConfig(DockerContainer::Awg2, clientName, Proto::Awg, nativeConfig); + ErrorCode errorCode = generateNativeConfig(static_cast(m_containersModel->getProcessedContainerIndex()), clientName, + Proto::Awg, nativeConfig); if (errorCode) { emit exportErrorOccurred(errorCode); return; @@ -252,7 +253,7 @@ void ExportController::generateCloakConfig() void ExportController::generateXrayConfig(const QString &clientName) { - //Xray data + // Xray data QJsonObject nativeConfig; ErrorCode errorCode = generateNativeConfig(DockerContainer::Xray, clientName, Proto::Xray, nativeConfig); if (errorCode) { @@ -262,13 +263,13 @@ void ExportController::generateXrayConfig(const QString &clientName) QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n"); for (const QString &line : std::as_const(lines)) { - m_config.append(line+ "\n"); + m_config.append(line + "\n"); } - //Xray data + // Xray data // Parse the Xray data to extract VLESS parameters and generate string QString configString = QString(QJsonDocument(nativeConfig).toJson(QJsonDocument::Compact)); - + QJsonDocument doc = QJsonDocument::fromJson(configString.toUtf8()); if (doc.isNull() || !doc.isObject()) { qDebug() << "ERROR: Failed to parse config JSON"; @@ -278,7 +279,7 @@ void ExportController::generateXrayConfig(const QString &clientName) QJsonObject xrayConfig = doc.object(); QJsonArray outbounds = xrayConfig.value("outbounds").toArray(); - + if (outbounds.isEmpty()) { qDebug() << "ERROR: Outbounds array is empty"; emit exportErrorOccurred(ErrorCode::InternalError); @@ -316,7 +317,6 @@ void ExportController::generateXrayConfig(const QString &clientName) vlessServer.network = streamSettings.value("network").toString("tcp"); vlessServer.security = streamSettings.value("security").toString("reality"); - if (vlessServer.security == "reality") { QJsonObject realitySettings = streamSettings.value("realitySettings").toObject(); vlessServer.serverName = realitySettings.value("serverName").toString(); @@ -328,7 +328,6 @@ void ExportController::generateXrayConfig(const QString &clientName) m_nativeConfigString = amnezia::serialization::vless::Serialize(vlessServer, "AmneziaVPN"); - emit exportConfigChanged(); } @@ -365,7 +364,7 @@ void ExportController::revokeConfig(const int row, const DockerContainer contain { QSharedPointer serverController(new ServerController(m_settings)); ErrorCode errorCode = - m_clientManagementModel->revokeClient(row, container, credentials, m_serversModel->getProcessedServerIndex(), serverController); + m_clientManagementModel->revokeClient(row, container, credentials, m_serversModel->getProcessedServerIndex(), serverController); if (errorCode != ErrorCode::NoError) { emit exportErrorOccurred(errorCode); } diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index 8e40435f2..2a1332e20 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -448,6 +448,7 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data) lastConfig[config_key::allowed_ips] = allowedIpsJsonArray; QString protocolName = "wireguard"; + QString protocolVersion; const QStringList requiredJunkFields = { config_key::junkPacketCount, config_key::junkPacketMinSize, config_key::junkPacketMaxSize, config_key::initPacketJunkSize, @@ -483,19 +484,18 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data) !configMap.value(config_key::specialJunk5).isEmpty(); if (hasCookieReplyPacketJunkSize && hasTransportPacketJunkSize) { - protocolName = "awg2"; + protocolVersion = "2"; } else if (hasSpecialJunk && !hasCookieReplyPacketJunkSize && !hasTransportPacketJunkSize) { - protocolName = "awg1.5"; - } else { - protocolName = "awg"; + protocolVersion = "1.5"; } + protocolName = "awg"; m_configType = ConfigTypes::Awg; } if (!configMap.value("MTU").isEmpty()) { lastConfig[config_key::mtu] = configMap.value("MTU"); } else { - lastConfig[config_key::mtu] = (protocolName == "awg" || protocolName == "awg2" || protocolName == "awg1.5") + lastConfig[config_key::mtu] = (protocolName == "awg") ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu; } @@ -505,6 +505,9 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data) wireguardConfig[config_key::isThirdPartyConfig] = true; wireguardConfig[config_key::port] = port; wireguardConfig[config_key::transport_proto] = "udp"; + if (protocolName == "awg" && !protocolVersion.isEmpty()) { + wireguardConfig[config_key::protocolVersion] = protocolVersion; + } QJsonObject containers; containers.insert(config_key::container, QJsonValue("amnezia-" + protocolName)); diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp index b6574bda7..f181c5ae3 100644 --- a/client/ui/controllers/installController.cpp +++ b/client/ui/controllers/installController.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -71,8 +72,11 @@ void InstallController::install(DockerContainer container, int port, TransportPr if (protocol == mainProto) { containerConfig.insert(config_key::port, QString::number(port)); containerConfig.insert(config_key::transport_proto, ProtocolProps::transportProtoToString(transportProto, protocol)); + containerConfig.insert(config_key::subnet_address, protocols::wireguard::defaultSubnetAddress); if (container == DockerContainer::Awg2) { + containerConfig[config_key::protocolVersion] = "2"; + QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(4, 7)); QString junkPacketMinSize = QString::number(10); QString junkPacketMaxSize = QString::number(50); @@ -91,8 +95,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr } usedValues.insert(s2); - while (usedValues.contains(s3) - || s1 + AwgConstant::messageInitiationSize == s3 + AwgConstant::messageCookieReplySize + while (usedValues.contains(s3) || s1 + AwgConstant::messageInitiationSize == s3 + AwgConstant::messageCookieReplySize || s2 + AwgConstant::messageResponseSize == s3 + AwgConstant::messageCookieReplySize) { s3 = QRandomGenerator::global()->bounded(0, 64); } @@ -107,18 +110,21 @@ void InstallController::install(DockerContainer container, int port, TransportPr QString cookieReplyPacketJunkSize = QString::number(s3); QString transportPacketJunkSize = QString::number(s4); - QSet headersValue; + QVector> headersValue; + int min = 5; + auto max = (std::numeric_limits::max)(); while (headersValue.size() != 4) { - auto max = (std::numeric_limits::max)(); - headersValue.insert(QString::number(QRandomGenerator::global()->bounded(5, max))); + auto first = QRandomGenerator::global()->bounded(min, max); + auto second = QRandomGenerator::global()->bounded(first, max); + min = second; + + headersValue.push_back(QPair(QString::number(first), QString::number(second))); } - auto headersValueList = headersValue.values(); - - QString initPacketMagicHeader = headersValueList.at(0); - QString responsePacketMagicHeader = headersValueList.at(1); - QString underloadPacketMagicHeader = headersValueList.at(2); - QString transportPacketMagicHeader = headersValueList.at(3); + QString initPacketMagicHeader = headersValue.at(0).first + "-" + headersValue.at(0).second; + QString responsePacketMagicHeader = headersValue.at(1).first + "-" + headersValue.at(1).second; + QString underloadPacketMagicHeader = headersValue.at(2).first + "-" + headersValue.at(2).second; + QString transportPacketMagicHeader = headersValue.at(3).first + "-" + headersValue.at(3).second; containerConfig[config_key::junkPacketCount] = junkPacketCount; containerConfig[config_key::junkPacketMinSize] = junkPacketMinSize; @@ -133,11 +139,11 @@ void InstallController::install(DockerContainer container, int port, TransportPr containerConfig[config_key::cookieReplyPacketJunkSize] = cookieReplyPacketJunkSize; containerConfig[config_key::transportPacketJunkSize] = transportPacketJunkSize; - containerConfig[config_key::specialJunk1] = ""; - containerConfig[config_key::specialJunk2] = ""; - containerConfig[config_key::specialJunk3] = ""; - containerConfig[config_key::specialJunk4] = ""; - containerConfig[config_key::specialJunk5] = ""; + containerConfig[config_key::specialJunk1] = protocols::awg::defaultSpecialJunk1; + containerConfig[config_key::specialJunk2] = protocols::awg::defaultSpecialJunk2; + containerConfig[config_key::specialJunk3] = protocols::awg::defaultSpecialJunk3; + containerConfig[config_key::specialJunk4] = protocols::awg::defaultSpecialJunk4; + containerConfig[config_key::specialJunk5] = protocols::awg::defaultSpecialJunk5; } else if (container == DockerContainer::Sftp) { containerConfig.insert(config_key::userName, protocols::sftp::defaultUserName); @@ -395,10 +401,10 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia QJsonObject config; Proto mainProto = ContainerProps::defaultProtocol(container); const auto &protocols = ContainerProps::protocolsForContainer(container); - + for (const auto &protocol : protocols) { QJsonObject containerConfig; - + // for Multiprotocols (OpenVPN over SS, OpenVPN over Cloak) bool shouldProcessProtocol = false; if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { @@ -406,7 +412,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia } else { shouldProcessProtocol = (protocol == mainProto); } - + if (shouldProcessProtocol) { containerConfig.insert(config_key::port, port); containerConfig.insert(config_key::transport_proto, transportProto); @@ -416,8 +422,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia if (container == DockerContainer::Awg) { configPath = amnezia::protocols::awg::serverLegacyConfigPath; } - QString serverConfig = serverController->getTextFileFromContainer(container, credentials, - configPath, errorCode); + QString serverConfig = serverController->getTextFileFromContainer(container, credentials, configPath, errorCode); QMap serverConfigMap; auto serverConfigLines = serverConfig.split("\n"); @@ -447,10 +452,10 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia serverConfigMap.value(config_key::transportPacketMagicHeader); if (container == DockerContainer::Awg2) { + containerConfig[config_key::protocolVersion] = "2"; containerConfig[config_key::cookieReplyPacketJunkSize] = serverConfigMap.value(config_key::cookieReplyPacketJunkSize); - containerConfig[config_key::transportPacketJunkSize] = - serverConfigMap.value(config_key::transportPacketJunkSize); + containerConfig[config_key::transportPacketJunkSize] = serverConfigMap.value(config_key::transportPacketJunkSize); } } else if (protocol == Proto::WireGuard) { @@ -586,7 +591,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia containerConfig[config_key::tls_auth] = tlsAuth; bool blockOutsideDns = serverConfig.contains("block-outside-dns"); - + containerConfig[config_key::block_outside_dns] = blockOutsideDns; QString cipher = serverConfigMap.value("cipher"); @@ -603,10 +608,10 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia "/opt/amnezia/cloak/ck-config.json", errorCode); QJsonDocument doc = QJsonDocument::fromJson(cloakConfig.toUtf8()); - + if (!doc.isNull() && doc.isObject()) { QJsonObject cloakConfigObj = doc.object(); - + QString site = cloakConfigObj.value("RedirAddr").toString(); if (!site.isEmpty()) { containerConfig[config_key::site] = site; @@ -614,13 +619,13 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia } else { qDebug() << "Failed to parse main loop Cloak JSON config"; } - + } else if (protocol == Proto::ShadowSocks) { - QString shadowsocksConfig = serverController->getTextFileFromContainer(container, credentials, - "/opt/amnezia/shadowsocks/ss-config.json", errorCode); + QString shadowsocksConfig = serverController->getTextFileFromContainer( + container, credentials, "/opt/amnezia/shadowsocks/ss-config.json", errorCode); QJsonDocument doc = QJsonDocument::fromJson(shadowsocksConfig.toUtf8()); - + if (!doc.isNull() && doc.isObject()) { QJsonObject ssConfigObj = doc.object(); QString cipher = ssConfigObj.value("method").toString(); @@ -1059,8 +1064,8 @@ bool InstallController::isUpdateDockerContainerRequired(const DockerContainer co const QJsonObject &newProtoConfig = newConfig.value(ProtocolProps::protoToString(mainProto)).toObject(); if (container == DockerContainer::Awg2) { - const AwgConfig oldConfig(oldProtoConfig, container); - const AwgConfig newConfig(newProtoConfig, container); + const AwgConfig oldConfig(oldProtoConfig); + const AwgConfig newConfig(newProtoConfig); if (oldConfig.hasEqualServerSettings(newConfig)) { return false; diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 1e1c86a85..69943544a 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -2,8 +2,7 @@ #include -ContainersModel::ContainersModel(QObject *parent) - : QAbstractListModel(parent) +ContainersModel::ContainersModel(QObject *parent) : QAbstractListModel(parent) { } @@ -20,10 +19,23 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const } DockerContainer container = ContainerProps::allContainers().at(index.row()); + QString protocolKey = ContainerProps::containerTypeToProtocolString(container); + auto isThirdPartyConfig = m_containers.value(container).value(protocolKey).toObject().value(config_key::isThirdPartyConfig).toBool(); switch (role) { - case NameRole: return ContainerProps::containerHumanNames().value(container); - case DescriptionRole: return ContainerProps::containerDescriptions().value(container); + case NameRole: { + if (container == DockerContainer::Awg && !isThirdPartyConfig) { + return "AmneziaWG Legacy"; + } + return ContainerProps::containerHumanNames().value(container); + } + case DescriptionRole: { + if (container == DockerContainer::Awg && !isThirdPartyConfig) { + return QObject::tr("AmneziaWG Legacy is a outdated version of AmneziaWG protocol. To upgrade, install AmneziaWG and recreate users."); + } + + return ContainerProps::containerDescriptions().value(container); + } case DetailedDescriptionRole: return ContainerProps::containerDetailedDescriptions().value(container); case ConfigRole: { if (container == DockerContainer::None) { @@ -31,10 +43,7 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const } return m_containers.value(container); } - case IsThirdPartyConfigRole: { - QString protocolKey = ContainerProps::containerTypeToProtocolString(container); - return m_containers.value(container).value(protocolKey).toObject().value(config_key::isThirdPartyConfig).toBool(); - } + case IsThirdPartyConfigRole: return isThirdPartyConfig; case ServiceTypeRole: return ContainerProps::containerService(container); case DockerContainerRole: return container; case IsEasySetupContainerRole: return ContainerProps::isEasySetupContainer(container); @@ -63,8 +72,7 @@ void ContainersModel::updateModel(const QJsonArray &containers) beginResetModel(); m_containers.clear(); for (const QJsonValue &val : containers) { - m_containers.insert(ContainerProps::containerFromString(val.toObject().value(config_key::container).toString()), - val.toObject()); + m_containers.insert(ContainerProps::containerFromString(val.toObject().value(config_key::container).toString()), val.toObject()); } endResetModel(); } @@ -121,7 +129,7 @@ bool ContainersModel::hasInstalledProtocols() bool ContainersModel::isInstallationAllowed(DockerContainer container) { - return container != DockerContainer::Awg && container != DockerContainer::Awg1_5; + return container != DockerContainer::Awg; } QHash ContainersModel::roleNames() const diff --git a/client/ui/models/protocols/awgConfigModel.cpp b/client/ui/models/protocols/awgConfigModel.cpp index 84a7fd21d..ff535490f 100644 --- a/client/ui/models/protocols/awgConfigModel.cpp +++ b/client/ui/models/protocols/awgConfigModel.cpp @@ -56,6 +56,11 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in case Roles::ServerTransportPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::transportPacketMagicHeader, value.toString()); break; + case Roles::ServerSpecialJunk1Role: m_serverProtocolConfig.insert(config_key::specialJunk1, value.toString()); break; + case Roles::ServerSpecialJunk2Role: m_serverProtocolConfig.insert(config_key::specialJunk2, value.toString()); break; + case Roles::ServerSpecialJunk3Role: m_serverProtocolConfig.insert(config_key::specialJunk3, value.toString()); break; + case Roles::ServerSpecialJunk4Role: m_serverProtocolConfig.insert(config_key::specialJunk4, value.toString()); break; + case Roles::ServerSpecialJunk5Role: m_serverProtocolConfig.insert(config_key::specialJunk5, value.toString()); break; } emit dataChanged(index, index, QList { role }); @@ -93,8 +98,13 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const 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); + case Roles::ServerSpecialJunk1Role: return m_serverProtocolConfig.value(config_key::specialJunk1); + case Roles::ServerSpecialJunk2Role: return m_serverProtocolConfig.value(config_key::specialJunk2); + case Roles::ServerSpecialJunk3Role: return m_serverProtocolConfig.value(config_key::specialJunk3); + case Roles::ServerSpecialJunk4Role: return m_serverProtocolConfig.value(config_key::specialJunk4); + case Roles::ServerSpecialJunk5Role: return m_serverProtocolConfig.value(config_key::specialJunk5); - case Roles::IsAwg2Role: return m_container == DockerContainer::Awg2; + case Roles::IsAwg2Role: return ProtocolProps::getProtocolVersion(m_fullConfig.value(config_key::awg).toObject()) == protocols::awg::awgV2; } return QVariant(); @@ -109,6 +119,11 @@ void AwgConfigModel::updateModel(const QJsonObject &config) QJsonObject serverProtocolConfig = config.value(config_key::awg).toObject(); + auto protocolVersion = serverProtocolConfig.value(config_key::protocolVersion).toString(); + if (!protocolVersion.isEmpty()) { + m_serverProtocolConfig[config_key::protocolVersion] = protocolVersion; + } + auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg); m_serverProtocolConfig.insert(config_key::transport_proto, serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); @@ -139,6 +154,17 @@ void AwgConfigModel::updateModel(const QJsonObject &config) m_serverProtocolConfig[config_key::transportPacketMagicHeader] = serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); + m_serverProtocolConfig[config_key::specialJunk1] = + serverProtocolConfig.value(config_key::specialJunk1).toString(); + m_serverProtocolConfig[config_key::specialJunk2] = + serverProtocolConfig.value(config_key::specialJunk2).toString(); + m_serverProtocolConfig[config_key::specialJunk3] = + serverProtocolConfig.value(config_key::specialJunk3).toString(); + m_serverProtocolConfig[config_key::specialJunk4] = + serverProtocolConfig.value(config_key::specialJunk4).toString(); + m_serverProtocolConfig[config_key::specialJunk5] = + serverProtocolConfig.value(config_key::specialJunk5).toString(); + 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); @@ -149,22 +175,22 @@ void AwgConfigModel::updateModel(const QJsonObject &config) 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); + clientProtocolConfig.value(config_key::specialJunk1).toString(); m_clientProtocolConfig[config_key::specialJunk2] = - clientProtocolConfig.value(config_key::specialJunk2).toString(protocols::awg::defaultSpecialJunk2); + clientProtocolConfig.value(config_key::specialJunk2).toString(); m_clientProtocolConfig[config_key::specialJunk3] = - clientProtocolConfig.value(config_key::specialJunk3).toString(protocols::awg::defaultSpecialJunk3); + clientProtocolConfig.value(config_key::specialJunk3).toString(); m_clientProtocolConfig[config_key::specialJunk4] = - clientProtocolConfig.value(config_key::specialJunk4).toString(protocols::awg::defaultSpecialJunk4); + clientProtocolConfig.value(config_key::specialJunk4).toString(); m_clientProtocolConfig[config_key::specialJunk5] = - clientProtocolConfig.value(config_key::specialJunk5).toString(protocols::awg::defaultSpecialJunk5); + clientProtocolConfig.value(config_key::specialJunk5).toString(); endResetModel(); } QJsonObject AwgConfigModel::getConfig() { - const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject(), m_container); - const AwgConfig newConfig(m_serverProtocolConfig, m_container); + const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); + const AwgConfig newConfig(m_serverProtocolConfig); if (!oldConfig.hasEqualServerSettings(newConfig)) { m_serverProtocolConfig.remove(config_key::last_config); @@ -184,6 +210,22 @@ QJsonObject AwgConfigModel::getConfig() m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); } + QString currentProtocolVersion = m_serverProtocolConfig.value(config_key::protocolVersion).toString(); + + if (currentProtocolVersion != protocols::awg::awgV2) { + bool hasSpecialJunk = !m_serverProtocolConfig.value(config_key::specialJunk1).toString().trimmed().isEmpty() || + !m_serverProtocolConfig.value(config_key::specialJunk2).toString().trimmed().isEmpty() || + !m_serverProtocolConfig.value(config_key::specialJunk3).toString().trimmed().isEmpty() || + !m_serverProtocolConfig.value(config_key::specialJunk4).toString().trimmed().isEmpty() || + !m_serverProtocolConfig.value(config_key::specialJunk5).toString().trimmed().isEmpty(); + + if (hasSpecialJunk) { + m_serverProtocolConfig[config_key::protocolVersion] = protocols::awg::awgV1_5; + } else { + m_serverProtocolConfig.remove(config_key::protocolVersion); + } + } + m_fullConfig.insert(config_key::awg, m_serverProtocolConfig); return m_fullConfig; } @@ -206,8 +248,8 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2, const int s3, bool AwgConfigModel::isServerSettingsEqual() { - const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject(), m_container); - const AwgConfig newConfig(m_serverProtocolConfig, m_container); + const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); + const AwgConfig newConfig(m_serverProtocolConfig); return oldConfig.hasEqualServerSettings(newConfig); } @@ -241,15 +283,20 @@ QHash AwgConfigModel::roleNames() const roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader"; roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader"; roles[ServerTransportPacketMagicHeaderRole] = "serverTransportPacketMagicHeader"; + roles[ServerSpecialJunk1Role] = "serverSpecialJunk1"; + roles[ServerSpecialJunk2Role] = "serverSpecialJunk2"; + roles[ServerSpecialJunk3Role] = "serverSpecialJunk3"; + roles[ServerSpecialJunk4Role] = "serverSpecialJunk4"; + roles[ServerSpecialJunk5Role] = "serverSpecialJunk5"; roles[IsAwg2Role] = "isAwg2"; return roles; } -AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig, const DockerContainer containerType) +AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig) { - m_containerType = containerType; + m_isProtocolV2 = ProtocolProps::getProtocolVersion(serverProtocolConfig) == protocols::awg::awgV2; auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString(); QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); @@ -272,7 +319,7 @@ AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig, const DockerContai serverResponsePacketJunkSize = serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); - if (m_containerType == DockerContainer::Awg2) { + if (m_isProtocolV2) { serverCookieReplyPacketJunkSize = serverProtocolConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize); serverTransportPacketJunkSize = @@ -287,6 +334,11 @@ AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig, const DockerContai serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader); serverTransportPacketMagicHeader = serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); + serverSpecialJunk1 = serverProtocolConfig.value(config_key::specialJunk1).toString(protocols::awg::defaultSpecialJunk1); + serverSpecialJunk2 = serverProtocolConfig.value(config_key::specialJunk2).toString(protocols::awg::defaultSpecialJunk2); + serverSpecialJunk3 = serverProtocolConfig.value(config_key::specialJunk3).toString(protocols::awg::defaultSpecialJunk3); + serverSpecialJunk4 = serverProtocolConfig.value(config_key::specialJunk4).toString(protocols::awg::defaultSpecialJunk4); + serverSpecialJunk5 = serverProtocolConfig.value(config_key::specialJunk5).toString(protocols::awg::defaultSpecialJunk5); } bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const @@ -297,11 +349,14 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const || serverInitPacketMagicHeader != other.serverInitPacketMagicHeader || serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader || serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader - || serverTransportPacketMagicHeader != other.serverTransportPacketMagicHeader) { + || serverTransportPacketMagicHeader != other.serverTransportPacketMagicHeader + || serverSpecialJunk1 != other.serverSpecialJunk1 || serverSpecialJunk2 != other.serverSpecialJunk2 + || serverSpecialJunk3 != other.serverSpecialJunk3 || serverSpecialJunk4 != other.serverSpecialJunk4 + || serverSpecialJunk5 != other.serverSpecialJunk5) { return false; } - if (m_containerType == DockerContainer::Awg2) { + if (m_isProtocolV2) { if (serverCookieReplyPacketJunkSize != other.serverCookieReplyPacketJunkSize || serverTransportPacketJunkSize != other.serverTransportPacketJunkSize) { return false; diff --git a/client/ui/models/protocols/awgConfigModel.h b/client/ui/models/protocols/awgConfigModel.h index 62f874c56..f10704fb0 100644 --- a/client/ui/models/protocols/awgConfigModel.h +++ b/client/ui/models/protocols/awgConfigModel.h @@ -16,7 +16,7 @@ namespace AwgConstant struct AwgConfig { - AwgConfig(const QJsonObject &jsonConfig, const DockerContainer containerType); + AwgConfig(const QJsonObject &serverProtocolConfig); QString subnetAddress; QString port; @@ -42,12 +42,17 @@ struct AwgConfig QString serverResponsePacketMagicHeader; QString serverUnderloadPacketMagicHeader; QString serverTransportPacketMagicHeader; + QString serverSpecialJunk1; + QString serverSpecialJunk2; + QString serverSpecialJunk3; + QString serverSpecialJunk4; + QString serverSpecialJunk5; bool hasEqualServerSettings(const AwgConfig &other) const; bool hasEqualClientSettings(const AwgConfig &other) const; private: - DockerContainer m_containerType; + bool m_isProtocolV2; }; class AwgConfigModel : public QAbstractListModel @@ -81,6 +86,11 @@ public: ServerResponsePacketMagicHeaderRole, ServerUnderloadPacketMagicHeaderRole, ServerTransportPacketMagicHeaderRole, + ServerSpecialJunk1Role, + ServerSpecialJunk2Role, + ServerSpecialJunk3Role, + ServerSpecialJunk4Role, + ServerSpecialJunk5Role, IsAwg2Role }; diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 0b3fcad09..62aeb4722 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -158,7 +158,7 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const QString primaryDns = server.value(config_key::dns1).toString(); return primaryDns == protocols::dns::amneziaDnsIp; } - case IsAdVisibleRole:{ + case IsAdVisibleRole: { return apiConfig.value(apiDefs::key::serviceInfo).toObject().value(apiDefs::key::isAdVisible).toBool(false); } case AdHeaderRole: { @@ -234,16 +234,29 @@ QString ServersModel::getServerDescription(const QJsonObject &server, const int const QString ServersModel::getDefaultServerDescriptionCollapsed() { - const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); - const auto configVersion = server.value(config_key::configVersion).toInt(); - auto description = getServerDescription(server, m_defaultServerIndex); + const QJsonObject serverConfig = m_servers.at(m_defaultServerIndex).toObject(); + const auto configVersion = serverConfig.value(config_key::configVersion).toInt(); + auto description = getServerDescription(serverConfig, m_defaultServerIndex); if (configVersion) { return description; } - auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + auto container = ContainerProps::containerFromString(serverConfig.value(config_key::defaultContainer).toString()); + QString protocolVersion; + QString containerName = ContainerProps::containerHumanNames().value(container); - return description += ContainerProps::containerHumanNames().value(container) + " | " + server.value(config_key::hostName).toString(); + if (ContainerProps::isAwgContainer(container)) { + QJsonObject containerConfig = m_settings->containerConfig(m_defaultServerIndex, container); + QJsonObject serverProtocolConfig = containerConfig.value(ContainerProps::containerTypeToProtocolString(container)).toObject(); + protocolVersion = ProtocolProps::getProtocolVersionString(serverProtocolConfig); + + auto isThirdPartyConfig = serverProtocolConfig.value(config_key::isThirdPartyConfig).toBool(); + if (container == DockerContainer::Awg && !isThirdPartyConfig) { + containerName = "AmneziaWG Legacy"; + } + } + + return description += containerName + protocolVersion + " | " + serverConfig.value(config_key::hostName).toString(); } const QString ServersModel::getDefaultServerDescriptionExpanded() @@ -522,7 +535,22 @@ void ServersModel::setDefaultContainer(const int serverIndex, const int containe const QString ServersModel::getDefaultServerDefaultContainerName() { auto defaultContainer = qvariant_cast(getDefaultServerData("defaultContainer")); - return ContainerProps::containerHumanNames().value(defaultContainer); + + QString protocolVersion; + QString containerName = ContainerProps::containerHumanNames().value(defaultContainer); + + if (ContainerProps::isAwgContainer(defaultContainer)) { + QJsonObject containerConfig = m_settings->containerConfig(m_defaultServerIndex, defaultContainer); + QJsonObject serverProtocolConfig = containerConfig.value(ContainerProps::containerTypeToProtocolString(defaultContainer)).toObject(); + protocolVersion = ProtocolProps::getProtocolVersionString(serverProtocolConfig); + + auto isThirdPartyConfig = serverProtocolConfig.value(config_key::isThirdPartyConfig).toBool(); + if (defaultContainer == DockerContainer::Awg && !isThirdPartyConfig) { + containerName = "AmneziaWG Legacy"; + } + } + + return containerName + protocolVersion; } ErrorCode ServersModel::removeAllContainers(const QSharedPointer &serverController) diff --git a/client/ui/qml/Pages2/PageProtocolAwgSettings.qml b/client/ui/qml/Pages2/PageProtocolAwgSettings.qml index c37651aa8..9dd559647 100644 --- a/client/ui/qml/Pages2/PageProtocolAwgSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolAwgSettings.qml @@ -382,6 +382,116 @@ PageType { } } + AwgTextField { + id: specialJunk1TextField + + Layout.leftMargin: 16 + Layout.rightMargin: 16 + + headerText: qsTr("I1 - Special junk 1") + textField.text: serverSpecialJunk1 + + textField.onEditingFinished: { + if (textField.text !== serverSpecialJunk1) { + serverSpecialJunk1 = textField.text + } + } + + textField.onActiveFocusChanged: { + if (textField.activeFocus) { + smartScroll.scrollToItem(specialJunk1TextField) + } + } + } + + AwgTextField { + id: specialJunk2TextField + + Layout.leftMargin: 16 + Layout.rightMargin: 16 + + headerText: qsTr("I2 - Special junk 2") + textField.text: serverSpecialJunk2 + + textField.onEditingFinished: { + if (textField.text !== serverSpecialJunk2) { + serverSpecialJunk2 = textField.text + } + } + + textField.onActiveFocusChanged: { + if (textField.activeFocus) { + smartScroll.scrollToItem(specialJunk2TextField) + } + } + } + + AwgTextField { + id: specialJunk3TextField + + Layout.leftMargin: 16 + Layout.rightMargin: 16 + + headerText: qsTr("I3 - Special junk 3") + textField.text: serverSpecialJunk3 + + textField.onEditingFinished: { + if (textField.text !== serverSpecialJunk3) { + serverSpecialJunk3 = textField.text + } + } + + textField.onActiveFocusChanged: { + if (textField.activeFocus) { + smartScroll.scrollToItem(specialJunk3TextField) + } + } + } + + AwgTextField { + id: specialJunk4TextField + + Layout.leftMargin: 16 + Layout.rightMargin: 16 + + headerText: qsTr("I4 - Special junk 4") + textField.text: serverSpecialJunk4 + + textField.onEditingFinished: { + if (textField.text !== serverSpecialJunk4) { + serverSpecialJunk4 = textField.text + } + } + + textField.onActiveFocusChanged: { + if (textField.activeFocus) { + smartScroll.scrollToItem(specialJunk4TextField) + } + } + } + + AwgTextField { + id: specialJunk5TextField + + Layout.leftMargin: 16 + Layout.rightMargin: 16 + + headerText: qsTr("I5 - Special junk 5") + textField.text: serverSpecialJunk5 + + textField.onEditingFinished: { + if (textField.text !== serverSpecialJunk5) { + serverSpecialJunk5 = textField.text + } + } + + textField.onActiveFocusChanged: { + if (textField.activeFocus) { + smartScroll.scrollToItem(specialJunk5TextField) + } + } + } + BasicButtonType { id: saveRestartButton diff --git a/client/ui/qml/Pages2/PageShare.qml b/client/ui/qml/Pages2/PageShare.qml index b3e69dfb2..4b36c93f0 100644 --- a/client/ui/qml/Pages2/PageShare.qml +++ b/client/ui/qml/Pages2/PageShare.qml @@ -461,8 +461,6 @@ PageType { root.connectionTypesModel.push(awgConnectionFormat) } else if (index === ContainerProps.containerFromString("amnezia-awg2")) { root.connectionTypesModel.push(awgConnectionFormat) - } else if (index === ContainerProps.containerFromString("amnezia-awg1.5")) { - root.connectionTypesModel.push(awgConnectionFormat) } else if (index === ContainerProps.containerFromString("amnezia-shadowsocks")) { root.connectionTypesModel.push(openVpnConnectionFormat) root.connectionTypesModel.push(shadowSocksConnectionFormat)