diff --git a/client/daemon/daemon.cpp b/client/daemon/daemon.cpp index b0e47817..9e5be582 100644 --- a/client/daemon/daemon.cpp +++ b/client/daemon/daemon.cpp @@ -373,19 +373,31 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) { return false; } - if (!obj.value("Jc").isNull() && !obj.value("Jmin").isNull() - && !obj.value("Jmax").isNull() && !obj.value("S1").isNull() - && !obj.value("S2").isNull() && !obj.value("H1").isNull() - && !obj.value("H2").isNull() && !obj.value("H3").isNull() - && !obj.value("H4").isNull()) { + if (!obj.value("Jc").isNull()) { config.m_junkPacketCount = obj.value("Jc").toString(); + } + if (!obj.value("Jmin").isNull()) { config.m_junkPacketMinSize = obj.value("Jmin").toString(); + } + if (!obj.value("Jmax").isNull()) { config.m_junkPacketMaxSize = obj.value("Jmax").toString(); + } + if (!obj.value("S1").isNull()) { config.m_initPacketJunkSize = obj.value("S1").toString(); + } + if (!obj.value("S2").isNull()) { config.m_responsePacketJunkSize = obj.value("S2").toString(); + } + if (!obj.value("H1").isNull()) { config.m_initPacketMagicHeader = obj.value("H1").toString(); + } + if (!obj.value("H2").isNull()) { config.m_responsePacketMagicHeader = obj.value("H2").toString(); + } + if (!obj.value("H3").isNull()) { config.m_underloadPacketMagicHeader = obj.value("H3").toString(); + } + if (!obj.value("H4").isNull()) { config.m_transportPacketMagicHeader = obj.value("H4").toString(); } diff --git a/client/mozilla/localsocketcontroller.cpp b/client/mozilla/localsocketcontroller.cpp index 420cabee..877dfed5 100644 --- a/client/mozilla/localsocketcontroller.cpp +++ b/client/mozilla/localsocketcontroller.cpp @@ -232,6 +232,24 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) { 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)); + } 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::initPacketMagicHeader).isUndefined() + && !wgConfig.value(amnezia::config_key::responsePacketMagicHeader).isUndefined() + && !wgConfig.value(amnezia::config_key::underloadPacketMagicHeader).isUndefined() + && !wgConfig.value(amnezia::config_key::transportPacketMagicHeader).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::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)); } write(json); diff --git a/client/platforms/linux/daemon/wireguardutilslinux.cpp b/client/platforms/linux/daemon/wireguardutilslinux.cpp index e5dce524..c92adb02 100644 --- a/client/platforms/linux/daemon/wireguardutilslinux.cpp +++ b/client/platforms/linux/daemon/wireguardutilslinux.cpp @@ -103,15 +103,32 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) { out << "private_key=" << QString(privateKey.toHex()) << "\n"; out << "replace_peers=true\n"; - if (config.m_junkPacketCount != "") { + + if (!config.m_junkPacketCount.isEmpty()) { out << "jc=" << config.m_junkPacketCount << "\n"; + } + if (!config.m_junkPacketMinSize.isEmpty()) { out << "jmin=" << config.m_junkPacketMinSize << "\n"; + } + if (!config.m_junkPacketMaxSize.isEmpty()) { out << "jmax=" << config.m_junkPacketMaxSize << "\n"; + } + if (!config.m_initPacketJunkSize.isEmpty()) { out << "s1=" << config.m_initPacketJunkSize << "\n"; + } + if (!config.m_responsePacketJunkSize.isEmpty()) { out << "s2=" << config.m_responsePacketJunkSize << "\n"; + } + if (!config.m_initPacketMagicHeader.isEmpty()) { out << "h1=" << config.m_initPacketMagicHeader << "\n"; + } + if (!config.m_responsePacketMagicHeader.isEmpty()) { out << "h2=" << config.m_responsePacketMagicHeader << "\n"; + } + if (!config.m_underloadPacketMagicHeader.isEmpty()) { out << "h3=" << config.m_underloadPacketMagicHeader << "\n"; + } + if (!config.m_transportPacketMagicHeader.isEmpty()) { out << "h4=" << config.m_transportPacketMagicHeader << "\n"; } diff --git a/client/platforms/macos/daemon/wireguardutilsmacos.cpp b/client/platforms/macos/daemon/wireguardutilsmacos.cpp index 718edaba..4c30eec6 100644 --- a/client/platforms/macos/daemon/wireguardutilsmacos.cpp +++ b/client/platforms/macos/daemon/wireguardutilsmacos.cpp @@ -101,15 +101,31 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) { out << "private_key=" << QString(privateKey.toHex()) << "\n"; out << "replace_peers=true\n"; - if (config.m_junkPacketCount != "") { + if (!config.m_junkPacketCount.isEmpty()) { out << "jc=" << config.m_junkPacketCount << "\n"; + } + if (!config.m_junkPacketMinSize.isEmpty()) { out << "jmin=" << config.m_junkPacketMinSize << "\n"; + } + if (!config.m_junkPacketMaxSize.isEmpty()) { out << "jmax=" << config.m_junkPacketMaxSize << "\n"; + } + if (!config.m_initPacketJunkSize.isEmpty()) { out << "s1=" << config.m_initPacketJunkSize << "\n"; + } + if (!config.m_responsePacketJunkSize.isEmpty()) { out << "s2=" << config.m_responsePacketJunkSize << "\n"; + } + if (!config.m_initPacketMagicHeader.isEmpty()) { out << "h1=" << config.m_initPacketMagicHeader << "\n"; + } + if (!config.m_responsePacketMagicHeader.isEmpty()) { out << "h2=" << config.m_responsePacketMagicHeader << "\n"; + } + if (!config.m_underloadPacketMagicHeader.isEmpty()) { out << "h3=" << config.m_underloadPacketMagicHeader << "\n"; + } + if (!config.m_transportPacketMagicHeader.isEmpty()) { out << "h4=" << config.m_transportPacketMagicHeader << "\n"; } diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index 15519971..f531ebb6 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "core/errorstrings.h" #ifdef Q_OS_ANDROID @@ -15,15 +16,6 @@ namespace { - enum class ConfigTypes { - Amnezia, - OpenVpn, - WireGuard, - Xray, - Backup, - Invalid - }; - ConfigTypes checkConfigFormat(const QString &config) { const QString openVpnConfigPatternCli = "client"; @@ -95,8 +87,8 @@ bool ImportController::extractConfigFromFile(const QString &fileName) bool ImportController::extractConfigFromData(QString data) { QString config = data; - auto configFormat = checkConfigFormat(config); - if (configFormat == ConfigTypes::Invalid) { + m_configType = checkConfigFormat(config); + if (m_configType == ConfigTypes::Invalid) { data.replace("vpn://", ""); QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); QByteArray ba_uncompressed = qUncompress(ba); @@ -105,14 +97,15 @@ bool ImportController::extractConfigFromData(QString data) } config = ba; - configFormat = checkConfigFormat(config); + m_configType = checkConfigFormat(config); } - switch (configFormat) { + switch (m_configType) { case ConfigTypes::OpenVpn: { m_config = extractOpenVpnConfig(config); return m_config.empty() ? false : true; } + case ConfigTypes::Awg: case ConfigTypes::WireGuard: { m_config = extractWireGuardConfig(config); return m_config.empty() ? false : true; @@ -168,6 +161,39 @@ QString ImportController::getConfigFileName() return m_configFileName; } +bool ImportController::isNativeWireGuardConfig() +{ + return m_configType == ConfigTypes::WireGuard; +} + +void ImportController::processNativeWireGuardConfig() +{ + auto containers = m_config.value(config_key::containers).toArray(); + if (!containers.isEmpty()) { + auto container = containers.at(0).toObject(); + auto containerConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::WireGuard)).toObject(); + auto protocolConfig = QJsonDocument::fromJson(containerConfig.value(config_key::last_config).toString().toUtf8()).object(); + + QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(3, 10)); + QString junkPacketMinSize = QString::number(50); + QString junkPacketMaxSize = QString::number(1000); + protocolConfig[config_key::junkPacketCount] = junkPacketCount; + protocolConfig[config_key::junkPacketMinSize] = junkPacketMinSize; + protocolConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize; + protocolConfig[config_key::initPacketJunkSize] = "0"; + protocolConfig[config_key::responsePacketJunkSize] = "0"; + protocolConfig[config_key::initPacketMagicHeader] = "1"; + protocolConfig[config_key::responsePacketMagicHeader] = "2"; + protocolConfig[config_key::underloadPacketMagicHeader] = "3"; + protocolConfig[config_key::transportPacketMagicHeader] = "4"; + + containerConfig[config_key::last_config] = QString(QJsonDocument(protocolConfig).toJson()); + container["wireguard"] = containerConfig; + containers.replace(0, container); + m_config[config_key::containers] = containers; + } +} + void ImportController::importConfig() { ServerCredentials credentials; @@ -323,6 +349,7 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data) lastConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader); lastConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader); protocolName = "awg"; + m_configType = ConfigTypes::Awg; } QJsonObject wireguardConfig; diff --git a/client/ui/controllers/importController.h b/client/ui/controllers/importController.h index 0fabc36d..bebbeca3 100644 --- a/client/ui/controllers/importController.h +++ b/client/ui/controllers/importController.h @@ -3,11 +3,22 @@ #include -#include "containers/containers_defs.h" -#include "core/defs.h" #include "ui/models/containers_model.h" #include "ui/models/servers_model.h" +namespace +{ + enum class ConfigTypes { + Amnezia, + OpenVpn, + WireGuard, + Awg, + Xray, + Backup, + Invalid + }; +} + class ImportController : public QObject { Q_OBJECT @@ -36,6 +47,9 @@ public slots: static bool decodeQrCode(const QString &code); #endif + bool isNativeWireGuardConfig(); + void processNativeWireGuardConfig(); + signals: void importFinished(); void importErrorOccurred(const QString &errorMessage, bool goToPageHome); @@ -59,6 +73,7 @@ private: QJsonObject m_config; QString m_configFileName; + ConfigTypes m_configType; #if defined Q_OS_ANDROID || defined Q_OS_IOS QMap m_qrCodeChunks; diff --git a/client/ui/qml/Pages2/PageSetupWizardViewConfig.qml b/client/ui/qml/Pages2/PageSetupWizardViewConfig.qml index 658d6604..88368734 100644 --- a/client/ui/qml/Pages2/PageSetupWizardViewConfig.qml +++ b/client/ui/qml/Pages2/PageSetupWizardViewConfig.qml @@ -116,6 +116,15 @@ PageType { } } + CheckBoxType { + id: cloakingCheckBox + + visible: ImportController.isNativeWireGuardConfig() + + Layout.fillWidth: true + text: qsTr("Enable WireGuard obfuscation. It may be useful if WireGuard is blocked on your provider.") + } + WarningType { Layout.topMargin: 16 Layout.fillWidth: true @@ -164,6 +173,9 @@ PageType { text: qsTr("Connect") clickedFunc: function() { + if (cloakingCheckBox.checked) { + ImportController.processNativeWireGuardConfig() + } ImportController.importConfig() } }