From 96f26d5a0107094ac1602e5023976aa117a0aead Mon Sep 17 00:00:00 2001 From: Mykola Baibuz Date: Wed, 4 Sep 2024 23:23:23 +0300 Subject: [PATCH 1/8] GoodByeDPI support initial --- client/3rd-prebuilt | 2 +- client/CMakeLists.txt | 2 + client/containers/containers_defs.cpp | 14 +++- client/containers/containers_defs.h | 1 + .../vpnConfigurationController.cpp | 9 +- client/core/defs.h | 1 + client/protocols/goodbyedpi.cpp | 83 +++++++++++++++++++ client/protocols/goodbyedpi.h | 28 +++++++ client/protocols/protocols_defs.cpp | 2 + client/protocols/protocols_defs.h | 3 +- client/protocols/vpnprotocol.cpp | 2 + client/ui/models/containers_model.cpp | 8 +- client/utilities.cpp | 9 ++ client/utilities.h | 1 + ipc/ipc.h | 5 +- 15 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 client/protocols/goodbyedpi.cpp create mode 100644 client/protocols/goodbyedpi.h diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt index c38a587fc..a7ec16db4 160000 --- a/client/3rd-prebuilt +++ b/client/3rd-prebuilt @@ -1 +1 @@ -Subproject commit c38a587fcda89bab4009560d36239fa8de74705e +Subproject commit a7ec16db48c6bb712eeaaabe278833b0f4b99155 diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 327a83f6b..d84430068 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -261,10 +261,12 @@ if(WIN32) ) set(HEADERS ${HEADERS} + ${CMAKE_CURRENT_LIST_DIR}/protocols/goodbyedpi.h ${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_windows.h ) set(SOURCES ${SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/protocols/goodbyedpi.cpp ${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_windows.cpp ) diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index ce673a85f..dcbf4bef9 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -53,6 +53,8 @@ QVector ContainerProps::protocolsForContainer(amnezia::DockerCon switch (container) { case DockerContainer::None: return {}; + case DockerContainer::GoodbyeDPI: return { Proto::GoodyeDPI }; + case DockerContainer::OpenVpn: return { Proto::OpenVpn }; case DockerContainer::ShadowSocks: return { Proto::OpenVpn, Proto::ShadowSocks }; @@ -97,6 +99,7 @@ QMap ContainerProps::containerHumanNames() { DockerContainer::Xray, "XRay" }, { DockerContainer::Ipsec, QObject::tr("IPsec") }, { DockerContainer::SSXray, "Shadowsocks"}, + { DockerContainer::GoodbyeDPI, "GoodbyeDPI"}, { DockerContainer::TorWebSite, QObject::tr("Website in Tor network") }, { DockerContainer::Dns, QObject::tr("AmneziaDNS") }, @@ -136,7 +139,9 @@ QMap ContainerProps::containerDescriptions() { DockerContainer::Sftp, QObject::tr("Create a file vault on your server to securely store and transfer files.") }, { DockerContainer::Socks5Proxy, - QObject::tr("") } }; + QObject::tr("") } , + { DockerContainer::GoodbyeDPI, + QObject::tr("GoodbueDPI --//DESRIPTION//--") }}; } QMap ContainerProps::containerDetailedDescriptions() @@ -245,7 +250,9 @@ QMap ContainerProps::containerDetailedDescriptions() "You will be able to access it using\n FileZilla or other SFTP clients, " "as well as mount the disk on your device to access\n it directly from your device.\n\n" "For more detailed information, you can\n find it in the support section under \"Create SFTP file storage.\" ") }, - { DockerContainer::Socks5Proxy, QObject::tr("SOCKS5 proxy server") } + { DockerContainer::Socks5Proxy, QObject::tr("SOCKS5 proxy server") }, + { DockerContainer::GoodbyeDPI, QObject::tr("GoodbyeDPI --//DETAILED DESRIPTION//--") } + }; } @@ -271,6 +278,7 @@ Proto ContainerProps::defaultProtocol(DockerContainer c) case DockerContainer::Dns: return Proto::Dns; case DockerContainer::Sftp: return Proto::Sftp; case DockerContainer::Socks5Proxy: return Proto::Socks5Proxy; + case DockerContainer::GoodbyeDPI: return Proto::GoodyeDPI; default: return Proto::Any; } } @@ -377,6 +385,7 @@ bool ContainerProps::isShareable(DockerContainer container) case DockerContainer::Dns: return false; case DockerContainer::Sftp: return false; case DockerContainer::Socks5Proxy: return false; + case DockerContainer::GoodbyeDPI: return false; default: return true; } } @@ -402,6 +411,7 @@ int ContainerProps::installPageOrder(DockerContainer container) case DockerContainer::Xray: return 3; case DockerContainer::Ipsec: return 7; case DockerContainer::SSXray: return 8; + case DockerContainer::GoodbyeDPI: return 9; default: return 0; } } diff --git a/client/containers/containers_defs.h b/client/containers/containers_defs.h index 0d7f9aa15..6a6a5719f 100644 --- a/client/containers/containers_defs.h +++ b/client/containers/containers_defs.h @@ -24,6 +24,7 @@ namespace amnezia Ipsec, Xray, SSXray, + GoodbyeDPI, // non-vpn TorWebSite, diff --git a/client/core/controllers/vpnConfigurationController.cpp b/client/core/controllers/vpnConfigurationController.cpp index 818cf57e6..9cebf8738 100644 --- a/client/core/controllers/vpnConfigurationController.cpp +++ b/client/core/controllers/vpnConfigurationController.cpp @@ -34,7 +34,8 @@ ErrorCode VpnConfigurationsController::createProtocolConfigForContainer(const Se { ErrorCode errorCode = ErrorCode::NoError; - if (ContainerProps::containerService(container) == ServiceType::Other) { + if (ContainerProps::containerService(container) == ServiceType::Other || + container == DockerContainer::GoodbyeDPI) { return errorCode; } @@ -61,7 +62,8 @@ ErrorCode VpnConfigurationsController::createProtocolConfigString(const bool isA { ErrorCode errorCode = ErrorCode::NoError; - if (ContainerProps::containerService(container) == ServiceType::Other) { + if (ContainerProps::containerService(container) == ServiceType::Other || + container == DockerContainer::GoodbyeDPI) { return errorCode; } @@ -82,7 +84,8 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair +#include +#include + +#include + +#include + +#include "logger.h" +#include "goodbyedpi.h" +#include "utilities.h" + + +GoodbyeDPIProtocol::GoodbyeDPIProtocol(const QJsonObject &configuration, QObject* parent) : + VpnProtocol(configuration, parent) +{ + qDebug() << "GoodbyeDPIProtocol::GoodbyeDPIProtocol()"; +} + +GoodbyeDPIProtocol::~GoodbyeDPIProtocol() +{ + qDebug() << "GoodbyeDPIProtocol::~GoodbyeDPIProtocol()"; + GoodbyeDPIProtocol::stop(); +} + +void GoodbyeDPIProtocol::stop() +{ + if (m_goodbyeDPIProcess) { + m_goodbyeDPIProcess->close(); + } +} + +ErrorCode GoodbyeDPIProtocol::start() +{ + qDebug() << "GoodbyeDPIProtocol::start()"; + + if (!QFileInfo::exists(Utils::goodbyedpiPath())) { + setLastError(ErrorCode::GoodByeDPIExecutableMissing); + return lastError(); + } + + m_goodbyeDPIProcess = IpcClient::CreatePrivilegedProcess(); + + if (!m_goodbyeDPIProcess) { + setLastError(ErrorCode::AmneziaServiceConnectionFailed); + return ErrorCode::AmneziaServiceConnectionFailed; + } + + m_goodbyeDPIProcess->waitForSource(1000); + if (!m_goodbyeDPIProcess->isInitialized()) { + qWarning() << "IpcProcess replica is not connected!"; + setLastError(ErrorCode::AmneziaServiceConnectionFailed); + return ErrorCode::AmneziaServiceConnectionFailed; + } + + m_goodbyeDPIProcess->setProgram(PermittedProcess::GoodbyeDPI); + + QStringList arguments({"-9", "--blacklist", "goodbyedpi/russia-blacklist.txt", "--blacklist", "goodbyedpi/russia-youtube.txt"}); + + m_goodbyeDPIProcess->setArguments(arguments); + qDebug() << arguments.join(" "); + + connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::errorOccurred, + [&](QProcess::ProcessError error) { qDebug() << "PrivilegedProcess errorOccurred" << error; }); + + connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::stateChanged, + [&](QProcess::ProcessState newState) { + qDebug() << "PrivilegedProcess stateChanged" << newState; + if (newState == QProcess::Running) + { + setConnectionState(Vpn::ConnectionState::Connected); + } + }); + + connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::finished, this, + [&]() { + setConnectionState(Vpn::ConnectionState::Disconnected); + }); + + + m_goodbyeDPIProcess->start(); + return ErrorCode::NoError; +} diff --git a/client/protocols/goodbyedpi.h b/client/protocols/goodbyedpi.h new file mode 100644 index 000000000..beb16d1ad --- /dev/null +++ b/client/protocols/goodbyedpi.h @@ -0,0 +1,28 @@ +#ifndef GOODBYEDPI_H +#define GOODBYEDPI_H + +#include +#include +#include +#include +#include + +#include "vpnprotocol.h" +#include "core/ipcclient.h" + +class GoodbyeDPIProtocol : public VpnProtocol +{ + Q_OBJECT + +public: + explicit GoodbyeDPIProtocol(const QJsonObject& configuration, QObject* parent = nullptr); + virtual ~GoodbyeDPIProtocol() override; + + ErrorCode start() override; + void stop() override; + +private: + QSharedPointer m_goodbyeDPIProcess; +}; + +#endif // GOODBYEDPI_H diff --git a/client/protocols/protocols_defs.cpp b/client/protocols/protocols_defs.cpp index ac5bb1ad8..a440f24a2 100644 --- a/client/protocols/protocols_defs.cpp +++ b/client/protocols/protocols_defs.cpp @@ -75,6 +75,7 @@ QMap ProtocolProps::protocolHumanNames() { Proto::SSXray, "Shadowsocks"}, + { Proto::GoodyeDPI, "GoodbyeDPI"}, { Proto::TorWebSite, "Website in Tor network" }, { Proto::Dns, "DNS Service" }, { Proto::Sftp, QObject::tr("SFTP service") }, @@ -99,6 +100,7 @@ amnezia::ServiceType ProtocolProps::protocolService(Proto p) case Proto::Awg: return ServiceType::Vpn; case Proto::Ikev2: return ServiceType::Vpn; case Proto::Xray: return ServiceType::Vpn; + case Proto::GoodyeDPI: return ServiceType::Vpn; case Proto::TorWebSite: return ServiceType::Other; case Proto::Dns: return ServiceType::Other; diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 56be0d7d3..46ec28e24 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -254,7 +254,8 @@ namespace amnezia TorWebSite, Dns, Sftp, - Socks5Proxy + Socks5Proxy, + GoodyeDPI }; Q_ENUM_NS(Proto) diff --git a/client/protocols/vpnprotocol.cpp b/client/protocols/vpnprotocol.cpp index 056089b8f..e0cdd5bb9 100644 --- a/client/protocols/vpnprotocol.cpp +++ b/client/protocols/vpnprotocol.cpp @@ -14,6 +14,7 @@ #ifdef Q_OS_WINDOWS #include "ikev2_vpn_protocol_windows.h" + #include "goodbyedpi.h" #endif VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject *parent) @@ -108,6 +109,7 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject & switch (container) { #if defined(Q_OS_WINDOWS) case DockerContainer::Ipsec: return new Ikev2Protocol(configuration); + case DockerContainer::GoodbyeDPI: return new GoodbyeDPIProtocol(configuration); #endif #if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) case DockerContainer::OpenVpn: return new OpenVpnProtocol(configuration); diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 41d26bc72..9f722d773 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -37,7 +37,13 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const case EasySetupHeaderRole: return ContainerProps::easySetupHeader(container); case EasySetupDescriptionRole: return ContainerProps::easySetupDescription(container); case EasySetupOrderRole: return ContainerProps::easySetupOrder(container); - case IsInstalledRole: return m_containers.contains(container); + case IsInstalledRole: { +#ifdef Q_OS_WIN + if (container == DockerContainer::GoodbyeDPI) + return true; +#endif + return m_containers.contains(container); + } case IsCurrentlyProcessedRole: return container == static_cast(m_processedContainerIndex); case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container); case IsShareableRole: return ContainerProps::isShareable(container); diff --git a/client/utilities.cpp b/client/utilities.cpp index a2f3d021d..22a9d2313 100644 --- a/client/utilities.cpp +++ b/client/utilities.cpp @@ -214,6 +214,15 @@ QString Utils::certUtilPath() #endif } +QString Utils::goodbyedpiPath() +{ +#ifdef Q_OS_WIN + return Utils::executable("goodbyedpi/goodbyedpi", true); +#else + return ""; +#endif +} + QString Utils::tun2socksPath() { #ifdef Q_OS_WIN diff --git a/client/utilities.h b/client/utilities.h index b85c5b3b1..89902e36e 100644 --- a/client/utilities.h +++ b/client/utilities.h @@ -34,6 +34,7 @@ class Utils : public QObject static QString wireguardExecPath(); static QString certUtilPath(); static QString tun2socksPath(); + static QString goodbyedpiPath(); #ifdef Q_OS_WIN static bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent); diff --git a/ipc/ipc.h b/ipc/ipc.h index b13296577..5185689e7 100644 --- a/ipc/ipc.h +++ b/ipc/ipc.h @@ -14,7 +14,8 @@ enum PermittedProcess { OpenVPN, Wireguard, Tun2Socks, - CertUtil + CertUtil, + GoodbyeDPI }; inline QString permittedProcessPath(PermittedProcess pid) @@ -27,6 +28,8 @@ inline QString permittedProcessPath(PermittedProcess pid) return Utils::certUtilPath(); } else if (pid == PermittedProcess::Tun2Socks) { return Utils::tun2socksPath(); + } else if (pid == PermittedProcess::GoodbyeDPI){ + return Utils::goodbyedpiPath(); } return ""; } From ca1bf0d6cd8c5f0d82041876e9f497728a66d666 Mon Sep 17 00:00:00 2001 From: Mykola Baibuz Date: Wed, 4 Sep 2024 23:51:23 +0300 Subject: [PATCH 2/8] Setup correct blacklist path --- client/protocols/goodbyedpi.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/protocols/goodbyedpi.cpp b/client/protocols/goodbyedpi.cpp index a53ec1d43..fff45ca41 100644 --- a/client/protocols/goodbyedpi.cpp +++ b/client/protocols/goodbyedpi.cpp @@ -28,6 +28,7 @@ void GoodbyeDPIProtocol::stop() if (m_goodbyeDPIProcess) { m_goodbyeDPIProcess->close(); } + setConnectionState(Vpn::ConnectionState::Disconnected); } ErrorCode GoodbyeDPIProtocol::start() @@ -55,7 +56,8 @@ ErrorCode GoodbyeDPIProtocol::start() m_goodbyeDPIProcess->setProgram(PermittedProcess::GoodbyeDPI); - QStringList arguments({"-9", "--blacklist", "goodbyedpi/russia-blacklist.txt", "--blacklist", "goodbyedpi/russia-youtube.txt"}); + QStringList arguments({"-9", "--blacklist", QCoreApplication::applicationDirPath() + "/goodbyedpi/russia-blacklist.txt", + "--blacklist", QCoreApplication::applicationDirPath() + "/goodbyedpi/russia-youtube.txt"}); m_goodbyeDPIProcess->setArguments(arguments); qDebug() << arguments.join(" "); From c7a48aeabcb230d817489199954bc5ed441fc9e8 Mon Sep 17 00:00:00 2001 From: Mykola Baibuz Date: Thu, 5 Sep 2024 15:55:08 +0300 Subject: [PATCH 3/8] Update GoodByeDPI description --- client/containers/containers_defs.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index dcbf4bef9..5720b6d78 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -141,7 +141,7 @@ QMap ContainerProps::containerDescriptions() { DockerContainer::Socks5Proxy, QObject::tr("") } , { DockerContainer::GoodbyeDPI, - QObject::tr("GoodbueDPI --//DESRIPTION//--") }}; + QObject::tr("GoodbyeDPI — Deep Packet Inspection circumvention utility") }}; } QMap ContainerProps::containerDetailedDescriptions() @@ -251,7 +251,9 @@ QMap ContainerProps::containerDetailedDescriptions() "as well as mount the disk on your device to access\n it directly from your device.\n\n" "For more detailed information, you can\n find it in the support section under \"Create SFTP file storage.\" ") }, { DockerContainer::Socks5Proxy, QObject::tr("SOCKS5 proxy server") }, - { DockerContainer::GoodbyeDPI, QObject::tr("GoodbyeDPI --//DETAILED DESRIPTION//--") } + { DockerContainer::GoodbyeDPI, QObject::tr("This software designed to bypass Deep Packet Inspection systems found in many Internet Service Providers which block access to certain websites. \n" + "It handles DPI connected using optical splitter or port mirroring (Passive DPI) which do not block any data but just replying faster than requested destination," + "and Active DPI connected in sequence.") } }; } From 5e27f0c8f022f625bc02b6d834117b28675c29b6 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 10 Sep 2024 17:31:44 +0400 Subject: [PATCH 4/8] feature: added a ui with the feature to configure goodbye dpi - added configuration file selection - added modset selection --- client/CMakeLists.txt | 14 +- client/amnezia_application.cpp | 10 ++ client/amnezia_application.h | 2 + client/containers/containers_defs.cpp | 15 +- client/containers/containers_defs.h | 1 - .../vpnConfigurationController.cpp | 9 +- client/core/errorstrings.cpp | 1 + client/localServices/goodByeDpi.cpp | 62 +++++++ client/localServices/goodByeDpi.h | 25 +++ client/protocols/goodbyedpi.cpp | 85 ---------- client/protocols/goodbyedpi.h | 28 --- client/protocols/protocols_defs.cpp | 2 - client/protocols/protocols_defs.h | 2 + client/protocols/vpnprotocol.cpp | 2 - client/resources.qrc | 1 + client/settings.cpp | 30 ++++ client/settings.h | 14 +- .../ui/controllers/connectionController.cpp | 16 ++ client/ui/controllers/connectionController.h | 3 + .../controllers/localServicesController.cpp | 101 +++++++++++ .../ui/controllers/localServicesController.h | 50 ++++++ client/ui/controllers/pageController.cpp | 12 +- client/ui/controllers/pageController.h | 21 ++- client/ui/controllers/settingsController.cpp | 12 +- client/ui/controllers/settingsController.h | 3 + client/ui/models/containers_model.cpp | 8 +- client/ui/models/servers_model.cpp | 24 ++- client/ui/models/servers_model.h | 4 +- .../LocalServices/PageGoodByeDpiSettings.qml | 159 ++++++++++++++++++ client/ui/qml/Pages2/PageHome.qml | 12 +- client/ui/qml/Pages2/PageSettings.qml | 14 ++ .../ui/qml/Pages2/PageSettingsServersList.qml | 2 + .../qml/Pages2/PageSetupWizardInstalling.qml | 2 +- client/ui/qml/Pages2/PageStart.qml | 12 +- 34 files changed, 589 insertions(+), 169 deletions(-) create mode 100644 client/localServices/goodByeDpi.cpp create mode 100644 client/localServices/goodByeDpi.h delete mode 100644 client/protocols/goodbyedpi.cpp delete mode 100644 client/protocols/goodbyedpi.h create mode 100644 client/ui/controllers/localServicesController.cpp create mode 100644 client/ui/controllers/localServicesController.h create mode 100644 client/ui/qml/Pages2/LocalServices/PageGoodByeDpiSettings.qml diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index d84430068..acfbaafa6 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -236,8 +236,14 @@ file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/services/*.cpp ) -file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.h) -file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.cpp) +file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS + ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.h + ${CMAKE_CURRENT_LIST_DIR}/ui/models/localServices/*.h +) +file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS + ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.cpp + ${CMAKE_CURRENT_LIST_DIR}/ui/models/localServices/*.cpp +) set(HEADERS ${HEADERS} ${COMMON_FILES_H} @@ -261,13 +267,13 @@ if(WIN32) ) set(HEADERS ${HEADERS} - ${CMAKE_CURRENT_LIST_DIR}/protocols/goodbyedpi.h ${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_windows.h + ${CMAKE_CURRENT_LIST_DIR}/localServices/goodByeDpi.h ) set(SOURCES ${SOURCES} - ${CMAKE_CURRENT_LIST_DIR}/protocols/goodbyedpi.cpp ${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_windows.cpp + ${CMAKE_CURRENT_LIST_DIR}/localServices/goodByeDpi.cpp ) set(RESOURCES ${RESOURCES} diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index b8ce5b004..dbe1acfc7 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -235,6 +235,7 @@ void AmneziaApplication::registerTypes() Vpn::declareQmlVpnConnectionStateEnum(); PageLoader::declareQmlPageEnum(); + PageLoader::declareQmlFolderEnum(); } void AmneziaApplication::loadFonts() @@ -455,4 +456,13 @@ void AmneziaApplication::initControllers() m_systemController.reset(new SystemController(m_settings)); m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get()); + + m_localServicesController.reset(new LocalServicesController(m_serversModel, m_settings)); + m_engine->rootContext()->setContextProperty("LocalServicesController", m_localServicesController.get()); + connect(m_connectionController.get(), &ConnectionController::startLocalService, m_localServicesController.get(), + &LocalServicesController::start); + connect(m_connectionController.get(), &ConnectionController::stopLocalService, m_localServicesController.get(), + &LocalServicesController::stop); + connect(m_localServicesController.get(), &LocalServicesController::serviceStateChanged, m_connectionController.get(), + &ConnectionController::connectionStateChanged); } diff --git a/client/amnezia_application.h b/client/amnezia_application.h index 6fb61f44a..1675ad4ea 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -24,6 +24,7 @@ #include "ui/controllers/sitesController.h" #include "ui/controllers/systemController.h" #include "ui/controllers/appSplitTunnelingController.h" +#include "ui/controllers/localServicesController.h" #include "ui/models/containers_model.h" #include "ui/models/languageModel.h" #include "ui/models/protocols/cloakConfigModel.h" @@ -136,6 +137,7 @@ class AmneziaApplication : public AMNEZIA_BASE_CLASS QScopedPointer m_sitesController; QScopedPointer m_systemController; QScopedPointer m_appSplitTunnelingController; + QScopedPointer m_localServicesController; QNetworkAccessManager *m_nam; diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index 5720b6d78..06f8fd0c6 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -53,8 +53,6 @@ QVector ContainerProps::protocolsForContainer(amnezia::DockerCon switch (container) { case DockerContainer::None: return {}; - case DockerContainer::GoodbyeDPI: return { Proto::GoodyeDPI }; - case DockerContainer::OpenVpn: return { Proto::OpenVpn }; case DockerContainer::ShadowSocks: return { Proto::OpenVpn, Proto::ShadowSocks }; @@ -99,7 +97,6 @@ QMap ContainerProps::containerHumanNames() { DockerContainer::Xray, "XRay" }, { DockerContainer::Ipsec, QObject::tr("IPsec") }, { DockerContainer::SSXray, "Shadowsocks"}, - { DockerContainer::GoodbyeDPI, "GoodbyeDPI"}, { DockerContainer::TorWebSite, QObject::tr("Website in Tor network") }, { DockerContainer::Dns, QObject::tr("AmneziaDNS") }, @@ -139,9 +136,7 @@ QMap ContainerProps::containerDescriptions() { DockerContainer::Sftp, QObject::tr("Create a file vault on your server to securely store and transfer files.") }, { DockerContainer::Socks5Proxy, - QObject::tr("") } , - { DockerContainer::GoodbyeDPI, - QObject::tr("GoodbyeDPI — Deep Packet Inspection circumvention utility") }}; + QObject::tr("") } }; } QMap ContainerProps::containerDetailedDescriptions() @@ -250,10 +245,7 @@ QMap ContainerProps::containerDetailedDescriptions() "You will be able to access it using\n FileZilla or other SFTP clients, " "as well as mount the disk on your device to access\n it directly from your device.\n\n" "For more detailed information, you can\n find it in the support section under \"Create SFTP file storage.\" ") }, - { DockerContainer::Socks5Proxy, QObject::tr("SOCKS5 proxy server") }, - { DockerContainer::GoodbyeDPI, QObject::tr("This software designed to bypass Deep Packet Inspection systems found in many Internet Service Providers which block access to certain websites. \n" - "It handles DPI connected using optical splitter or port mirroring (Passive DPI) which do not block any data but just replying faster than requested destination," - "and Active DPI connected in sequence.") } + { DockerContainer::Socks5Proxy, QObject::tr("SOCKS5 proxy server") } } }; } @@ -280,7 +272,6 @@ Proto ContainerProps::defaultProtocol(DockerContainer c) case DockerContainer::Dns: return Proto::Dns; case DockerContainer::Sftp: return Proto::Sftp; case DockerContainer::Socks5Proxy: return Proto::Socks5Proxy; - case DockerContainer::GoodbyeDPI: return Proto::GoodyeDPI; default: return Proto::Any; } } @@ -387,7 +378,6 @@ bool ContainerProps::isShareable(DockerContainer container) case DockerContainer::Dns: return false; case DockerContainer::Sftp: return false; case DockerContainer::Socks5Proxy: return false; - case DockerContainer::GoodbyeDPI: return false; default: return true; } } @@ -413,7 +403,6 @@ int ContainerProps::installPageOrder(DockerContainer container) case DockerContainer::Xray: return 3; case DockerContainer::Ipsec: return 7; case DockerContainer::SSXray: return 8; - case DockerContainer::GoodbyeDPI: return 9; default: return 0; } } diff --git a/client/containers/containers_defs.h b/client/containers/containers_defs.h index 6a6a5719f..0d7f9aa15 100644 --- a/client/containers/containers_defs.h +++ b/client/containers/containers_defs.h @@ -24,7 +24,6 @@ namespace amnezia Ipsec, Xray, SSXray, - GoodbyeDPI, // non-vpn TorWebSite, diff --git a/client/core/controllers/vpnConfigurationController.cpp b/client/core/controllers/vpnConfigurationController.cpp index 9cebf8738..818cf57e6 100644 --- a/client/core/controllers/vpnConfigurationController.cpp +++ b/client/core/controllers/vpnConfigurationController.cpp @@ -34,8 +34,7 @@ ErrorCode VpnConfigurationsController::createProtocolConfigForContainer(const Se { ErrorCode errorCode = ErrorCode::NoError; - if (ContainerProps::containerService(container) == ServiceType::Other || - container == DockerContainer::GoodbyeDPI) { + if (ContainerProps::containerService(container) == ServiceType::Other) { return errorCode; } @@ -62,8 +61,7 @@ ErrorCode VpnConfigurationsController::createProtocolConfigString(const bool isA { ErrorCode errorCode = ErrorCode::NoError; - if (ContainerProps::containerService(container) == ServiceType::Other || - container == DockerContainer::GoodbyeDPI) { + if (ContainerProps::containerService(container) == ServiceType::Other) { return errorCode; } @@ -84,8 +82,7 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPairwaitForSource(1000); + if (!m_goodbyeDPIProcess->isInitialized()) { + qWarning() << "IpcProcess replica is not connected!"; + return amnezia::ErrorCode::AmneziaServiceConnectionFailed; + } + + m_goodbyeDPIProcess->setProgram(amnezia::PermittedProcess::GoodbyeDPI); + + QStringList arguments; + arguments << QString("-%1").arg(modset); + arguments << QString("--blacklist %1").arg(blackListFile); + + m_goodbyeDPIProcess->setArguments(arguments); + qDebug() << arguments.join(" "); + + connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::errorOccurred, + [&](QProcess::ProcessError error) { qDebug() << "PrivilegedProcess errorOccurred" << error; }); + + connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::stateChanged, [&](QProcess::ProcessState newState) { + qDebug() << "PrivilegedProcess stateChanged" << newState; + if (newState == QProcess::Running) { + qDebug() << "PrivilegedProcess running"; + emit serviceStateChanged(Vpn::ConnectionState::Connected); + } + }); + + connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::finished, this, [&]() { + qDebug() << "PrivilegedProcess finished"; + emit serviceStateChanged(Vpn::ConnectionState::Disconnected); + }); + + m_goodbyeDPIProcess->start(); + return amnezia::ErrorCode::NoError; +} + +void GoodByeDpi::stop() +{ + if (m_goodbyeDPIProcess) { + m_goodbyeDPIProcess->close(); + } +} diff --git a/client/localServices/goodByeDpi.h b/client/localServices/goodByeDpi.h new file mode 100644 index 000000000..c2419e0e6 --- /dev/null +++ b/client/localServices/goodByeDpi.h @@ -0,0 +1,25 @@ +#ifndef GOODBYEDPI_H +#define GOODBYEDPI_H + +#include + +#include "core/defs.h" +#include "core/privileged_process.h" +#include "protocols/vpnprotocol.h" + +class GoodByeDpi : public QObject +{ + Q_OBJECT +public: + explicit GoodByeDpi(QObject *parent = nullptr); + + amnezia::ErrorCode start(const QString &blackListFile, const int modset); + void stop(); + +private: + QSharedPointer m_goodbyeDPIProcess; +signals: + void serviceStateChanged(Vpn::ConnectionState state); +}; + +#endif // GOODBYEDPI_H diff --git a/client/protocols/goodbyedpi.cpp b/client/protocols/goodbyedpi.cpp deleted file mode 100644 index fff45ca41..000000000 --- a/client/protocols/goodbyedpi.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include - -#include - -#include - -#include "logger.h" -#include "goodbyedpi.h" -#include "utilities.h" - - -GoodbyeDPIProtocol::GoodbyeDPIProtocol(const QJsonObject &configuration, QObject* parent) : - VpnProtocol(configuration, parent) -{ - qDebug() << "GoodbyeDPIProtocol::GoodbyeDPIProtocol()"; -} - -GoodbyeDPIProtocol::~GoodbyeDPIProtocol() -{ - qDebug() << "GoodbyeDPIProtocol::~GoodbyeDPIProtocol()"; - GoodbyeDPIProtocol::stop(); -} - -void GoodbyeDPIProtocol::stop() -{ - if (m_goodbyeDPIProcess) { - m_goodbyeDPIProcess->close(); - } - setConnectionState(Vpn::ConnectionState::Disconnected); -} - -ErrorCode GoodbyeDPIProtocol::start() -{ - qDebug() << "GoodbyeDPIProtocol::start()"; - - if (!QFileInfo::exists(Utils::goodbyedpiPath())) { - setLastError(ErrorCode::GoodByeDPIExecutableMissing); - return lastError(); - } - - m_goodbyeDPIProcess = IpcClient::CreatePrivilegedProcess(); - - if (!m_goodbyeDPIProcess) { - setLastError(ErrorCode::AmneziaServiceConnectionFailed); - return ErrorCode::AmneziaServiceConnectionFailed; - } - - m_goodbyeDPIProcess->waitForSource(1000); - if (!m_goodbyeDPIProcess->isInitialized()) { - qWarning() << "IpcProcess replica is not connected!"; - setLastError(ErrorCode::AmneziaServiceConnectionFailed); - return ErrorCode::AmneziaServiceConnectionFailed; - } - - m_goodbyeDPIProcess->setProgram(PermittedProcess::GoodbyeDPI); - - QStringList arguments({"-9", "--blacklist", QCoreApplication::applicationDirPath() + "/goodbyedpi/russia-blacklist.txt", - "--blacklist", QCoreApplication::applicationDirPath() + "/goodbyedpi/russia-youtube.txt"}); - - m_goodbyeDPIProcess->setArguments(arguments); - qDebug() << arguments.join(" "); - - connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::errorOccurred, - [&](QProcess::ProcessError error) { qDebug() << "PrivilegedProcess errorOccurred" << error; }); - - connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::stateChanged, - [&](QProcess::ProcessState newState) { - qDebug() << "PrivilegedProcess stateChanged" << newState; - if (newState == QProcess::Running) - { - setConnectionState(Vpn::ConnectionState::Connected); - } - }); - - connect(m_goodbyeDPIProcess.data(), &PrivilegedProcess::finished, this, - [&]() { - setConnectionState(Vpn::ConnectionState::Disconnected); - }); - - - m_goodbyeDPIProcess->start(); - return ErrorCode::NoError; -} diff --git a/client/protocols/goodbyedpi.h b/client/protocols/goodbyedpi.h deleted file mode 100644 index beb16d1ad..000000000 --- a/client/protocols/goodbyedpi.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef GOODBYEDPI_H -#define GOODBYEDPI_H - -#include -#include -#include -#include -#include - -#include "vpnprotocol.h" -#include "core/ipcclient.h" - -class GoodbyeDPIProtocol : public VpnProtocol -{ - Q_OBJECT - -public: - explicit GoodbyeDPIProtocol(const QJsonObject& configuration, QObject* parent = nullptr); - virtual ~GoodbyeDPIProtocol() override; - - ErrorCode start() override; - void stop() override; - -private: - QSharedPointer m_goodbyeDPIProcess; -}; - -#endif // GOODBYEDPI_H diff --git a/client/protocols/protocols_defs.cpp b/client/protocols/protocols_defs.cpp index a440f24a2..ac5bb1ad8 100644 --- a/client/protocols/protocols_defs.cpp +++ b/client/protocols/protocols_defs.cpp @@ -75,7 +75,6 @@ QMap ProtocolProps::protocolHumanNames() { Proto::SSXray, "Shadowsocks"}, - { Proto::GoodyeDPI, "GoodbyeDPI"}, { Proto::TorWebSite, "Website in Tor network" }, { Proto::Dns, "DNS Service" }, { Proto::Sftp, QObject::tr("SFTP service") }, @@ -100,7 +99,6 @@ amnezia::ServiceType ProtocolProps::protocolService(Proto p) case Proto::Awg: return ServiceType::Vpn; case Proto::Ikev2: return ServiceType::Vpn; case Proto::Xray: return ServiceType::Vpn; - case Proto::GoodyeDPI: return ServiceType::Vpn; case Proto::TorWebSite: return ServiceType::Other; case Proto::Dns: return ServiceType::Other; diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 46ec28e24..0ea264d74 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -100,6 +100,8 @@ namespace amnezia constexpr char clientId[] = "clientId"; + constexpr char isGoodbyeDpi[] = "is_goodbye_dpi"; + } namespace protocols diff --git a/client/protocols/vpnprotocol.cpp b/client/protocols/vpnprotocol.cpp index e0cdd5bb9..056089b8f 100644 --- a/client/protocols/vpnprotocol.cpp +++ b/client/protocols/vpnprotocol.cpp @@ -14,7 +14,6 @@ #ifdef Q_OS_WINDOWS #include "ikev2_vpn_protocol_windows.h" - #include "goodbyedpi.h" #endif VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject *parent) @@ -109,7 +108,6 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject & switch (container) { #if defined(Q_OS_WINDOWS) case DockerContainer::Ipsec: return new Ikev2Protocol(configuration); - case DockerContainer::GoodbyeDPI: return new GoodbyeDPIProtocol(configuration); #endif #if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) case DockerContainer::OpenVpn: return new OpenVpnProtocol(configuration); diff --git a/client/resources.qrc b/client/resources.qrc index fed42a004..6c8ebcfeb 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -218,6 +218,7 @@ ui/qml/Pages2/PageSettingsApiLanguageList.qml images/controls/archive-restore.svg images/controls/help-circle.svg + ui/qml/Pages2/LocalServices/PageGoodByeDpiSettings.qml images/flagKit/ZW.svg diff --git a/client/settings.cpp b/client/settings.cpp index 490ede526..470e75791 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -523,3 +523,33 @@ QString Settings::getGatewayEndpoint() { return m_gatewayEndpoint; } + +void Settings::setGoodbyeDpiBlackListFile(const QString &file) +{ + setValue("Conf/goodbyeDpiBlackListFile", file); +} + +QString Settings::getGoodbyeDpiBlackListFile() const +{ + return value("Conf/goodbyeDpiBlackListFile").toString(); +} + +void Settings::toggleGoodbyeDpi(bool enable) +{ + setValue("Conf/isGoodbyeDpiEnabled", enable); +} + +bool Settings::isGoodbyeDpiEnabled() const +{ + return value("Conf/isGoodbyeDpiEnabled", false).toBool(); +} + +void Settings::setGoodbyeDpiModset(const int modset) +{ + setValue("Conf/goodbyeDpiModset", modset); +} + +int Settings::getGoodbyeDpiModset() const +{ + return value("Conf/goodbyeDpiModset", 9).toInt(); +} diff --git a/client/settings.h b/client/settings.h index 55a3d0575..6fe9dc7eb 100644 --- a/client/settings.h +++ b/client/settings.h @@ -113,7 +113,10 @@ class Settings : public QObject QString routeModeString(RouteMode mode) const; RouteMode routeMode() const; - void setRouteMode(RouteMode mode) { setValue("Conf/routeMode", mode); } + void setRouteMode(RouteMode mode) + { + setValue("Conf/routeMode", mode); + } bool isSitesSplitTunnelingEnabled() const; void setSitesSplitTunnelingEnabled(bool enabled); @@ -219,6 +222,15 @@ class Settings : public QObject void setGatewayEndpoint(const QString &endpoint); QString getGatewayEndpoint(); + void setGoodbyeDpiBlackListFile(const QString &file); + QString getGoodbyeDpiBlackListFile() const; + + void toggleGoodbyeDpi(bool enable); + bool isGoodbyeDpiEnabled() const; + + void setGoodbyeDpiModset(const int modset); + int getGoodbyeDpiModset() const; + signals: void saveLogsChanged(bool enabled); void screenshotsEnabledChanged(bool enabled); diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp index c7f950007..d1b2d586a 100644 --- a/client/ui/controllers/connectionController.cpp +++ b/client/ui/controllers/connectionController.cpp @@ -44,6 +44,13 @@ void ConnectionController::openConnection() int serverIndex = m_serversModel->getDefaultServerIndex(); QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex); + + const auto isGoodbyeDpi = serverConfig.value(config_key::isGoodbyeDpi).toBool(false); + if (isGoodbyeDpi) { + emit startLocalService(); + return; + } + auto configVersion = serverConfig.value(config_key::configVersion).toInt(); emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Preparing); @@ -65,6 +72,15 @@ void ConnectionController::openConnection() void ConnectionController::closeConnection() { + int serverIndex = m_serversModel->getDefaultServerIndex(); + QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex); + + const auto isGoodbyeDpi = serverConfig.value(config_key::isGoodbyeDpi).toBool(false); + if (isGoodbyeDpi) { + emit stopLocalService(); + return; + } + emit disconnectFromVpn(); } diff --git a/client/ui/controllers/connectionController.h b/client/ui/controllers/connectionController.h index 25d4d74a1..5104ca6e9 100644 --- a/client/ui/controllers/connectionController.h +++ b/client/ui/controllers/connectionController.h @@ -61,6 +61,9 @@ public slots: void updateApiConfigFromTelegram(); void configFromApiUpdated(); + void startLocalService(); + void stopLocalService(); + private: Vpn::ConnectionState getCurrentConnectionState(); bool isProtocolConfigExists(const QJsonObject &containerConfig, const DockerContainer container); diff --git a/client/ui/controllers/localServicesController.cpp b/client/ui/controllers/localServicesController.cpp new file mode 100644 index 000000000..36e23de3e --- /dev/null +++ b/client/ui/controllers/localServicesController.cpp @@ -0,0 +1,101 @@ +#include "localServicesController.h" + +namespace +{ + // Logger logger("ServerController"); +} + +LocalServicesController::LocalServicesController(const QSharedPointer &serversModel, + const std::shared_ptr &settings, QObject *parent) + : QObject(parent), m_serversModel(serversModel), m_settings(settings) +{ + connect(&m_goodbyeDpiService, &GoodByeDpi::serviceStateChanged, this, &LocalServicesController::serviceStateChanged); +} + +LocalServicesController::~LocalServicesController() +{ + m_goodbyeDpiService.stop(); +} + +void LocalServicesController::toggleGoodbyeDpi(bool enable) +{ + if (enable) { + // auto file = getGoodbyeDpiBlackListFile(); + // auto modset = getGoodbyeDpiModset(); + // auto errorCode = ErrorCode::NoError;//m_goodbyeDpiService.start(file, modset); + // if (errorCode != ErrorCode::NoError) { + // emit errorOccurred(errorCode); + // } else { + + QJsonObject server; + server.insert(config_key::isGoodbyeDpi, true); + server.insert(config_key::description, "GoodbyeDPI service"); + server.insert(config_key::name, "GoodbyeDPI"); + m_serversModel->addServer(server); + m_serversModel->setDefaultServerIndex(m_serversModel->getServersCount() - 1); + + m_settings->toggleGoodbyeDpi(true); + emit toggleGoodbyeDpiFinished(tr("GoodbyeDPI added to home page")); + // } + } else { + // m_goodbyeDpiService.stop(); + + for (int i = 0; i < m_serversModel->getServersCount(); i++) { + if (m_serversModel->getServerConfig(i).value(config_key::isGoodbyeDpi).toBool(false)) { + m_serversModel->setProcessedServerIndex(i); + m_serversModel->removeServer(); + break; + } + } + + m_settings->toggleGoodbyeDpi(false); + emit toggleGoodbyeDpiFinished("GoodbyeDPI removed from home page"); + } +} + +bool LocalServicesController::isGoodbyeDpiEnabled() +{ + return m_settings->isGoodbyeDpiEnabled(); +} + +void LocalServicesController::setGoodbyeDpiBlackListFile(const QString &file) +{ + m_settings->setGoodbyeDpiBlackListFile(file); +} + +QString LocalServicesController::getGoodbyeDpiBlackListFile() +{ + auto file = m_settings->getGoodbyeDpiBlackListFile(); + if (file.isEmpty()) { + return m_defaultBlackListFile; + } + return file; +} + +void LocalServicesController::resetGoodbyeDpiBlackListFile() +{ + m_settings->setGoodbyeDpiBlackListFile(m_defaultBlackListFile); +} + +void LocalServicesController::setGoodbyeDpiModset(const int modset) +{ + m_settings->setGoodbyeDpiModset(modset); +} + +int LocalServicesController::getGoodbyeDpiModset() +{ + return m_settings->getGoodbyeDpiModset(); +} + +void LocalServicesController::start() +{ + auto errorCode = m_goodbyeDpiService.start(getGoodbyeDpiBlackListFile(), getGoodbyeDpiModset()); + if (errorCode != ErrorCode::NoError) { + emit errorOccurred(errorCode); + } +} + +void LocalServicesController::stop() +{ + m_goodbyeDpiService.stop(); +} diff --git a/client/ui/controllers/localServicesController.h b/client/ui/controllers/localServicesController.h new file mode 100644 index 000000000..4daa517f6 --- /dev/null +++ b/client/ui/controllers/localServicesController.h @@ -0,0 +1,50 @@ +#ifndef LOCALSERVICESCONTROLLER_H +#define LOCALSERVICESCONTROLLER_H + +#include + +#include "localServices/goodByeDpi.h" +#include "protocols/vpnprotocol.h" +#include "settings.h" +#include "ui/models/servers_model.h" + +class LocalServicesController : public QObject +{ + Q_OBJECT + +public: + LocalServicesController(const QSharedPointer &serversModel, const std::shared_ptr &settings, + QObject *parent = nullptr); + ~LocalServicesController(); + + Q_PROPERTY(bool isGoodbyeDpiEnabled READ isGoodbyeDpiEnabled NOTIFY toggleGoodbyeDpiFinished) + +public slots: + void toggleGoodbyeDpi(bool enable); + bool isGoodbyeDpiEnabled(); + + void setGoodbyeDpiBlackListFile(const QString &file); + QString getGoodbyeDpiBlackListFile(); + void resetGoodbyeDpiBlackListFile(); + + void setGoodbyeDpiModset(const int modset); + int getGoodbyeDpiModset(); + + void start(); + void stop(); + +signals: + void errorOccurred(ErrorCode errorCode); + void toggleGoodbyeDpiFinished(const QString &message); + void serviceStateChanged(Vpn::ConnectionState state); + +private: + std::shared_ptr m_settings; + QSharedPointer m_serversModel; + + GoodByeDpi m_goodbyeDpiService; + bool m_isGoodbyeDpiServiceEnabled = false; + QString m_defaultBlackListFile = QCoreApplication::applicationDirPath() + "/goodbyedpi/blacklist.txt"; +}; + +#endif // LOCALSERVICESCONTROLLER_H diff --git a/client/ui/controllers/pageController.cpp b/client/ui/controllers/pageController.cpp index 3e5e5cc3d..91c8ddc43 100644 --- a/client/ui/controllers/pageController.cpp +++ b/client/ui/controllers/pageController.cpp @@ -59,11 +59,19 @@ bool PageController::isStartPageVisible() } } -QString PageController::getPagePath(PageLoader::PageEnum page) +QString PageController::getPagePath(PageLoader::PageEnum page, PageLoader::FolderEnum folder) { QMetaEnum metaEnum = QMetaEnum::fromType(); QString pageName = metaEnum.valueToKey(static_cast(page)); - return "qrc:/ui/qml/Pages2/" + pageName + ".qml"; + + metaEnum = QMetaEnum::fromType(); + QString folderName = ""; + if (metaEnum.value(static_cast(folder)) != static_cast(PageLoader::FolderEnum::Root)) { + folderName = metaEnum.valueToKey(static_cast(folder)); + folderName += "/"; + } + + return "qrc:/ui/qml/Pages2/" + folderName + pageName + ".qml"; } void PageController::closeWindow() diff --git a/client/ui/controllers/pageController.h b/client/ui/controllers/pageController.h index 2cc2d983d..771569681 100644 --- a/client/ui/controllers/pageController.h +++ b/client/ui/controllers/pageController.h @@ -61,7 +61,9 @@ namespace PageLoader PageShareFullAccess, - PageDevMenu + PageDevMenu, + + PageGoodByeDpiSettings }; Q_ENUM_NS(PageEnum) @@ -69,6 +71,19 @@ namespace PageLoader { qmlRegisterUncreatableMetaObject(PageLoader::staticMetaObject, "PageEnum", 1, 0, "PageEnum", "Error: only enums"); } + + Q_NAMESPACE + enum class FolderEnum { + Root = 0, + LocalServices + + }; + Q_ENUM_NS(FolderEnum) + + static void declareQmlFolderEnum() + { + qmlRegisterUncreatableMetaObject(PageLoader::staticMetaObject, "FolderEnum", 1, 0, "FolderEnum", "Error: only enums"); + } } class PageController : public QObject @@ -80,7 +95,7 @@ class PageController : public QObject public slots: bool isStartPageVisible(); - QString getPagePath(PageLoader::PageEnum page); + QString getPagePath(PageLoader::PageEnum page, PageLoader::FolderEnum folder = PageLoader::FolderEnum::Root); void closeWindow(); void hideWindow(); @@ -103,7 +118,7 @@ public slots: void onShowErrorMessage(amnezia::ErrorCode errorCode); signals: - void goToPage(PageLoader::PageEnum page, bool slide = true); + void goToPage(PageLoader::PageEnum page, PageLoader::FolderEnum folder = PageLoader::FolderEnum::Root, bool slide = true); void goToStartPage(); void goToPageHome(); void goToPageSettings(); diff --git a/client/ui/controllers/settingsController.cpp b/client/ui/controllers/settingsController.cpp index 93fd89714..5ca5a8791 100644 --- a/client/ui/controllers/settingsController.cpp +++ b/client/ui/controllers/settingsController.cpp @@ -16,8 +16,7 @@ SettingsController::SettingsController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, - const QSharedPointer &languageModel, - const QSharedPointer &sitesModel, + const QSharedPointer &languageModel, const QSharedPointer &sitesModel, const QSharedPointer &appSplitTunnelingModel, const std::shared_ptr &settings, QObject *parent) : QObject(parent), @@ -31,7 +30,8 @@ SettingsController::SettingsController(const QSharedPointer &serve m_appVersion = QString("%1 (%2, %3)").arg(QString(APP_VERSION), __DATE__, GIT_COMMIT_HASH); checkIfNeedDisableLogs(); #ifdef Q_OS_ANDROID - connect(AndroidController::instance(), &AndroidController::notificationStateChanged, this, &SettingsController::onNotificationStateChanged); + connect(AndroidController::instance(), &AndroidController::notificationStateChanged, this, + &SettingsController::onNotificationStateChanged); #endif } @@ -131,8 +131,7 @@ void SettingsController::restoreAppConfigFromData(const QByteArray &data) bool ok = m_settings->restoreAppConfig(data); if (ok) { m_serversModel->resetModel(); - m_languageModel->changeLanguage( - static_cast(m_languageModel->getCurrentLanguageIndex())); + m_languageModel->changeLanguage(static_cast(m_languageModel->getCurrentLanguageIndex())); emit restoreBackupFinished(); } else { emit changeSettingsErrorOccurred(tr("Backup file is corrupted")); @@ -148,8 +147,7 @@ void SettingsController::clearSettings() { m_settings->clearSettings(); m_serversModel->resetModel(); - m_languageModel->changeLanguage( - static_cast(m_languageModel->getCurrentLanguageIndex())); + m_languageModel->changeLanguage(static_cast(m_languageModel->getCurrentLanguageIndex())); m_sitesModel->setRouteMode(Settings::RouteMode::VpnOnlyForwardSites); m_sitesModel->toggleSplitTunneling(false); diff --git a/client/ui/controllers/settingsController.h b/client/ui/controllers/settingsController.h index a18888a9e..a2cb1fbf5 100644 --- a/client/ui/controllers/settingsController.h +++ b/client/ui/controllers/settingsController.h @@ -8,6 +8,7 @@ #include "ui/models/servers_model.h" #include "ui/models/sites_model.h" #include "ui/models/appSplitTunnelingModel.h" +#include "localServices/goodByeDpi.h" class SettingsController : public QObject { @@ -112,6 +113,8 @@ public slots: QSharedPointer m_appSplitTunnelingModel; std::shared_ptr m_settings; + GoodByeDpi m_goodbyeDpiService; + QString m_appVersion; QDateTime m_loggingDisableDate; diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 9f722d773..41d26bc72 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -37,13 +37,7 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const case EasySetupHeaderRole: return ContainerProps::easySetupHeader(container); case EasySetupDescriptionRole: return ContainerProps::easySetupDescription(container); case EasySetupOrderRole: return ContainerProps::easySetupOrder(container); - case IsInstalledRole: { -#ifdef Q_OS_WIN - if (container == DockerContainer::GoodbyeDPI) - return true; -#endif - return m_containers.contains(container); - } + case IsInstalledRole: return m_containers.contains(container); case IsCurrentlyProcessedRole: return container == static_cast(m_processedContainerIndex); case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container); case IsShareableRole: return ContainerProps::isShareable(container); diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 85e5dae2d..3805dd59e 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -88,9 +88,10 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const const QJsonObject server = m_servers.at(index.row()).toObject(); const auto apiConfig = server.value(configKey::apiConfig).toObject(); const auto configVersion = server.value(config_key::configVersion).toInt(); + const auto isGoodbyeDpi = server.value(config_key::isGoodbyeDpi).toBool(false); switch (role) { case NameRole: { - if (configVersion) { + if (configVersion || isGoodbyeDpi) { return server.value(config_key::name).toString(); } auto name = server.value(config_key::description).toString(); @@ -100,6 +101,10 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const return name; } case ServerDescriptionRole: { + if (isGoodbyeDpi) { + return server.value(config_key::description).toString(); + } + auto description = getServerDescription(server, index.row()); return configVersion ? description : description + server.value(config_key::hostName).toString(); } @@ -144,6 +149,9 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const QString primaryDns = server.value(config_key::dns1).toString(); return primaryDns == protocols::dns::amneziaDnsIp; } + case IsGoodByeDpiRole: { + return isGoodbyeDpi; + } } return QVariant(); @@ -208,6 +216,12 @@ QString ServersModel::getServerDescription(const QJsonObject &server, const int const QString ServersModel::getDefaultServerDescriptionCollapsed() { const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); + + const auto isGoodbyeDpi = server.value(config_key::isGoodbyeDpi).toBool(false); + if (isGoodbyeDpi) { + return server.value(config_key::description).toString(); + } + const auto configVersion = server.value(config_key::configVersion).toInt(); auto description = getServerDescription(server, m_defaultServerIndex); if (configVersion) { @@ -222,6 +236,12 @@ const QString ServersModel::getDefaultServerDescriptionCollapsed() const QString ServersModel::getDefaultServerDescriptionExpanded() { const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); + + const auto isGoodbyeDpi = server.value(config_key::isGoodbyeDpi).toBool(false); + if (isGoodbyeDpi) { + return server.value(config_key::description).toString(); + } + const auto configVersion = server.value(config_key::configVersion).toInt(); auto description = getServerDescription(server, m_defaultServerIndex); if (configVersion) { @@ -370,6 +390,8 @@ QHash ServersModel::roleNames() const roles[IsCountrySelectionAvailableRole] = "isCountrySelectionAvailable"; roles[ApiAvailableCountriesRole] = "apiAvailableCountries"; roles[ApiServerCountryCodeRole] = "apiServerCountryCode"; + + roles[IsGoodByeDpiRole] = "isGoodbyeDpi"; return roles; } diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index 0f18ea301..7e4271758 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -38,7 +38,9 @@ class ServersModel : public QAbstractListModel ApiAvailableCountriesRole, ApiServerCountryCodeRole, - HasAmneziaDns + HasAmneziaDns, + + IsGoodByeDpiRole }; ServersModel(std::shared_ptr settings, QObject *parent = nullptr); diff --git a/client/ui/qml/Pages2/LocalServices/PageGoodByeDpiSettings.qml b/client/ui/qml/Pages2/LocalServices/PageGoodByeDpiSettings.qml new file mode 100644 index 000000000..58c47ade1 --- /dev/null +++ b/client/ui/qml/Pages2/LocalServices/PageGoodByeDpiSettings.qml @@ -0,0 +1,159 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import PageEnum 1.0 +import Style 1.0 + +import "./" +import "../../Controls2" +import "../../Config" +import "../../Controls2/TextTypes" +import "../../Components" + +PageType { + id: root + + BackButtonType { + id: backButton + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.topMargin: 20 + } + + FlickableType { + id: fl + anchors.top: backButton.bottom + anchors.bottom: parent.bottom + contentHeight: content.height + + ColumnLayout { + id: content + + property bool isGoodbyeDpiEnabled: LocalServicesController.isGoodbyeDpiEnabled + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: 16 + anchors.rightMargin: 16 + + spacing: 16 + + HeaderType { + Layout.fillWidth: true + + headerText: qsTr("GoodbyeDPI settings") + descriptionText: qsTr("Deep Packet Inspection circumvention utility") + } + + SwitcherType { + Layout.fillWidth: true + + text: qsTr("Enable GoodbyeDPI") + + checked: LocalServicesController.isGoodbyeDpiEnabled + onCheckedChanged: { + if (checked !== LocalServicesController.isGoodbyeDpiEnabled) { + LocalServicesController.toggleGoodbyeDpi(checked) + } + } + } + + RowLayout { + Layout.fillWidth: true + Layout.topMargin: 16 + + enabled: !content.isGoodbyeDpiEnabled + + ListItemTitleType { + Layout.fillWidth: true + + text: LocalServicesController.getGoodbyeDpiBlackListFile() + } + + ImageButtonType { + image: "qrc:/images/controls/folder-search-2.svg" + imageColor: AmneziaStyle.color.paleGray + + onClicked: function() { + var fileName = SystemController.getFileName(qsTr("Open black list file"), + qsTr("Text files (*.txt)")) + + LocalServicesController.setGoodbyeDpiBlackListFile(fileName) + } + } + + ImageButtonType { + image: "qrc:/images/controls/trash.svg" + imageColor: AmneziaStyle.color.paleGray + + onClicked: function() { + LocalServicesController.resetGoodbyeDpiBlackListFile() + } + } + } + + DropDownType { + id: modsetDropDown + Layout.fillWidth: true + + descriptionText: qsTr("Setup templates") + headerText: qsTr("Modset") + + drawerParent: root + + enabled: !content.isGoodbyeDpiEnabled + + listView: ListViewWithRadioButtonType { + id: modsetListView + + rootWidth: root.width + + model: ListModel { + ListElement { name : "-p -r -s -f 2 -k 2 -n -e 2" } + ListElement { name : "-p -r -s -f 2 -k 2 -n -e 40" } + ListElement { name : "-p -r -s -e 40" } + ListElement { name : "-p -r -s" } + ListElement { name : "-f 2 -e 2 --auto-ttl --reverse-frag --max-payload" } + ListElement { name : "-f 2 -e 2 --wrong-seq --reverse-frag --max-payload" } + ListElement { name : "-f 2 -e 2 --wrong-chksum --reverse-frag --max-payload" } + ListElement { name : "-f 2 -e 2 --wrong-seq --wrong-chksum --reverse-frag --max-payload" } + ListElement { name : "-f 2 -e 2 --wrong-seq --wrong-chksum --reverse-frag --max-payload -q" } + } + + clickedFunction: function() { + modsetDropDown.text = selectedText + LocalServicesController.setGoodbyeDpiModset(currentIndex + 1) + modsetDropDown.close() + } + + Component.onCompleted: { + modsetListView.currentIndex = (LocalServicesController.getGoodbyeDpiModset() - 1) + modsetListView.triggerCurrentItem() + } + } + } + + BasicButtonType { + id: detailedInstructionsButton + implicitHeight: 32 + + defaultColor: AmneziaStyle.color.transparent + hoveredColor: AmneziaStyle.color.translucentWhite + pressedColor: AmneziaStyle.color.sheerWhite + disabledColor: AmneziaStyle.color.mutedGray + textColor: AmneziaStyle.color.goldenApricot + + text: qsTr("Description of options") + + clickedFunc: function() { + Qt.openUrlExternally("https://github.com/ValdikSS/GoodbyeDPI?tab=readme-ov-file#how-to-use") + } + } + } + } + +} diff --git a/client/ui/qml/Pages2/PageHome.qml b/client/ui/qml/Pages2/PageHome.qml index 8074337a9..c8296dc4e 100644 --- a/client/ui/qml/Pages2/PageHome.qml +++ b/client/ui/qml/Pages2/PageHome.qml @@ -105,6 +105,8 @@ PageType { buttonTextLabel.font.pixelSize: 14 buttonTextLabel.font.weight: 500 + visible: !ServersModel.getDefaultServerData("isGoodbyeDpi") + property bool isSplitTunnelingEnabled: SitesModel.isTunnelingEnabled || AppSplitTunnelingModel.isTunnelingEnabled || ServersModel.isDefaultServerDefaultContainerHasSplitTunneling @@ -304,7 +306,7 @@ PageType { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter spacing: 8 - visible: !ServersModel.isDefaultServerFromApi + visible: !ServersModel.isDefaultServerFromApi && !ServersModel.getDefaultServerData("isGoodbyeDpi") Item { id: focusItem1 @@ -535,8 +537,12 @@ PageType { Keys.onReturnPressed: serverInfoButton.clicked() onClicked: function() { - ServersModel.processedIndex = index - PageController.goToPage(PageEnum.PageSettingsServerInfo) + if (ServersModel.getDefaultServerData("isGoodbyeDpi")) { + PageController.goToPage(PageEnum.PageGoodByeDpiSettings, PageEnum.LocalServices) + } else { + ServersModel.processedIndex = index + PageController.goToPage(PageEnum.PageSettingsServerInfo) + } drawer.close() } } diff --git a/client/ui/qml/Pages2/PageSettings.qml b/client/ui/qml/Pages2/PageSettings.qml index bb5ca7667..76cae3b58 100644 --- a/client/ui/qml/Pages2/PageSettings.qml +++ b/client/ui/qml/Pages2/PageSettings.qml @@ -95,6 +95,20 @@ PageType { DividerType {} + LabelWithButtonType { + Layout.fillWidth: true + + text: qsTr("Local bypass services") + rightImageSource: "qrc:/images/controls/chevron-right.svg" + leftImageSource: "qrc:/images/controls/app.svg" + + clickedFunction: function() { + PageController.goToPage(PageEnum.PageGoodByeDpiSettings, PageEnum.LocalServices) + } + } + + DividerType {} + LabelWithButtonType { id: backup Layout.fillWidth: true diff --git a/client/ui/qml/Pages2/PageSettingsServersList.qml b/client/ui/qml/Pages2/PageSettingsServersList.qml index 102dd46ff..58fe9e04b 100644 --- a/client/ui/qml/Pages2/PageSettingsServersList.qml +++ b/client/ui/qml/Pages2/PageSettingsServersList.qml @@ -111,6 +111,8 @@ PageType { id: server Layout.fillWidth: true + visible: !isGoodbyeDpi + text: name parentFlickable: fl descriptionText: { diff --git a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml index 1128761d3..9a12d172f 100644 --- a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml +++ b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml @@ -54,7 +54,7 @@ PageType { function onServerAlreadyExists(serverIndex) { PageController.goToStartPage() ServersModel.processedIndex = serverIndex - PageController.goToPage(PageEnum.PageSettingsServerInfo, false) + PageController.goToPage(PageEnum.PageSettingsServerInfo, PageEnum.LocalServices, false) PageController.showErrorMessage(qsTr("The server has already been added to the application")) } diff --git a/client/ui/qml/Pages2/PageStart.qml b/client/ui/qml/Pages2/PageStart.qml index 770347ca2..4b6bb651b 100644 --- a/client/ui/qml/Pages2/PageStart.qml +++ b/client/ui/qml/Pages2/PageStart.qml @@ -60,8 +60,8 @@ PageType { tabBarStackView.pop() } - function onGoToPage(page, slide) { - var pagePath = PageController.getPagePath(page) + function onGoToPage(page, folder, slide) { + var pagePath = PageController.getPagePath(page, folder) if (slide) { tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition) @@ -204,6 +204,14 @@ PageType { } } + Connections { + target: LocalServicesController + + function onErrorOccurred(error) { + PageController.showErrorMessage(error) + } + } + StackViewType { id: tabBarStackView From d47e37e04fab0f81f9cdd7a075207f00633f7fcd Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 10 Sep 2024 21:24:42 +0400 Subject: [PATCH 5/8] limited goodbyedpi to the windows platform --- client/containers/containers_defs.cpp | 51 +++++++++---------- .../controllers/localServicesController.cpp | 18 +++---- .../ui/controllers/localServicesController.h | 10 +++- client/ui/controllers/settingsController.h | 2 - client/ui/qml/Pages2/PageSettings.qml | 2 + 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index 06f8fd0c6..952926a3c 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -1,7 +1,7 @@ #include "containers_defs.h" -#include "QJsonObject" #include "QJsonDocument" +#include "QJsonObject" QDebug operator<<(QDebug debug, const amnezia::DockerContainer &c) { @@ -96,7 +96,7 @@ QMap ContainerProps::containerHumanNames() { DockerContainer::Awg, "AmneziaWG" }, { DockerContainer::Xray, "XRay" }, { DockerContainer::Ipsec, QObject::tr("IPsec") }, - { DockerContainer::SSXray, "Shadowsocks"}, + { DockerContainer::SSXray, "Shadowsocks" }, { DockerContainer::TorWebSite, QObject::tr("Website in Tor network") }, { DockerContainer::Dns, QObject::tr("AmneziaDNS") }, @@ -124,27 +124,24 @@ QMap ContainerProps::containerDescriptions() "but very resistant to blockages. " "Recommended for regions with high levels of censorship.") }, { DockerContainer::Xray, - QObject::tr("XRay with REALITY - Suitable for countries with the highest level of internet censorship. " - "Traffic masking as web traffic at the TLS level, and protection against detection by active probing methods.") }, + QObject::tr( + "XRay with REALITY - Suitable for countries with the highest level of internet censorship. " + "Traffic masking as web traffic at the TLS level, and protection against detection by active probing methods.") }, { DockerContainer::Ipsec, QObject::tr("IKEv2/IPsec - Modern stable protocol, a bit faster than others, restores connection after " "signal loss. It has native support on the latest versions of Android and iOS.") }, { DockerContainer::TorWebSite, QObject::tr("Deploy a WordPress site on the Tor network in two clicks.") }, - { DockerContainer::Dns, - QObject::tr("Replace the current DNS server with your own. This will increase your privacy level.") }, - { DockerContainer::Sftp, - QObject::tr("Create a file vault on your server to securely store and transfer files.") }, - { DockerContainer::Socks5Proxy, - QObject::tr("") } }; + { DockerContainer::Dns, QObject::tr("Replace the current DNS server with your own. This will increase your privacy level.") }, + { DockerContainer::Sftp, QObject::tr("Create a file vault on your server to securely store and transfer files.") }, + { DockerContainer::Socks5Proxy, QObject::tr("") } }; } QMap ContainerProps::containerDetailedDescriptions() { return { { DockerContainer::OpenVpn, - QObject::tr( - "OpenVPN stands as one of the most popular and time-tested VPN protocols available.\n" + QObject::tr("OpenVPN stands as one of the most popular and time-tested VPN protocols available.\n" "It employs its unique security protocol, " "leveraging the strength of SSL/TLS for encryption and key exchange. " "Furthermore, OpenVPN's support for a multitude of authentication methods makes it versatile and adaptable, " @@ -160,7 +157,8 @@ QMap ContainerProps::containerDetailedDescriptions() "* Can operate over both TCP and UDP network protocols.") }, { DockerContainer::ShadowSocks, QObject::tr("Shadowsocks, inspired by the SOCKS5 protocol, safeguards the connection using the AEAD cipher. " - "Although Shadowsocks is designed to be discreet and challenging to identify, it isn't identical to a standard HTTPS connection." + "Although Shadowsocks is designed to be discreet and challenging to identify, it isn't identical to a standard HTTPS " + "connection." "However, certain traffic analysis systems might still detect a Shadowsocks connection. " "Due to limited support in Amnezia, it's recommended to use AmneziaWG protocol.\n\n" "* Available in the AmneziaVPN only on desktop platforms\n" @@ -217,15 +215,18 @@ QMap ContainerProps::containerDetailedDescriptions() "* Works over UDP network protocol.") }, { DockerContainer::Xray, QObject::tr("The REALITY protocol, a pioneering development by the creators of XRay, " - "is specifically designed to counteract the highest levels of internet censorship through its novel approach to evasion.\n" - "It uniquely identifies censors during the TLS handshake phase, seamlessly operating as a proxy for legitimate clients while diverting censors to genuine websites like google.com, " + "is specifically designed to counteract the highest levels of internet censorship through its novel approach to " + "evasion.\n" + "It uniquely identifies censors during the TLS handshake phase, seamlessly operating as a proxy for legitimate " + "clients while diverting censors to genuine websites like google.com, " "thus presenting an authentic TLS certificate and data. \n" - "This advanced capability differentiates REALITY from similar technologies by its ability to disguise web traffic as coming from random, " + "This advanced capability differentiates REALITY from similar technologies by its ability to disguise web traffic as " + "coming from random, " "legitimate sites without the need for specific configurations. \n" "Unlike older protocols such as VMess, VLESS, and the XTLS-Vision transport, " - "REALITY's innovative \"friend or foe\" recognition at the TLS handshake enhances security and circumvents detection by sophisticated DPI systems employing active probing techniques. " - "This makes REALITY a robust solution for maintaining internet freedom in environments with stringent censorship.") - }, + "REALITY's innovative \"friend or foe\" recognition at the TLS handshake enhances security and circumvents detection " + "by sophisticated DPI systems employing active probing techniques. " + "This makes REALITY a robust solution for maintaining internet freedom in environments with stringent censorship.") }, { DockerContainer::Ipsec, QObject::tr("IKEv2, paired with the IPSec encryption layer, stands as a modern and stable VPN protocol.\n" "One of its distinguishing features is its ability to swiftly switch between networks and devices, " @@ -245,8 +246,7 @@ QMap ContainerProps::containerDetailedDescriptions() "You will be able to access it using\n FileZilla or other SFTP clients, " "as well as mount the disk on your device to access\n it directly from your device.\n\n" "For more detailed information, you can\n find it in the support section under \"Create SFTP file storage.\" ") }, - { DockerContainer::Socks5Proxy, QObject::tr("SOCKS5 proxy server") } } - + { DockerContainer::Socks5Proxy, QObject::tr("SOCKS5 proxy server") } }; } @@ -288,7 +288,8 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c) case DockerContainer::Awg: return true; case DockerContainer::Xray: return true; case DockerContainer::Cloak: return true; - case DockerContainer::SSXray: return true; + case DockerContainer::SSXray: + return true; // case DockerContainer::ShadowSocks: return true; default: return false; } @@ -384,10 +385,8 @@ bool ContainerProps::isShareable(DockerContainer container) QJsonObject ContainerProps::getProtocolConfigFromContainer(const Proto protocol, const QJsonObject &containerConfig) { - QString protocolConfigString = containerConfig.value(ProtocolProps::protoToString(protocol)) - .toObject() - .value(config_key::last_config) - .toString(); + QString protocolConfigString = + containerConfig.value(ProtocolProps::protoToString(protocol)).toObject().value(config_key::last_config).toString(); return QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); } diff --git a/client/ui/controllers/localServicesController.cpp b/client/ui/controllers/localServicesController.cpp index 36e23de3e..3cd999aee 100644 --- a/client/ui/controllers/localServicesController.cpp +++ b/client/ui/controllers/localServicesController.cpp @@ -9,24 +9,21 @@ LocalServicesController::LocalServicesController(const QSharedPointer &settings, QObject *parent) : QObject(parent), m_serversModel(serversModel), m_settings(settings) { +#ifdef Q_OS_WINDOWS connect(&m_goodbyeDpiService, &GoodByeDpi::serviceStateChanged, this, &LocalServicesController::serviceStateChanged); +#endif } LocalServicesController::~LocalServicesController() { +#ifdef Q_OS_WINDOWS m_goodbyeDpiService.stop(); +#endif } void LocalServicesController::toggleGoodbyeDpi(bool enable) { if (enable) { - // auto file = getGoodbyeDpiBlackListFile(); - // auto modset = getGoodbyeDpiModset(); - // auto errorCode = ErrorCode::NoError;//m_goodbyeDpiService.start(file, modset); - // if (errorCode != ErrorCode::NoError) { - // emit errorOccurred(errorCode); - // } else { - QJsonObject server; server.insert(config_key::isGoodbyeDpi, true); server.insert(config_key::description, "GoodbyeDPI service"); @@ -36,10 +33,7 @@ void LocalServicesController::toggleGoodbyeDpi(bool enable) m_settings->toggleGoodbyeDpi(true); emit toggleGoodbyeDpiFinished(tr("GoodbyeDPI added to home page")); - // } } else { - // m_goodbyeDpiService.stop(); - for (int i = 0; i < m_serversModel->getServersCount(); i++) { if (m_serversModel->getServerConfig(i).value(config_key::isGoodbyeDpi).toBool(false)) { m_serversModel->setProcessedServerIndex(i); @@ -89,13 +83,17 @@ int LocalServicesController::getGoodbyeDpiModset() void LocalServicesController::start() { +#ifdef Q_OS_WINDOWS auto errorCode = m_goodbyeDpiService.start(getGoodbyeDpiBlackListFile(), getGoodbyeDpiModset()); if (errorCode != ErrorCode::NoError) { emit errorOccurred(errorCode); } +#endif } void LocalServicesController::stop() { +#ifdef Q_OS_WINDOWS m_goodbyeDpiService.stop(); +#endif } diff --git a/client/ui/controllers/localServicesController.h b/client/ui/controllers/localServicesController.h index 4daa517f6..5d16a3322 100644 --- a/client/ui/controllers/localServicesController.h +++ b/client/ui/controllers/localServicesController.h @@ -3,7 +3,9 @@ #include -#include "localServices/goodByeDpi.h" +#ifdef Q_OS_WINDOWS + #include "localServices/goodByeDpi.h" +#endif #include "protocols/vpnprotocol.h" #include "settings.h" #include "ui/models/servers_model.h" @@ -42,9 +44,15 @@ public slots: std::shared_ptr m_settings; QSharedPointer m_serversModel; +#ifdef Q_OS_WINDOWS GoodByeDpi m_goodbyeDpiService; +#endif bool m_isGoodbyeDpiServiceEnabled = false; +#ifdef Q_OS_WINDOWS QString m_defaultBlackListFile = QCoreApplication::applicationDirPath() + "/goodbyedpi/blacklist.txt"; +#else + QString m_defaultBlackListFile; +#endif }; #endif // LOCALSERVICESCONTROLLER_H diff --git a/client/ui/controllers/settingsController.h b/client/ui/controllers/settingsController.h index a2cb1fbf5..e01cd6a57 100644 --- a/client/ui/controllers/settingsController.h +++ b/client/ui/controllers/settingsController.h @@ -113,8 +113,6 @@ public slots: QSharedPointer m_appSplitTunnelingModel; std::shared_ptr m_settings; - GoodByeDpi m_goodbyeDpiService; - QString m_appVersion; QDateTime m_loggingDisableDate; diff --git a/client/ui/qml/Pages2/PageSettings.qml b/client/ui/qml/Pages2/PageSettings.qml index 76cae3b58..9026fc457 100644 --- a/client/ui/qml/Pages2/PageSettings.qml +++ b/client/ui/qml/Pages2/PageSettings.qml @@ -98,6 +98,8 @@ PageType { LabelWithButtonType { Layout.fillWidth: true + visible: Qt.platform.os === "windows" + text: qsTr("Local bypass services") rightImageSource: "qrc:/images/controls/chevron-right.svg" leftImageSource: "qrc:/images/controls/app.svg" From 3d152adf5fb299efc468410a8b90da898a19389c Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 10 Sep 2024 22:25:06 +0400 Subject: [PATCH 6/8] chore: removed unused header --- client/ui/controllers/settingsController.h | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ui/controllers/settingsController.h b/client/ui/controllers/settingsController.h index 26517c887..efc18a7d0 100644 --- a/client/ui/controllers/settingsController.h +++ b/client/ui/controllers/settingsController.h @@ -8,7 +8,6 @@ #include "ui/models/servers_model.h" #include "ui/models/sites_model.h" #include "ui/models/appSplitTunnelingModel.h" -#include "localServices/goodByeDpi.h" class SettingsController : public QObject { From 92492952e93fbc5bafe5a4c630a9f6302cab92c5 Mon Sep 17 00:00:00 2001 From: Mykola Baibuz Date: Tue, 10 Sep 2024 21:45:46 +0300 Subject: [PATCH 7/8] Update prebuilt --- client/3rd-prebuilt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt index a7ec16db4..2f73c6782 160000 --- a/client/3rd-prebuilt +++ b/client/3rd-prebuilt @@ -1 +1 @@ -Subproject commit a7ec16db48c6bb712eeaaabe278833b0f4b99155 +Subproject commit 2f73c6782ca71f10d5be60aab42817a6a7486968 From f3b3e937e9fbb37f3f450ac54536060c1981960a Mon Sep 17 00:00:00 2001 From: Mykola Baibuz Date: Wed, 11 Sep 2024 00:29:07 +0300 Subject: [PATCH 8/8] Update binaries --- client/3rd-prebuilt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt index 2f73c6782..a1d0c22a6 160000 --- a/client/3rd-prebuilt +++ b/client/3rd-prebuilt @@ -1 +1 @@ -Subproject commit 2f73c6782ca71f10d5be60aab42817a6a7486968 +Subproject commit a1d0c22a6fa64e11bb0e3960a2615b4a57e67818