fix: fixed awg2 container processing (#2067)

This commit is contained in:
vkamn
2025-12-18 22:25:20 +08:00
committed by GitHub
parent 36edafb985
commit 46ce22b85c
16 changed files with 347 additions and 116 deletions

View File

@@ -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<DockerContainer>();
QString containerKey = metaEnum.valueToKey(static_cast<int>(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<DockerContainer>();
QString containerKey = metaEnum.valueToKey(static_cast<int>(c));
@@ -84,7 +78,6 @@ QVector<amnezia::Proto> 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<DockerContainer, QString> 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<DockerContainer, QString> 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<DockerContainer, QString> 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))

View File

@@ -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);

View File

@@ -1,6 +1,7 @@
#include "protocols_defs.h"
#include <QRandomGenerator>
#include <QJsonObject>
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 "";
}

View File

@@ -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[] = "<b 0x084481800001000300000000077469636b65747306776964676574096b696e6f706f69736b0272750000010001c00c0005000100000039001806776964676574077469636b6574730679616e646578c025c0390005000100000039002b1765787465726e616c2d7469636b6574732d776964676574066166697368610679616e646578036e657400c05d000100010000001c000457fafe25>";
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<DockerContainer>(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> 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);
}

View File

@@ -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));

View File

@@ -4,6 +4,7 @@
#include <QDir>
#include <QEventLoop>
#include <QJsonObject>
#include <QPair>
#include <QRandomGenerator>
#include <QStandardPaths>
#include <QtConcurrent>
@@ -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<QString> headersValue;
QVector<QPair<QString, QString>> headersValue;
int min = 5;
auto max = (std::numeric_limits<qint32>::max)();
while (headersValue.size() != 4) {
auto max = (std::numeric_limits<qint32>::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, QString>(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<QString, QString> 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;

View File

@@ -2,8 +2,7 @@
#include <QJsonArray>
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<int, QByteArray> ContainersModel::roleNames() const

View File

@@ -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<int, QByteArray> 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;

View File

@@ -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
};

View File

@@ -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<DockerContainer>(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> &serverController)

View File

@@ -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

View File

@@ -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)