diff --git a/.gitignore b/.gitignore
index 88a3b397..7de64e4b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ deploy/build/*
deploy/build_32/*
deploy/build_64/*
winbuild*.bat
+.cache/
# Qt-es
diff --git a/.gitmodules b/.gitmodules
index 453a8ee4..c96dd6bc 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "client/3rd/wireguard-apple"]
- path = client/3rd/wireguard-apple
- url = https://github.com/WireGuard/wireguard-apple
[submodule "client/3rd/OpenVPNAdapter"]
path = client/3rd/OpenVPNAdapter
url = https://github.com/amnezia-vpn/OpenVPNAdapter.git
@@ -25,3 +22,6 @@
[submodule "client/3rd-prebuilt"]
path = client/3rd-prebuilt
url = https://github.com/amnezia-vpn/3rd-prebuilt
+[submodule "client/3rd/awg-apple"]
+ path = client/3rd/awg-apple
+ url = https://github.com/amnezia-vpn/awg-apple
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f6f94a23..2e7be435 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,11 +2,14 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
-project(${PROJECT} VERSION 3.1.0.1
+project(${PROJECT} VERSION 4.0.8.6
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
-set(RELEASE_DATE "2023-09-21")
+
+string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
+set(RELEASE_DATE "${CURRENT_DATE}")
+
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt
index e8795854..ac32d335 160000
--- a/client/3rd-prebuilt
+++ b/client/3rd-prebuilt
@@ -1 +1 @@
-Subproject commit e8795854a5cf27004fe78caecc90a961688d1d41
+Subproject commit ac32d33555bd62f0b0af314b1e5119d6d78a1a4e
diff --git a/client/3rd/awg-apple b/client/3rd/awg-apple
new file mode 160000
index 00000000..fab07138
--- /dev/null
+++ b/client/3rd/awg-apple
@@ -0,0 +1 @@
+Subproject commit fab07138dbab06ac0de256021e47e273f4df8e88
diff --git a/client/3rd/qtkeychain b/client/3rd/qtkeychain
index c6f0b663..8bbaa6d8 160000
--- a/client/3rd/qtkeychain
+++ b/client/3rd/qtkeychain
@@ -1 +1 @@
-Subproject commit c6f0b66318f8da6917fb4681103f7303b1836194
+Subproject commit 8bbaa6d8302cf0747d9786ace4dd13c7fb746502
diff --git a/client/3rd/wireguard-apple b/client/3rd/wireguard-apple
deleted file mode 160000
index 23618f99..00000000
--- a/client/3rd/wireguard-apple
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 23618f994f17d8ad8f2f65d79b4a1e8a0830b334
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 7e7837ac..6c4f1ae4 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -10,30 +10,34 @@ set_property(GLOBAL PROPERTY AUTOMOC_TARGETS_FOLDER "Autogen")
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "Autogen")
set(PACKAGES
- Widgets Core Gui Network Xml
+ Core Gui Network Xml
RemoteObjects Quick Svg QuickControls2
Core5Compat Concurrent LinguistTools
)
+
if(IOS)
- set(PACKAGES
- ${PACKAGES}
- Multimedia
- )
+ set(PACKAGES ${PACKAGES} Multimedia)
+endif()
+
+if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
+ set(PACKAGES ${PACKAGES} Widgets)
endif()
find_package(Qt6 REQUIRED COMPONENTS ${PACKAGES})
set(LIBS ${LIBS}
- Qt6::Widgets Qt6::Core Qt6::Gui
+ Qt6::Core Qt6::Gui
Qt6::Network Qt6::Xml Qt6::RemoteObjects
Qt6::Quick Qt6::Svg Qt6::QuickControls2
Qt6::Core5Compat Qt6::Concurrent
)
+
if(IOS)
- set(LIBS
- ${LIBS}
- Qt6::Multimedia
- )
+ set(LIBS ${LIBS} Qt6::Multimedia)
+endif()
+
+if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
+ set(LIBS ${LIBS} Qt6::Widgets)
endif()
qt_standard_project_setup()
@@ -46,12 +50,30 @@ endif()
qt6_add_resources(QRC ${QRC} ${CMAKE_CURRENT_LIST_DIR}/resources.qrc)
-qt6_add_translations(${PROJECT} TS_FILES
+# -- i18n begin
+set(CMAKE_AUTORCC ON)
+
+set(AMNEZIAVPN_TS_FILES
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts
+ ${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_zh_CN.ts
)
+file(GLOB_RECURSE AMNEZIAVPN_TS_SOURCES *.qrc *.cpp *.h *.ui)
+
+qt_create_translation(AMNEZIAVPN_QM_FILES ${AMNEZIAVPN_TS_SOURCES} ${AMNEZIAVPN_TS_FILES})
+
+set(QM_FILE_LIST "")
+foreach(FILE ${AMNEZIAVPN_QM_FILES})
+ get_filename_component(QM_FILE_NAME ${FILE} NAME)
+ list(APPEND QM_FILE_LIST "${QM_FILE_NAME}")
+endforeach()
+string(REPLACE ";" "" QM_FILE_LIST ${QM_FILE_LIST})
+
+configure_file(${CMAKE_CURRENT_LIST_DIR}/translations/translations.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
+qt6_add_resources(QRC ${I18NQRC} ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
+# -- i18n end
+
if(IOS)
- #execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/scripts/run-build-cloak.sh)
execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/ios/scripts/openvpn.sh args
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
endif()
@@ -91,7 +113,6 @@ set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.h
${CMAKE_CURRENT_LIST_DIR}/ui/pages.h
${CMAKE_CURRENT_LIST_DIR}/ui/property_helper.h
- ${CMAKE_CURRENT_LIST_DIR}/ui/uilogic.h
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h
${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h
${CMAKE_CURRENT_BINARY_DIR}/version.h
@@ -128,7 +149,6 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/core/servercontroller.cpp
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.cpp
${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.cpp
- ${CMAKE_CURRENT_LIST_DIR}/ui/uilogic.cpp
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.cpp
${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.cpp
${CMAKE_CURRENT_LIST_DIR}/core/sshclient.cpp
@@ -162,20 +182,33 @@ file(GLOB_RECURSE PAGE_LOGIC_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/
file(GLOB CONFIGURATORS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.h)
file(GLOB CONFIGURATORS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.cpp)
-file(GLOB UI_MODELS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h)
-file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp)
+file(GLOB UI_MODELS_H CONFIGURE_DEPENDS
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.h
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/services/*.h
+)
+file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.cpp
+ ${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)
set(HEADERS ${HEADERS}
${COMMON_FILES_H}
${PAGE_LOGIC_H}
${CONFIGURATORS_H}
${UI_MODELS_H}
+ ${UI_CONTROLLERS_H}
)
set(SOURCES ${SOURCES}
${COMMON_FILES_CPP}
${PAGE_LOGIC_CPP}
${CONFIGURATORS_CPP}
${UI_MODELS_CPP}
+ ${UI_CONTROLLERS_CPP}
)
if(WIN32)
@@ -248,6 +281,7 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.h
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.h
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.h
)
set(SOURCES ${SOURCES}
@@ -258,6 +292,7 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.cpp
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.cpp
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.cpp
)
endif()
@@ -307,16 +342,5 @@ if(NOT IOS AND NOT ANDROID)
endif()
-if(WIN32)
- add_custom_command(
- TARGET ${PROJECT} POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E $,copy,true>
- $/../service/wireguard-service/wireguard-service.exe
- $/wireguard/wireguard-service.exe
- COMMAND_EXPAND_LISTS
- )
-endif()
-
-
-target_sources(${PROJECT} PRIVATE ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC})
+target_sources(${PROJECT} PRIVATE ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC} ${I18NQRC})
qt_finalize_target(${PROJECT})
diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp
index 491a68b8..3e227863 100644
--- a/client/amnezia_application.cpp
+++ b/client/amnezia_application.cpp
@@ -3,55 +3,35 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
#include
+#include
-#include "core/servercontroller.h"
#include "logger.h"
#include "version.h"
-#include
#include "platforms/ios/QRCodeReaderBase.h"
-
-#include "ui/pages.h"
-
-#include "ui/pages_logic/AppSettingsLogic.h"
-#include "ui/pages_logic/GeneralSettingsLogic.h"
-#include "ui/pages_logic/NetworkSettingsLogic.h"
-#include "ui/pages_logic/NewServerProtocolsLogic.h"
-#include "ui/pages_logic/QrDecoderLogic.h"
-#include "ui/pages_logic/ServerConfiguringProgressLogic.h"
-#include "ui/pages_logic/ServerContainersLogic.h"
-#include "ui/pages_logic/ServerListLogic.h"
-#include "ui/pages_logic/ServerSettingsLogic.h"
-#include "ui/pages_logic/ServerContainersLogic.h"
-#include "ui/pages_logic/ShareConnectionLogic.h"
-#include "ui/pages_logic/SitesLogic.h"
-#include "ui/pages_logic/StartPageLogic.h"
-#include "ui/pages_logic/VpnLogic.h"
-#include "ui/pages_logic/WizardLogic.h"
-
-#include "ui/pages_logic/protocols/CloakLogic.h"
-#include "ui/pages_logic/protocols/OpenVpnLogic.h"
-#include "ui/pages_logic/protocols/ShadowSocksLogic.h"
+#if defined(Q_OS_ANDROID)
+ #include "platforms/android/android_controller.h"
+#endif
#include "protocols/qml_register_protocols.h"
#if defined(Q_OS_IOS)
-#include "platforms/ios/QtAppDelegate-C-Interface.h"
-#include "platforms/ios/ios_controller.h"
+ #include "platforms/ios/ios_controller.h"
#endif
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
- AmneziaApplication::AmneziaApplication(int &argc, char *argv[]):
- AMNEZIA_BASE_CLASS(argc, argv)
+AmneziaApplication::AmneziaApplication(int &argc, char *argv[]) : AMNEZIA_BASE_CLASS(argc, argv)
#else
- AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary,
- SingleApplication::Options options, int timeout, const QString &userData):
- SingleApplication(argc, argv, allowSecondary, options, timeout, userData)
+AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, SingleApplication::Options options,
+ int timeout, const QString &userData)
+ : SingleApplication(argc, argv, allowSecondary, options, timeout, userData)
#endif
{
setQuitOnLastWindowClosed(false);
@@ -73,49 +53,97 @@
#endif
m_settings = std::shared_ptr(new Settings);
- m_configurator = std::shared_ptr(new VpnConfigurator(m_settings, this));
}
AmneziaApplication::~AmneziaApplication()
{
+ m_vpnConnectionThread.quit();
+ m_vpnConnectionThread.wait(3000);
+
if (m_engine) {
- QObject::disconnect(m_engine, 0,0,0);
+ QObject::disconnect(m_engine, 0, 0, 0);
delete m_engine;
}
- if (m_uiLogic) {
- QObject::disconnect(m_uiLogic, 0,0,0);
- delete m_uiLogic;
- }
-
- if (m_protocolProps) delete m_protocolProps;
- if (m_containerProps) delete m_containerProps;
}
void AmneziaApplication::init()
{
m_engine = new QQmlApplicationEngine;
- m_uiLogic = new UiLogic(m_settings, m_configurator);
- const QUrl url(QStringLiteral("qrc:/ui/qml/main.qml"));
- QObject::connect(m_engine, &QQmlApplicationEngine::objectCreated,
- this, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
+ const QUrl url(QStringLiteral("qrc:/ui/qml/main2.qml"));
+ QObject::connect(
+ m_engine, &QQmlApplicationEngine::objectCreated, this,
+ [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ },
+ Qt::QueuedConnection);
m_engine->rootContext()->setContextProperty("Debug", &Logger::Instance());
- m_uiLogic->registerPagesLogic();
-#if defined(Q_OS_IOS)
- setStartPageLogic(m_uiLogic->pageLogic());
- IosController::Instance()->initialize();
+ m_configurator = std::shared_ptr(new VpnConfigurator(m_settings, this));
+ m_vpnConnection.reset(new VpnConnection(m_settings, m_configurator));
+ m_vpnConnection->moveToThread(&m_vpnConnectionThread);
+ m_vpnConnectionThread.start();
+
+ initModels();
+ loadTranslator();
+ initControllers();
+
+#ifdef Q_OS_ANDROID
+ connect(AndroidController::instance(), &AndroidController::initialized, this,
+ [this](bool status, bool connected, const QDateTime &connectionDate) {
+ if (connected) {
+ m_connectionController->onConnectionStateChanged(Vpn::ConnectionState::Connected);
+ if (m_vpnConnection)
+ m_vpnConnection->restoreConnection();
+ }
+ });
+ if (!AndroidController::instance()->initialize()) {
+ qCritical() << QString("Init failed");
+ if (m_vpnConnection)
+ emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Error);
+ return;
+ }
+
+ connect(AndroidController::instance(), &AndroidController::importConfigFromOutside, [this](QString data) {
+ m_pageController->replaceStartPage();
+ m_importController->extractConfigFromData(data);
+ m_pageController->goToPageViewConfig();
+ });
#endif
- m_engine->load(url);
+#ifdef Q_OS_IOS
+ IosController::Instance()->initialize();
+ connect(IosController::Instance(), &IosController::importConfigFromOutside, [this](QString data) {
+ m_pageController->replaceStartPage();
+ m_importController->extractConfigFromData(data);
+ m_pageController->goToPageViewConfig();
+ });
- if (m_engine->rootObjects().size() > 0) {
- m_uiLogic->setQmlRoot(m_engine->rootObjects().at(0));
- }
+ connect(IosController::Instance(), &IosController::importBackupFromOutside, [this](QString filePath) {
+ m_pageController->replaceStartPage();
+ m_pageController->goToPageSettingsBackup();
+ m_settingsController->importBackupFromOutside(filePath);
+ });
+#endif
+
+ m_notificationHandler.reset(NotificationHandler::create(nullptr));
+
+ connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(),
+ &NotificationHandler::setConnectionState);
+
+ connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(),
+ &PageController::raiseMainWindow);
+ connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(),
+ &ConnectionController::openConnection);
+ connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(),
+ &ConnectionController::closeConnection);
+ connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(),
+ &NotificationHandler::onTranslationsUpdated);
+
+ m_engine->load(url);
+ m_systemController->setQmlRoot(m_engine->rootObjects().value(0));
if (m_settings->isSaveLogs()) {
if (!Logger::init()) {
@@ -124,19 +152,20 @@ void AmneziaApplication::init()
}
#ifdef Q_OS_WIN
- if (m_parser.isSet("a")) m_uiLogic->showOnStartup();
- else emit m_uiLogic->show();
+ if (m_parser.isSet("a"))
+ m_pageController->showOnStartup();
+ else
+ emit m_pageController->raiseMainWindow();
#else
- m_uiLogic->showOnStartup();
+ m_pageController->showOnStartup();
#endif
- // TODO - fix
+ // TODO - fix
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
if (isPrimary()) {
- QObject::connect(this, &SingleApplication::instanceStarted, m_uiLogic, [this](){
+ QObject::connect(this, &SingleApplication::instanceStarted, m_pageController.get(), [this]() {
qDebug() << "Secondary instance started, showing this window instead";
- emit m_uiLogic->show();
- emit m_uiLogic->raise();
+ emit m_pageController->raiseMainWindow();
});
}
#endif
@@ -144,7 +173,7 @@ void AmneziaApplication::init()
// Android TextField clipboard workaround
// https://bugreports.qt.io/browse/QTBUG-113461
#ifdef Q_OS_ANDROID
- QObject::connect(qApp, &QApplication::applicationStateChanged, [](Qt::ApplicationState state) {
+ QObject::connect(qApp, &QGuiApplication::applicationStateChanged, [](Qt::ApplicationState state) {
if (state == Qt::ApplicationActive) {
if (qApp->clipboard()->mimeData()->formats().contains("text/html")) {
QTextDocument doc;
@@ -158,55 +187,64 @@ void AmneziaApplication::init()
void AmneziaApplication::registerTypes()
{
- qRegisterMetaType("VpnProtocol::VpnConnectionState");
qRegisterMetaType("ServerCredentials");
qRegisterMetaType("DockerContainer");
qRegisterMetaType("TransportProto");
qRegisterMetaType("Proto");
qRegisterMetaType("ServiceType");
- qRegisterMetaType("Page");
- qRegisterMetaType("ConnectionState");
- qRegisterMetaType("PageProtocolLogicBase *");
-
-
- declareQmlPageEnum();
declareQmlProtocolEnum();
declareQmlContainerEnum();
- qmlRegisterType("PageType", 1, 0, "PageType");
qmlRegisterType("QRCodeReader", 1, 0, "QRCodeReader");
- m_containerProps = new ContainerProps;
- qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", m_containerProps);
+ m_containerProps.reset(new ContainerProps());
+ qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", m_containerProps.get());
- m_protocolProps = new ProtocolProps;
- qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", m_protocolProps);
+ m_protocolProps.reset(new ProtocolProps());
+ qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", m_protocolProps.get());
+
+ qmlRegisterSingletonType(QUrl("qrc:/ui/qml/Filters/ContainersModelFilters.qml"), "ContainersModelFilters", 1, 0,
+ "ContainersModelFilters");
+
+ //
+ Vpn::declareQmlVpnConnectionStateEnum();
+ PageLoader::declareQmlPageEnum();
}
void AmneziaApplication::loadFonts()
{
QQuickStyle::setStyle("Basic");
- QFontDatabase::addApplicationFont(":/fonts/Lato-Black.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-BlackItalic.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-Bold.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-BoldItalic.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-Italic.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-Light.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-LightItalic.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-Regular.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-Thin.ttf");
- QFontDatabase::addApplicationFont(":/fonts/Lato-ThinItalic.ttf");
+ QFontDatabase::addApplicationFont(":/fonts/pt-root-ui_vf.ttf");
}
void AmneziaApplication::loadTranslator()
{
- m_translator = new QTranslator;
- if (m_translator->load(QLocale(), QString("amneziavpn"), QLatin1String("_"), QLatin1String(":/translations"))) {
- installTranslator(m_translator);
+ auto locale = m_settings->getAppLanguage();
+ m_translator.reset(new QTranslator());
+ updateTranslator(locale);
+}
+
+void AmneziaApplication::updateTranslator(const QLocale &locale)
+{
+ if (!m_translator->isEmpty()) {
+ QCoreApplication::removeTranslator(m_translator.get());
}
+
+ QString strFileName = QString(":/translations/amneziavpn") + QLatin1String("_") + locale.name() + ".qm";
+ if (m_translator->load(strFileName)) {
+ if (QCoreApplication::installTranslator(m_translator.get())) {
+ m_settings->setAppLanguage(locale);
+ }
+ } else {
+ m_settings->setAppLanguage(QLocale::English);
+ }
+
+ m_engine->retranslate();
+
+ emit translationsUpdated();
}
bool AmneziaApplication::parseCommands()
@@ -215,19 +253,17 @@ bool AmneziaApplication::parseCommands()
m_parser.addHelpOption();
m_parser.addVersionOption();
- QCommandLineOption c_autostart {{"a", "autostart"}, "System autostart"};
+ QCommandLineOption c_autostart { { "a", "autostart" }, "System autostart" };
m_parser.addOption(c_autostart);
- QCommandLineOption c_cleanup {{"c", "cleanup"}, "Cleanup logs"};
+ QCommandLineOption c_cleanup { { "c", "cleanup" }, "Cleanup logs" };
m_parser.addOption(c_cleanup);
m_parser.process(*this);
if (m_parser.isSet(c_cleanup)) {
Logger::cleanUp();
- QTimer::singleShot(100, this, [this]{
- quit();
- });
+ QTimer::singleShot(100, this, [this] { quit(); });
exec();
return false;
}
@@ -239,3 +275,100 @@ QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
return m_engine;
}
+void AmneziaApplication::initModels()
+{
+ m_containersModel.reset(new ContainersModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
+ connect(m_vpnConnection.get(), &VpnConnection::newVpnConfigurationCreated, m_containersModel.get(),
+ &ContainersModel::updateContainersConfig);
+
+ m_serversModel.reset(new ServersModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
+ connect(m_serversModel.get(), &ServersModel::currentlyProcessedServerIndexChanged, m_containersModel.get(),
+ &ContainersModel::setCurrentlyProcessedServerIndex);
+ connect(m_serversModel.get(), &ServersModel::defaultServerIndexChanged, m_containersModel.get(),
+ &ContainersModel::setCurrentlyProcessedServerIndex);
+
+ m_languageModel.reset(new LanguageModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
+ connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &AmneziaApplication::updateTranslator);
+ connect(this, &AmneziaApplication::translationsUpdated, m_languageModel.get(), &LanguageModel::translationsUpdated);
+
+ m_sitesModel.reset(new SitesModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("SitesModel", m_sitesModel.get());
+ connect(m_containersModel.get(), &ContainersModel::defaultContainerChanged, this, [this]() {
+ if ((m_containersModel->getDefaultContainer() == DockerContainer::WireGuard
+ || m_containersModel->getDefaultContainer() == DockerContainer::Awg)
+ && m_sitesModel->isSplitTunnelingEnabled()) {
+ m_sitesModel->toggleSplitTunneling(false);
+ emit m_pageController->showNotificationMessage(
+ tr("Split tunneling for %1 is not implemented, the option was disabled")
+ .arg(ContainerProps::containerHumanNames().value(m_containersModel->getDefaultContainer())));
+ }
+ });
+
+ m_protocolsModel.reset(new ProtocolsModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get());
+
+ m_openVpnConfigModel.reset(new OpenVpnConfigModel(this));
+ m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get());
+
+ m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this));
+ m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get());
+
+ m_cloakConfigModel.reset(new CloakConfigModel(this));
+ m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get());
+
+ m_wireGuardConfigModel.reset(new WireGuardConfigModel(this));
+ m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireGuardConfigModel.get());
+
+ m_awgConfigModel.reset(new AwgConfigModel(this));
+ m_engine->rootContext()->setContextProperty("AwgConfigModel", m_awgConfigModel.get());
+
+#ifdef Q_OS_WINDOWS
+ m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this));
+ m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get());
+#endif
+
+ m_sftpConfigModel.reset(new SftpConfigModel(this));
+ m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get());
+}
+
+void AmneziaApplication::initControllers()
+{
+ m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_vpnConnection));
+ m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
+
+ connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(),
+ &ConnectionController::onTranslationsUpdated);
+
+ m_pageController.reset(new PageController(m_serversModel, m_settings));
+ m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
+
+ m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_settings));
+ m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());
+ connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(),
+ &PageController::showPassphraseRequestDrawer);
+ connect(m_pageController.get(), &PageController::passphraseRequestDrawerClosed, m_installController.get(),
+ &InstallController::setEncryptedPassphrase);
+ connect(m_installController.get(), &InstallController::currentContainerUpdated, m_connectionController.get(),
+ &ConnectionController::onCurrentContainerUpdated);
+
+ m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
+ m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
+
+ m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_settings, m_configurator));
+ m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
+
+ m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_settings));
+ m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
+ if (m_settingsController->isAutoStartEnabled() && m_serversModel->getDefaultServerIndex() >= 0) {
+ QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); });
+ }
+
+ m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel));
+ m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get());
+
+ m_systemController.reset(new SystemController(m_settings));
+ m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get());
+}
diff --git a/client/amnezia_application.h b/client/amnezia_application.h
index 1ac6e772..32300421 100644
--- a/client/amnezia_application.h
+++ b/client/amnezia_application.h
@@ -1,27 +1,53 @@
#ifndef AMNEZIA_APPLICATION_H
#define AMNEZIA_APPLICATION_H
-#include
-#include
-
#include
#include
#include
+#include
+#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
+ #include
+#else
+ #include
+#endif
#include "settings.h"
+#include "vpnconnection.h"
-#include "ui/uilogic.h"
#include "configurators/vpn_configurator.h"
+#include "ui/controllers/connectionController.h"
+#include "ui/controllers/exportController.h"
+#include "ui/controllers/importController.h"
+#include "ui/controllers/installController.h"
+#include "ui/controllers/pageController.h"
+#include "ui/controllers/settingsController.h"
+#include "ui/controllers/sitesController.h"
+#include "ui/controllers/systemController.h"
+#include "ui/models/containers_model.h"
+#include "ui/models/languageModel.h"
+#include "ui/models/protocols/cloakConfigModel.h"
+#include "ui/notificationhandler.h"
+#ifdef Q_OS_WINDOWS
+ #include "ui/models/protocols/ikev2ConfigModel.h"
+#endif
+#include "ui/models/protocols/awgConfigModel.h"
+#include "ui/models/protocols/openvpnConfigModel.h"
+#include "ui/models/protocols/shadowsocksConfigModel.h"
+#include "ui/models/protocols/wireguardConfigModel.h"
+#include "ui/models/protocols_model.h"
+#include "ui/models/servers_model.h"
+#include "ui/models/services/sftpConfigModel.h"
+#include "ui/models/sites_model.h"
+
#define amnApp (static_cast(QCoreApplication::instance()))
-
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
- #define AMNEZIA_BASE_CLASS QApplication
+ #define AMNEZIA_BASE_CLASS QGuiApplication
#else
- #define AMNEZIA_BASE_CLASS SingleApplication
- #define QAPPLICATION_CLASS QApplication
- #include "singleapplication.h"
+ #define AMNEZIA_BASE_CLASS SingleApplication
+ #define QAPPLICATION_CLASS QApplication
+ #include "singleapplication.h"
#endif
class AmneziaApplication : public AMNEZIA_BASE_CLASS
@@ -32,7 +58,8 @@ public:
AmneziaApplication(int &argc, char *argv[]);
#else
AmneziaApplication(int &argc, char *argv[], bool allowSecondary = false,
- SingleApplication::Options options = SingleApplication::User, int timeout = 1000, const QString &userData = {} );
+ SingleApplication::Options options = SingleApplication::User, int timeout = 1000,
+ const QString &userData = {});
#endif
virtual ~AmneziaApplication();
@@ -40,22 +67,57 @@ public:
void registerTypes();
void loadFonts();
void loadTranslator();
+ void updateTranslator(const QLocale &locale);
bool parseCommands();
QQmlApplicationEngine *qmlEngine() const;
+signals:
+ void translationsUpdated();
+
private:
+ void initModels();
+ void initControllers();
+
QQmlApplicationEngine *m_engine {};
- UiLogic *m_uiLogic {};
std::shared_ptr m_settings;
std::shared_ptr m_configurator;
- ContainerProps* m_containerProps {};
- ProtocolProps* m_protocolProps {};
+ QSharedPointer m_containerProps;
+ QSharedPointer m_protocolProps;
- QTranslator* m_translator;
+ QSharedPointer m_translator;
QCommandLineParser m_parser;
+ QSharedPointer m_containersModel;
+ QSharedPointer m_serversModel;
+ QSharedPointer m_languageModel;
+ QSharedPointer m_protocolsModel;
+ QSharedPointer m_sitesModel;
+
+ QScopedPointer m_openVpnConfigModel;
+ QScopedPointer m_shadowSocksConfigModel;
+ QScopedPointer m_cloakConfigModel;
+ QScopedPointer m_wireGuardConfigModel;
+ QScopedPointer m_awgConfigModel;
+#ifdef Q_OS_WINDOWS
+ QScopedPointer m_ikev2ConfigModel;
+#endif
+
+ QScopedPointer m_sftpConfigModel;
+
+ QSharedPointer m_vpnConnection;
+ QThread m_vpnConnectionThread;
+ QScopedPointer m_notificationHandler;
+
+ QScopedPointer m_connectionController;
+ QScopedPointer m_pageController;
+ QScopedPointer m_installController;
+ QScopedPointer m_importController;
+ QScopedPointer m_exportController;
+ QScopedPointer m_settingsController;
+ QScopedPointer m_sitesController;
+ QScopedPointer m_systemController;
};
#endif // AMNEZIA_APPLICATION_H
diff --git a/client/android/AndroidManifest.xml b/client/android/AndroidManifest.xml
index bf431ec6..1115b74d 100644
--- a/client/android/AndroidManifest.xml
+++ b/client/android/AndroidManifest.xml
@@ -36,7 +36,8 @@
android:requestLegacyExternalStorage="true"
android:allowNativeHeapPointerTagging="false"
android:theme="@style/Theme.AppCompat.NoActionBar"
- android:icon="@drawable/icon">
+ android:icon="@drawable/icon"
+ android:roundIcon="@drawable/icon_round">
diff --git a/client/android/build.gradle b/client/android/build.gradle
index cfc53460..a6b3f651 100644
--- a/client/android/build.gradle
+++ b/client/android/build.gradle
@@ -138,8 +138,8 @@ android {
resConfig "en"
minSdkVersion = 24
targetSdkVersion = 34
- versionCode 32 // Change to a higher number
- versionName "3.0.9" // Change to a higher number
+ versionCode 37 // Change to a higher number
+ versionName "4.0.8" // Change to a higher number
javaCompileOptions.annotationProcessorOptions.arguments = [
"room.schemaLocation": "${qtAndroidDir}/schemas".toString()
diff --git a/client/android/res/drawable-hdpi/icon_round.png b/client/android/res/drawable-hdpi/icon_round.png
new file mode 100644
index 00000000..418a71cc
Binary files /dev/null and b/client/android/res/drawable-hdpi/icon_round.png differ
diff --git a/client/android/res/drawable-ldpi/icon_round.png b/client/android/res/drawable-ldpi/icon_round.png
new file mode 100644
index 00000000..371994ed
Binary files /dev/null and b/client/android/res/drawable-ldpi/icon_round.png differ
diff --git a/client/android/res/drawable-mdpi/icon_round.png b/client/android/res/drawable-mdpi/icon_round.png
new file mode 100644
index 00000000..0ed71d4c
Binary files /dev/null and b/client/android/res/drawable-mdpi/icon_round.png differ
diff --git a/client/android/res/drawable-xhdpi/icon_round.png b/client/android/res/drawable-xhdpi/icon_round.png
new file mode 100644
index 00000000..a3e18823
Binary files /dev/null and b/client/android/res/drawable-xhdpi/icon_round.png differ
diff --git a/client/android/res/drawable-xxhdpi/icon_round.png b/client/android/res/drawable-xxhdpi/icon_round.png
new file mode 100644
index 00000000..ca2a6362
Binary files /dev/null and b/client/android/res/drawable-xxhdpi/icon_round.png differ
diff --git a/client/android/res/drawable-xxxhdpi/icon_round.png b/client/android/res/drawable-xxxhdpi/icon_round.png
new file mode 100644
index 00000000..b2b33777
Binary files /dev/null and b/client/android/res/drawable-xxxhdpi/icon_round.png differ
diff --git a/client/android/src/com/wireguard/config/BadConfigException.java b/client/android/src/com/wireguard/config/BadConfigException.java
index 33910501..af909b0d 100644
--- a/client/android/src/com/wireguard/config/BadConfigException.java
+++ b/client/android/src/com/wireguard/config/BadConfigException.java
@@ -70,6 +70,15 @@ public class BadConfigException extends Exception {
EXCLUDED_APPLICATIONS("ExcludedApplications"),
INCLUDED_APPLICATIONS("IncludedApplications"),
LISTEN_PORT("ListenPort"),
+ JC("Jc"),
+ JMIN("Jmin"),
+ JMAX("Jmax"),
+ S1("S1"),
+ S2("S2"),
+ H1("H1"),
+ H2("H2"),
+ H3("H3"),
+ H4("H4"),
MTU("MTU"),
PERSISTENT_KEEPALIVE("PersistentKeepalive"),
PRE_SHARED_KEY("PresharedKey"),
diff --git a/client/android/src/com/wireguard/config/Interface.java b/client/android/src/com/wireguard/config/Interface.java
index 2594d701..4b561680 100644
--- a/client/android/src/com/wireguard/config/Interface.java
+++ b/client/android/src/com/wireguard/config/Interface.java
@@ -44,6 +44,15 @@ public final class Interface {
private final KeyPair keyPair;
private final Optional listenPort;
private final Optional mtu;
+ private final Optional jc;
+ private final Optional jmin;
+ private final Optional jmax;
+ private final Optional s1;
+ private final Optional s2;
+ private final Optional h1;
+ private final Optional h2;
+ private final Optional h3;
+ private final Optional h4;
private Interface(final Builder builder) {
// Defensively copy to ensure immutability even if the Builder is reused.
@@ -56,6 +65,15 @@ public final class Interface {
keyPair = Objects.requireNonNull(builder.keyPair, "Interfaces must have a private key");
listenPort = builder.listenPort;
mtu = builder.mtu;
+ jc = builder.jc;
+ jmax = builder.jmax;
+ jmin = builder.jmin;
+ s1 = builder.s1;
+ s2 = builder.s2;
+ h1 = builder.h1;
+ h2 = builder.h2;
+ h3 = builder.h3;
+ h4 = builder.h4;
}
/**
@@ -95,6 +113,33 @@ public final class Interface {
case "privatekey":
builder.parsePrivateKey(attribute.getValue());
break;
+ case "jc":
+ builder.parseJc(attribute.getValue());
+ break;
+ case "jmin":
+ builder.parseJmin(attribute.getValue());
+ break;
+ case "jmax":
+ builder.parseJmax(attribute.getValue());
+ break;
+ case "s1":
+ builder.parseS1(attribute.getValue());
+ break;
+ case "s2":
+ builder.parseS2(attribute.getValue());
+ break;
+ case "h1":
+ builder.parseH1(attribute.getValue());
+ break;
+ case "h2":
+ builder.parseH2(attribute.getValue());
+ break;
+ case "h3":
+ builder.parseH3(attribute.getValue());
+ break;
+ case "h4":
+ builder.parseH4(attribute.getValue());
+ break;
default:
throw new BadConfigException(
Section.INTERFACE, Location.TOP_LEVEL, Reason.UNKNOWN_ATTRIBUTE, attribute.getKey());
@@ -111,7 +156,9 @@ public final class Interface {
return addresses.equals(other.addresses) && dnsServers.equals(other.dnsServers)
&& excludedApplications.equals(other.excludedApplications)
&& includedApplications.equals(other.includedApplications) && keyPair.equals(other.keyPair)
- && listenPort.equals(other.listenPort) && mtu.equals(other.mtu);
+ && listenPort.equals(other.listenPort) && mtu.equals(other.mtu) && jc.equals(other.jc) && jmin.equals(other.jmin)
+ && jmax.equals(other.jmax) && s1.equals(other.s1) && s2.equals(other.s2) && h1.equals(other.h1) && h2.equals(other.h2)
+ && h3.equals(other.h3) && h4.equals(other.h4);
}
/**
@@ -180,6 +227,42 @@ public final class Interface {
public Optional getMtu() {
return mtu;
}
+
+ public Optional getJc() {
+ return jc;
+ }
+
+ public Optional getJmin() {
+ return jmin;
+ }
+
+ public Optional getJmax() {
+ return jmax;
+ }
+
+ public Optional getS1() {
+ return s1;
+ }
+
+ public Optional getS2() {
+ return s2;
+ }
+
+ public Optional getH1() {
+ return h1;
+ }
+
+ public Optional getH2() {
+ return h2;
+ }
+
+ public Optional getH3() {
+ return h3;
+ }
+
+ public Optional getH4() {
+ return h4;
+ }
@Override
public int hashCode() {
@@ -191,6 +274,15 @@ public final class Interface {
hash = 31 * hash + keyPair.hashCode();
hash = 31 * hash + listenPort.hashCode();
hash = 31 * hash + mtu.hashCode();
+ hash = 31 * hash + jc.hashCode();
+ hash = 31 * hash + jmin.hashCode();
+ hash = 31 * hash + jmax.hashCode();
+ hash = 31 * hash + s1.hashCode();
+ hash = 31 * hash + s2.hashCode();
+ hash = 31 * hash + h1.hashCode();
+ hash = 31 * hash + h2.hashCode();
+ hash = 31 * hash + h3.hashCode();
+ hash = 31 * hash + h4.hashCode();
return hash;
}
@@ -234,6 +326,19 @@ public final class Interface {
.append('\n');
listenPort.ifPresent(lp -> sb.append("ListenPort = ").append(lp).append('\n'));
mtu.ifPresent(m -> sb.append("MTU = ").append(m).append('\n'));
+
+ jc.ifPresent(t_jc -> sb.append("Jc = ").append(t_jc).append('\n'));
+ jmin.ifPresent(t_jmin -> sb.append("Jmin = ").append(t_jmin).append('\n'));
+ jmax.ifPresent(t_jmax -> sb.append("Jmax = ").append(t_jmax).append('\n'));
+
+ s1.ifPresent(t_s1 -> sb.append("S1 = ").append(t_s1).append('\n'));
+ s2.ifPresent(t_s2 -> sb.append("S2 = ").append(t_s2).append('\n'));
+
+ h1.ifPresent(t_h1 -> sb.append("H1 = ").append(t_h1).append('\n'));
+ h2.ifPresent(t_h2 -> sb.append("H2 = ").append(t_h2).append('\n'));
+ h3.ifPresent(t_h3 -> sb.append("H3 = ").append(t_h3).append('\n'));
+ h4.ifPresent(t_h4 -> sb.append("H4 = ").append(t_h4).append('\n'));
+
sb.append("PrivateKey = ").append(keyPair.getPrivateKey().toBase64()).append('\n');
return sb.toString();
}
@@ -248,6 +353,18 @@ public final class Interface {
final StringBuilder sb = new StringBuilder();
sb.append("private_key=").append(keyPair.getPrivateKey().toHex()).append('\n');
listenPort.ifPresent(lp -> sb.append("listen_port=").append(lp).append('\n'));
+
+ jc.ifPresent(t_jc -> sb.append("jc=").append(t_jc).append('\n'));
+ jmin.ifPresent(t_jmin -> sb.append("jmin=").append(t_jmin).append('\n'));
+ jmax.ifPresent(t_jmax -> sb.append("jmax=").append(t_jmax).append('\n'));
+
+ s1.ifPresent(t_s1 -> sb.append("s1=").append(t_s1).append('\n'));
+ s2.ifPresent(t_s2 -> sb.append("s2=").append(t_s2).append('\n'));
+
+ h1.ifPresent(t_h1 -> sb.append("h1=").append(t_h1).append('\n'));
+ h2.ifPresent(t_h2 -> sb.append("h2=").append(t_h2).append('\n'));
+ h3.ifPresent(t_h3 -> sb.append("h3=").append(t_h3).append('\n'));
+ h4.ifPresent(t_h4 -> sb.append("h4=").append(t_h4).append('\n'));
return sb.toString();
}
@@ -267,6 +384,17 @@ public final class Interface {
private Optional listenPort = Optional.empty();
// Defaults to not present.
private Optional mtu = Optional.empty();
+ private Optional jc = Optional.empty();
+ private Optional jmin = Optional.empty();
+ private Optional jmax = Optional.empty();
+
+ private Optional s1 = Optional.empty();
+ private Optional s2 = Optional.empty();
+
+ private Optional h1 = Optional.empty();
+ private Optional h2 = Optional.empty();
+ private Optional h3 = Optional.empty();
+ private Optional h4 = Optional.empty();
public Builder addAddress(final InetNetwork address) {
addresses.add(address);
@@ -362,6 +490,78 @@ public final class Interface {
}
}
+ public Builder parseJc(final String jc) throws BadConfigException {
+ try {
+ return setJc(Integer.parseInt(jc));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.JC, jc, e);
+ }
+ }
+
+ public Builder parseJmax(final String jmax) throws BadConfigException {
+ try {
+ return setJmax(Integer.parseInt(jmax));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.JMAX, jmax, e);
+ }
+ }
+
+ public Builder parseJmin(final String jmin) throws BadConfigException {
+ try {
+ return setJmin(Integer.parseInt(jmin));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.JMIN, jmin, e);
+ }
+ }
+
+ public Builder parseS1(final String s1) throws BadConfigException {
+ try {
+ return setS1(Integer.parseInt(s1));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.S1, s1, e);
+ }
+ }
+
+ public Builder parseS2(final String s2) throws BadConfigException {
+ try {
+ return setS2(Integer.parseInt(s2));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.S2, s2, e);
+ }
+ }
+
+ public Builder parseH1(final String h1) throws BadConfigException {
+ try {
+ return setH1(Long.parseLong(h1));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.H1, h1, e);
+ }
+ }
+
+ public Builder parseH2(final String h2) throws BadConfigException {
+ try {
+ return setH2(Long.parseLong(h2));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.H2, h2, e);
+ }
+ }
+
+ public Builder parseH3(final String h3) throws BadConfigException {
+ try {
+ return setH3(Long.parseLong(h3));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.H3, h3, e);
+ }
+ }
+
+ public Builder parseH4(final String h4) throws BadConfigException {
+ try {
+ return setH4(Long.parseLong(h4));
+ } catch (final NumberFormatException e) {
+ throw new BadConfigException(Section.INTERFACE, Location.H4, h4, e);
+ }
+ }
+
public Builder parsePrivateKey(final String privateKey) throws BadConfigException {
try {
return setKeyPair(new KeyPair(Key.fromBase64(privateKey)));
@@ -386,9 +586,81 @@ public final class Interface {
public Builder setMtu(final int mtu) throws BadConfigException {
if (mtu < 0)
throw new BadConfigException(
- Section.INTERFACE, Location.LISTEN_PORT, Reason.INVALID_VALUE, String.valueOf(mtu));
+ Section.INTERFACE, Location.MTU, Reason.INVALID_VALUE, String.valueOf(mtu));
this.mtu = mtu == 0 ? Optional.empty() : Optional.of(mtu);
return this;
}
+
+ public Builder setJc(final int jc) throws BadConfigException {
+ if (jc < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.JC, Reason.INVALID_VALUE, String.valueOf(jc));
+ this.jc = Optional.of(jc);
+ return this;
+ }
+
+ public Builder setJmin(final int jmin) throws BadConfigException {
+ if (jmin < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.JMIN, Reason.INVALID_VALUE, String.valueOf(jmin));
+ this.jmin = Optional.of(jmin);
+ return this;
+ }
+
+ public Builder setJmax(final int jmax) throws BadConfigException {
+ if (jmax < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.JMAX, Reason.INVALID_VALUE, String.valueOf(jmax));
+ this.jmax = Optional.of(jmax);
+ return this;
+ }
+
+ public Builder setS1(final int s1) throws BadConfigException {
+ if (s1 < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.S1, Reason.INVALID_VALUE, String.valueOf(s1));
+ this.s1 = Optional.of(s1);
+ return this;
+ }
+
+ public Builder setS2(final int s2) throws BadConfigException {
+ if (s2 < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.S2, Reason.INVALID_VALUE, String.valueOf(s2));
+ this.s2 = Optional.of(s2);
+ return this;
+ }
+
+ public Builder setH1(final long h1) throws BadConfigException {
+ if (h1 < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.H1, Reason.INVALID_VALUE, String.valueOf(h1));
+ this.h1 = Optional.of(h1);
+ return this;
+ }
+
+ public Builder setH2(final long h2) throws BadConfigException {
+ if (h2 < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.H2, Reason.INVALID_VALUE, String.valueOf(h2));
+ this.h2 = Optional.of(h2);
+ return this;
+ }
+
+ public Builder setH3(final long h3) throws BadConfigException {
+ if (h3 < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.H3, Reason.INVALID_VALUE, String.valueOf(h3));
+ this.h3 = Optional.of(h3);
+ return this;
+ }
+
+ public Builder setH4(final long h4) throws BadConfigException {
+ if (h4 < 0)
+ throw new BadConfigException(
+ Section.INTERFACE, Location.H4, Reason.INVALID_VALUE, String.valueOf(h4));
+ this.h4 = Optional.of(h4);
+ return this;
+ }
}
-}
+}
diff --git a/client/android/src/org/amnezia/vpn/VPNService.kt b/client/android/src/org/amnezia/vpn/VPNService.kt
index 082fe412..06f58980 100644
--- a/client/android/src/org/amnezia/vpn/VPNService.kt
+++ b/client/android/src/org/amnezia/vpn/VPNService.kt
@@ -380,7 +380,10 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
mNetworkState.bindNetworkListener()
}
"wireguard" -> {
- startWireGuard()
+ startWireGuard("wireguard")
+ }
+ "awg" -> {
+ startWireGuard("awg")
}
"shadowsocks" -> {
startShadowsocks()
@@ -457,7 +460,8 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
fun turnOff() {
Log.v(tag, "Aman: turnOff....................")
when (mProtocol) {
- "wireguard" -> {
+ "wireguard",
+ "awg" -> {
GoBackend.wgTurnOff(currentTunnelHandle)
}
"cloak",
@@ -559,14 +563,14 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
}
return parseData
}
-
+
/**
* Create a Wireguard [Config] from a [json] string -
* The [json] will be created in AndroidVpnProtocol.cpp
*/
- private fun buildWireguardConfig(obj: JSONObject): Config {
+ private fun buildWireguardConfig(obj: JSONObject, type: String): Config {
val confBuilder = Config.Builder()
- val wireguardConfigData = obj.getJSONObject("wireguard_config_data")
+ val wireguardConfigData = obj.getJSONObject(type)
val config = parseConfigData(wireguardConfigData.getString("config"))
val peerBuilder = Peer.Builder()
val peerConfig = config["Peer"]!!
@@ -599,6 +603,30 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
ifaceConfig["DNS"]!!.split(",").forEach {
ifaceBuilder.addDnsServer(InetNetwork.parse(it.trim()).address)
}
+
+ ifaceBuilder.parsePrivateKey(ifaceConfig["PrivateKey"])
+ if (type == "awg_config_data") {
+ ifaceBuilder.parseJc(ifaceConfig["Jc"])
+ ifaceBuilder.parseJmin(ifaceConfig["Jmin"])
+ ifaceBuilder.parseJmax(ifaceConfig["Jmax"])
+ ifaceBuilder.parseS1(ifaceConfig["S1"])
+ ifaceBuilder.parseS2(ifaceConfig["S2"])
+ ifaceBuilder.parseH1(ifaceConfig["H1"])
+ ifaceBuilder.parseH2(ifaceConfig["H2"])
+ ifaceBuilder.parseH3(ifaceConfig["H3"])
+ ifaceBuilder.parseH4(ifaceConfig["H4"])
+ } else {
+ ifaceBuilder.parseJc("0")
+ ifaceBuilder.parseJmin("0")
+ ifaceBuilder.parseJmax("0")
+ ifaceBuilder.parseS1("0")
+ ifaceBuilder.parseS2("0")
+ ifaceBuilder.parseH1("0")
+ ifaceBuilder.parseH2("0")
+ ifaceBuilder.parseH3("0")
+ ifaceBuilder.parseH4("0")
+
+ }
/*val jExcludedApplication = obj.getJSONArray("excludedApps")
(0 until jExcludedApplication.length()).toList().forEach {
val appName = jExcludedApplication.get(it).toString()
@@ -716,8 +744,8 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
}).start()
}
- private fun startWireGuard() {
- val wireguard_conf = buildWireguardConfig(mConfig!!)
+ private fun startWireGuard(type: String) {
+ val wireguard_conf = buildWireguardConfig(mConfig!!, type + "_config_data")
Log.i(tag, "startWireGuard: wireguard_conf : $wireguard_conf")
if (currentTunnelHandle != -1) {
Log.e(tag, "Tunnel already up")
@@ -728,9 +756,15 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
val builder = Builder()
setupBuilder(wireguard_conf, builder)
builder.setSession("Amnezia")
+
+
builder.establish().use { tun ->
- if (tun == null) return
- currentTunnelHandle = GoBackend.wgTurnOn("Amnezia", tun.detachFd(), wgConfig)
+ if (tun == null) return
+ if (type == "awg"){
+ currentTunnelHandle = GoBackend.wgTurnOn("awg0", tun.detachFd(), wgConfig)
+ } else {
+ currentTunnelHandle = GoBackend.wgTurnOn("amn0", tun.detachFd(), wgConfig)
+ }
}
if (currentTunnelHandle < 0) {
Log.e(tag, "Activation Error Code -> $currentTunnelHandle")
diff --git a/client/cmake/android.cmake b/client/cmake/android.cmake
index dd37e0a6..9440ad10 100644
--- a/client/cmake/android.cmake
+++ b/client/cmake/android.cmake
@@ -10,6 +10,7 @@ set(HEADERS ${HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_notificationhandler.h
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/androidutils.h
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/androidvpnactivity.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/authResultReceiver.h
${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.h
)
@@ -18,6 +19,7 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_notificationhandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/androidutils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/androidvpnactivity.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/authResultReceiver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.cpp
)
diff --git a/client/cmake/ios.cmake b/client/cmake/ios.cmake
index 5dc1b2e7..7aa9f1a9 100644
--- a/client/cmake/ios.cmake
+++ b/client/cmake/ios.cmake
@@ -97,7 +97,7 @@ target_compile_options(${PROJECT} PRIVATE
-DVPN_NE_BUNDLEID=\"${BUILD_IOS_APP_IDENTIFIER}.network-extension\"
)
-set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/wireguard-apple/Sources)
+set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/awg-apple/Sources)
target_sources(${PROJECT} PRIVATE
# ${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/iosvpnprotocol.swift
diff --git a/client/configurators/awg_configurator.cpp b/client/configurators/awg_configurator.cpp
new file mode 100644
index 00000000..c3e42258
--- /dev/null
+++ b/client/configurators/awg_configurator.cpp
@@ -0,0 +1,47 @@
+#include "awg_configurator.h"
+
+#include
+#include
+
+#include "core/servercontroller.h"
+
+AwgConfigurator::AwgConfigurator(std::shared_ptr settings, QObject *parent)
+ : WireguardConfigurator(settings, true, parent)
+{
+}
+
+QString AwgConfigurator::genAwgConfig(const ServerCredentials &credentials,
+ DockerContainer container,
+ const QJsonObject &containerConfig, ErrorCode *errorCode)
+{
+ QString config = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, errorCode);
+
+ QJsonObject jsonConfig = QJsonDocument::fromJson(config.toUtf8()).object();
+ QString awgConfig = jsonConfig.value(config_key::config).toString();
+
+ QMap configMap;
+ auto configLines = awgConfig.split("\n");
+ for (auto &line : configLines) {
+ auto trimmedLine = line.trimmed();
+ if (trimmedLine.startsWith("[") && trimmedLine.endsWith("]")) {
+ continue;
+ } else {
+ QStringList parts = trimmedLine.split(" = ");
+ if (parts.count() == 2) {
+ configMap.insert(parts[0].trimmed(), parts[1].trimmed());
+ }
+ }
+ }
+
+ jsonConfig[config_key::junkPacketCount] = configMap.value(config_key::junkPacketCount);
+ jsonConfig[config_key::junkPacketMinSize] = configMap.value(config_key::junkPacketMinSize);
+ jsonConfig[config_key::junkPacketMaxSize] = configMap.value(config_key::junkPacketMaxSize);
+ jsonConfig[config_key::initPacketJunkSize] = configMap.value(config_key::initPacketJunkSize);
+ jsonConfig[config_key::responsePacketJunkSize] = configMap.value(config_key::responsePacketJunkSize);
+ jsonConfig[config_key::initPacketMagicHeader] = configMap.value(config_key::initPacketMagicHeader);
+ jsonConfig[config_key::responsePacketMagicHeader] = configMap.value(config_key::responsePacketMagicHeader);
+ jsonConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader);
+ jsonConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader);
+
+ return QJsonDocument(jsonConfig).toJson();
+}
diff --git a/client/configurators/awg_configurator.h b/client/configurators/awg_configurator.h
new file mode 100644
index 00000000..cf0f2cae
--- /dev/null
+++ b/client/configurators/awg_configurator.h
@@ -0,0 +1,18 @@
+#ifndef AWGCONFIGURATOR_H
+#define AWGCONFIGURATOR_H
+
+#include
+
+#include "wireguard_configurator.h"
+
+class AwgConfigurator : public WireguardConfigurator
+{
+ Q_OBJECT
+public:
+ AwgConfigurator(std::shared_ptr settings, QObject *parent = nullptr);
+
+ QString genAwgConfig(const ServerCredentials &credentials, DockerContainer container,
+ const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
+};
+
+#endif // AWGCONFIGURATOR_H
diff --git a/client/configurators/ikev2_configurator.cpp b/client/configurators/ikev2_configurator.cpp
index 7ed83da1..4ca0e5da 100644
--- a/client/configurators/ikev2_configurator.cpp
+++ b/client/configurators/ikev2_configurator.cpp
@@ -1,28 +1,26 @@
#include "ikev2_configurator.h"
-#include
+
+#include
+#include
#include
#include
#include
-#include
#include
-#include
#include
#include "containers/containers_defs.h"
-#include "core/server_defs.h"
#include "core/scripts_registry.h"
-#include "utilities.h"
+#include "core/server_defs.h"
#include "core/servercontroller.h"
+#include "utilities.h"
-
-Ikev2Configurator::Ikev2Configurator(std::shared_ptr settings, QObject *parent):
- ConfiguratorBase(settings, parent)
+Ikev2Configurator::Ikev2Configurator(std::shared_ptr settings, QObject *parent)
+ : ConfiguratorBase(settings, parent)
{
-
}
Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials,
- DockerContainer container, ErrorCode *errorCode)
+ DockerContainer container, ErrorCode *errorCode)
{
Ikev2Configurator::ConnectionData connData;
connData.host = credentials.hostName;
@@ -32,26 +30,27 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
QString certFileName = "/opt/amnezia/ikev2/clients/" + connData.clientId + ".p12";
- QString scriptCreateCert = QString("certutil -z <(head -c 1024 /dev/urandom) "\
- "-S -c \"IKEv2 VPN CA\" -n \"%1\" "\
- "-s \"O=IKEv2 VPN,CN=%1\" "\
- "-k rsa -g 3072 -v 120 "\
- "-d sql:/etc/ipsec.d -t \",,\" "\
- "--keyUsage digitalSignature,keyEncipherment "\
- "--extKeyUsage serverAuth,clientAuth -8 \"%1\"")
- .arg(connData.clientId);
+ QString scriptCreateCert = QString("certutil -z <(head -c 1024 /dev/urandom) "
+ "-S -c \"IKEv2 VPN CA\" -n \"%1\" "
+ "-s \"O=IKEv2 VPN,CN=%1\" "
+ "-k rsa -g 3072 -v 120 "
+ "-d sql:/etc/ipsec.d -t \",,\" "
+ "--keyUsage digitalSignature,keyEncipherment "
+ "--extKeyUsage serverAuth,clientAuth -8 \"%1\"")
+ .arg(connData.clientId);
ServerController serverController(m_settings);
ErrorCode e = serverController.runContainerScript(credentials, container, scriptCreateCert);
QString scriptExportCert = QString("pk12util -W \"%1\" -d sql:/etc/ipsec.d -n \"%2\" -o \"%3\"")
- .arg(connData.password)
- .arg(connData.clientId)
- .arg(certFileName);
+ .arg(connData.password)
+ .arg(connData.clientId)
+ .arg(certFileName);
e = serverController.runContainerScript(credentials, container, scriptExportCert);
connData.clientCert = serverController.getTextFileFromContainer(container, credentials, certFileName, &e);
- connData.caCert = serverController.getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", &e);
+ connData.caCert =
+ serverController.getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", &e);
qDebug() << "Ikev2Configurator::ConnectionData client cert size:" << connData.clientCert.size();
qDebug() << "Ikev2Configurator::ConnectionData ca cert size:" << connData.caCert.size();
@@ -59,8 +58,8 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
return connData;
}
-QString Ikev2Configurator::genIkev2Config(const ServerCredentials &credentials,
- DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
+QString Ikev2Configurator::genIkev2Config(const ServerCredentials &credentials, DockerContainer container,
+ const QJsonObject &containerConfig, ErrorCode *errorCode)
{
Q_UNUSED(containerConfig)
@@ -120,4 +119,3 @@ QString Ikev2Configurator::genStrongSwanConfig(const ConnectionData &connData)
return config;
}
-
diff --git a/client/configurators/openvpn_configurator.cpp b/client/configurators/openvpn_configurator.cpp
index 3bc6676a..a62bdd9c 100644
--- a/client/configurators/openvpn_configurator.cpp
+++ b/client/configurators/openvpn_configurator.cpp
@@ -1,82 +1,94 @@
#include "openvpn_configurator.h"
-#include
+
+#include
+#include
+#include
#include
#include
#include
-#include
#include
-#include
-#include
+#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
+ #include
+#else
+ #include
+#endif
#include "containers/containers_defs.h"
+#include "core/scripts_registry.h"
#include "core/server_defs.h"
#include "core/servercontroller.h"
-#include "core/scripts_registry.h"
-#include "utilities.h"
#include "settings.h"
+#include "utilities.h"
+#include
#include
#include
-#include
-OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr settings, QObject *parent):
- ConfiguratorBase(settings, parent)
+OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr settings, QObject *parent)
+ : ConfiguratorBase(settings, parent)
{
-
}
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials,
- DockerContainer container, ErrorCode *errorCode)
+ DockerContainer container,
+ ErrorCode *errorCode)
{
OpenVpnConfigurator::ConnectionData connData = OpenVpnConfigurator::createCertRequest();
connData.host = credentials.hostName;
if (connData.privKey.isEmpty() || connData.request.isEmpty()) {
- if (errorCode) *errorCode = ErrorCode::OpenSslFailed;
+ if (errorCode)
+ *errorCode = ErrorCode::OpenSslFailed;
return connData;
}
- QString reqFileName = QString("%1/%2.req").
- arg(amnezia::protocols::openvpn::clientsDirPath).
- arg(connData.clientId);
+ QString reqFileName = QString("%1/%2.req").arg(amnezia::protocols::openvpn::clientsDirPath).arg(connData.clientId);
ServerController serverController(m_settings);
ErrorCode e = serverController.uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
if (e) {
- if (errorCode) *errorCode = e;
+ if (errorCode)
+ *errorCode = e;
return connData;
}
e = signCert(container, credentials, connData.clientId);
if (e) {
- if (errorCode) *errorCode = e;
+ if (errorCode)
+ *errorCode = e;
return connData;
}
- connData.caCert = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::caCertPath, &e);
- connData.clientCert = serverController.getTextFileFromContainer(container, credentials,
- QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), &e);
+ connData.caCert = serverController.getTextFileFromContainer(container, credentials,
+ amnezia::protocols::openvpn::caCertPath, &e);
+ connData.clientCert = serverController.getTextFileFromContainer(
+ container, credentials,
+ QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), &e);
if (e) {
- if (errorCode) *errorCode = e;
+ if (errorCode)
+ *errorCode = e;
return connData;
}
- connData.taKey = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath, &e);
+ connData.taKey = serverController.getTextFileFromContainer(container, credentials,
+ amnezia::protocols::openvpn::taKeyPath, &e);
if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) {
- if (errorCode) *errorCode = ErrorCode::SshSftpFailureError;
+ if (errorCode)
+ *errorCode = ErrorCode::SshSftpFailureError;
}
return connData;
}
-QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials,
- DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
+QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
+ const QJsonObject &containerConfig, ErrorCode *errorCode)
{
ServerController serverController(m_settings);
- QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
- serverController.genVarsForScript(credentials, container, containerConfig));
+ QString config =
+ serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
+ serverController.genVarsForScript(credentials, container, containerConfig));
ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode);
if (errorCode && *errorCode) {
@@ -89,8 +101,7 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
if (config.contains("$OPENVPN_TA_KEY")) {
config.replace("$OPENVPN_TA_KEY", connData.taKey);
- }
- else {
+ } else {
config.replace("", "");
config.replace("", "");
}
@@ -133,12 +144,11 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig)
config.replace("block-outside-dns", "");
#endif
-#if (defined (MZ_MACOS) || defined(MZ_LINUX))
- QString dnsConf = QString(
- "\nscript-security 2\n"
- "up %1/update-resolv-conf.sh\n"
- "down %1/update-resolv-conf.sh\n").
- arg(qApp->applicationDirPath());
+#if (defined(MZ_MACOS) || defined(MZ_LINUX))
+ QString dnsConf = QString("\nscript-security 2\n"
+ "up %1/update-resolv-conf.sh\n"
+ "down %1/update-resolv-conf.sh\n")
+ .arg(qApp->applicationDirPath());
config.append(dnsConf);
#endif
@@ -168,23 +178,23 @@ QString OpenVpnConfigurator::processConfigWithExportSettings(QString jsonConfig)
return QJsonDocument(json).toJson();
}
-ErrorCode OpenVpnConfigurator::signCert(DockerContainer container,
- const ServerCredentials &credentials, QString clientId)
+ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId)
{
QString script_import = QString("sudo docker exec -i %1 bash -c \"cd /opt/amnezia/openvpn && "
- "easyrsa import-req %2/%3.req %3\"")
- .arg(ContainerProps::containerToString(container))
- .arg(amnezia::protocols::openvpn::clientsDirPath)
- .arg(clientId);
+ "easyrsa import-req %2/%3.req %3\"")
+ .arg(ContainerProps::containerToString(container))
+ .arg(amnezia::protocols::openvpn::clientsDirPath)
+ .arg(clientId);
QString script_sign = QString("sudo docker exec -i %1 bash -c \"export EASYRSA_BATCH=1; cd /opt/amnezia/openvpn && "
- "easyrsa sign-req client %2\"")
- .arg(ContainerProps::containerToString(container))
- .arg(clientId);
+ "easyrsa sign-req client %2\"")
+ .arg(ContainerProps::containerToString(container))
+ .arg(clientId);
ServerController serverController(m_settings);
- QStringList scriptList {script_import, script_sign};
- QString script = serverController.replaceVars(scriptList.join("\n"), serverController.genVarsForScript(credentials, container));
+ QStringList scriptList { script_import, script_sign };
+ QString script = serverController.replaceVars(scriptList.join("\n"),
+ serverController.genVarsForScript(credentials, container));
return serverController.runScript(credentials, script);
}
@@ -194,18 +204,17 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
ConnectionData connData;
connData.clientId = Utils::getRandomString(32);
- int ret = 0;
- int nVersion = 1;
+ int ret = 0;
+ int nVersion = 1;
QByteArray clientIdUtf8 = connData.clientId.toUtf8();
- EVP_PKEY * pKey = EVP_PKEY_new();
+ EVP_PKEY *pKey = EVP_PKEY_new();
q_check_ptr(pKey);
- RSA * rsa = RSA_generate_key(2048, RSA_F4, nullptr, nullptr);
+ RSA *rsa = RSA_generate_key(2048, RSA_F4, nullptr, nullptr);
q_check_ptr(rsa);
EVP_PKEY_assign_RSA(pKey, rsa);
-
// 2. set version of x509 req
X509_REQ *x509_req = X509_REQ_new();
ret = X509_REQ_set_version(x509_req, nVersion);
@@ -219,16 +228,14 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
// 3. set subject of x509 req
X509_NAME *x509_name = X509_REQ_get_subject_name(x509_req);
- X509_NAME_add_entry_by_txt(x509_name, "C", MBSTRING_ASC,
- (unsigned char *)"ORG", -1, -1, 0);
- X509_NAME_add_entry_by_txt(x509_name, "O", MBSTRING_ASC,
- (unsigned char *)"", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(x509_name, "C", MBSTRING_ASC, (unsigned char *)"ORG", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(x509_name, "O", MBSTRING_ASC, (unsigned char *)"", -1, -1, 0);
X509_NAME_add_entry_by_txt(x509_name, "CN", MBSTRING_ASC,
reinterpret_cast(clientIdUtf8.data()), clientIdUtf8.size(), -1, 0);
// 4. set public key of x509 req
ret = X509_REQ_set_pubkey(x509_req, pKey);
- if (ret != 1){
+ if (ret != 1) {
qWarning() << "Could not set pubkey!";
X509_REQ_free(x509_req);
EVP_PKEY_free(pKey);
@@ -236,8 +243,8 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
}
// 5. set sign key of x509 req
- ret = X509_REQ_sign(x509_req, pKey, EVP_sha256()); // return x509_req->signature->length
- if (ret <= 0){
+ ret = X509_REQ_sign(x509_req, pKey, EVP_sha256()); // return x509_req->signature->length
+ if (ret <= 0) {
qWarning() << "Could not sign request!";
X509_REQ_free(x509_req);
EVP_PKEY_free(pKey);
@@ -245,10 +252,9 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
}
// save private key
- BIO * bp_private = BIO_new(BIO_s_mem());
+ BIO *bp_private = BIO_new(BIO_s_mem());
q_check_ptr(bp_private);
- if (PEM_write_bio_PrivateKey(bp_private, pKey, nullptr, nullptr, 0, nullptr, nullptr) != 1)
- {
+ if (PEM_write_bio_PrivateKey(bp_private, pKey, nullptr, nullptr, 0, nullptr, nullptr) != 1) {
qFatal("PEM_write_bio_PrivateKey");
EVP_PKEY_free(pKey);
BIO_free_all(bp_private);
@@ -256,7 +262,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
return connData;
}
- const char * buffer = nullptr;
+ const char *buffer = nullptr;
size_t size = BIO_get_mem_data(bp_private, &buffer);
q_check_ptr(buffer);
connData.privKey = QByteArray(buffer, size);
@@ -270,7 +276,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
BIO_free_all(bp_private);
// save req
- BIO * bio_req = BIO_new(BIO_s_mem());
+ BIO *bio_req = BIO_new(BIO_s_mem());
PEM_write_bio_X509_REQ(bio_req, x509_req);
BUF_MEM *bio_buf;
@@ -278,7 +284,6 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
connData.request = QByteArray(bio_buf->data, bio_buf->length);
BIO_free(bio_req);
-
EVP_PKEY_free(pKey); // this will also free the rsa key
return connData;
diff --git a/client/configurators/ssh_configurator.cpp b/client/configurators/ssh_configurator.cpp
index e1435bc3..42e7eb47 100644
--- a/client/configurators/ssh_configurator.cpp
+++ b/client/configurators/ssh_configurator.cpp
@@ -1,24 +1,25 @@
#include "ssh_configurator.h"
-#include
+
+#include
+#include
#include
#include
#include
-#include
#include
#include
-#include
-#include
-#include
#include
+#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
+ #include
+#else
+ #include
+#endif
#include "core/server_defs.h"
#include "utilities.h"
-
-SshConfigurator::SshConfigurator(std::shared_ptr settings, QObject *parent):
- ConfiguratorBase(settings, parent)
+SshConfigurator::SshConfigurator(std::shared_ptr settings, QObject *parent)
+ : ConfiguratorBase(settings, parent)
{
-
}
QString SshConfigurator::convertOpenSShKey(const QString &key)
@@ -28,23 +29,30 @@ QString SshConfigurator::convertOpenSShKey(const QString &key)
p.setProcessChannelMode(QProcess::MergedChannels);
QTemporaryFile tmp;
-#ifdef QT_DEBUG
+ #ifdef QT_DEBUG
tmp.setAutoRemove(false);
-#endif
+ #endif
tmp.open();
tmp.write(key.toUtf8());
tmp.close();
// ssh-keygen -p -P "" -N "" -m pem -f id_ssh
-#ifdef Q_OS_WIN
+ #ifdef Q_OS_WIN
p.setProcessEnvironment(prepareEnv());
p.setProgram("cmd.exe");
p.setNativeArguments(QString("/C \"ssh-keygen.exe -p -P \"\" -N \"\" -m pem -f \"%1\"\"").arg(tmp.fileName()));
-#else
+ #else
p.setProgram("ssh-keygen");
- p.setArguments(QStringList() << "-p" << "-P" << "" << "-N" << "" << "-m" << "pem" << "-f" << tmp.fileName());
-#endif
+ p.setArguments(QStringList() << "-p"
+ << "-P"
+ << ""
+ << "-N"
+ << ""
+ << "-m"
+ << "pem"
+ << "-f" << tmp.fileName());
+ #endif
p.start();
p.waitForFinished();
@@ -65,22 +73,21 @@ void SshConfigurator::openSshTerminal(const ServerCredentials &credentials)
QProcess *p = new QProcess();
p->setProcessChannelMode(QProcess::SeparateChannels);
-#ifdef Q_OS_WIN
+ #ifdef Q_OS_WIN
p->setProcessEnvironment(prepareEnv());
p->setProgram(qApp->applicationDirPath() + "\\cygwin\\putty.exe");
- if (credentials.password.contains("PRIVATE KEY")) {
+ if (credentials.secretData.contains("PRIVATE KEY")) {
// todo: connect by key
-// p->setNativeArguments(QString("%1@%2")
-// .arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
+ // p->setNativeArguments(QString("%1@%2")
+ // .arg(credentials.userName).arg(credentials.hostName).arg(credentials.secretData));
+ } else {
+ p->setNativeArguments(
+ QString("%1@%2 -pw %3").arg(credentials.userName).arg(credentials.hostName).arg(credentials.secretData));
}
- else {
- p->setNativeArguments(QString("%1@%2 -pw %3")
- .arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
- }
-#else
+ #else
p->setProgram("/bin/bash");
-#endif
+ #endif
p->startDetached();
#endif
@@ -95,11 +102,11 @@ QProcessEnvironment SshConfigurator::prepareEnv()
pathEnvVar.clear();
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\cygwin;");
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\openvpn;");
-#else
+#elif defined(Q_OS_MACX)
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS");
#endif
env.insert("PATH", pathEnvVar);
- //qDebug().noquote() << "ENV PATH" << pathEnvVar;
+ // qDebug().noquote() << "ENV PATH" << pathEnvVar;
return env;
}
diff --git a/client/configurators/vpn_configurator.cpp b/client/configurators/vpn_configurator.cpp
index ceb6a5a4..6c5286c2 100644
--- a/client/configurators/vpn_configurator.cpp
+++ b/client/configurators/vpn_configurator.cpp
@@ -1,32 +1,34 @@
#include "vpn_configurator.h"
-#include "openvpn_configurator.h"
#include "cloak_configurator.h"
-#include "shadowsocks_configurator.h"
-#include "wireguard_configurator.h"
#include "ikev2_configurator.h"
+#include "openvpn_configurator.h"
+#include "shadowsocks_configurator.h"
#include "ssh_configurator.h"
+#include "wireguard_configurator.h"
+#include "awg_configurator.h"
#include
-#include
#include
+#include
#include "containers/containers_defs.h"
-#include "utilities.h"
#include "settings.h"
+#include "utilities.h"
-VpnConfigurator::VpnConfigurator(std::shared_ptr settings, QObject *parent):
- ConfiguratorBase(settings, parent)
+VpnConfigurator::VpnConfigurator(std::shared_ptr settings, QObject *parent)
+ : ConfiguratorBase(settings, parent)
{
openVpnConfigurator = std::shared_ptr(new OpenVpnConfigurator(settings, this));
shadowSocksConfigurator = std::shared_ptr(new ShadowSocksConfigurator(settings, this));
cloakConfigurator = std::shared_ptr(new CloakConfigurator(settings, this));
- wireguardConfigurator = std::shared_ptr(new WireguardConfigurator(settings, this));
+ wireguardConfigurator = std::shared_ptr(new WireguardConfigurator(settings, false, this));
ikev2Configurator = std::shared_ptr(new Ikev2Configurator(settings, this));
sshConfigurator = std::shared_ptr(new SshConfigurator(settings, this));
+ awgConfigurator = std::shared_ptr(new AwgConfigurator(settings, this));
}
-QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials,
- DockerContainer container, const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
+QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
+ const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
{
switch (proto) {
case Proto::OpenVpn:
@@ -35,17 +37,17 @@ QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentia
case Proto::ShadowSocks:
return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode);
- case Proto::Cloak:
- return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
+ case Proto::Cloak: return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
case Proto::WireGuard:
return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, errorCode);
- case Proto::Ikev2:
- return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
+ case Proto::Awg:
+ return awgConfigurator->genAwgConfig(credentials, container, containerConfig, errorCode);
- default:
- return "";
+ case Proto::Ikev2: return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
+
+ default: return "";
}
}
@@ -62,8 +64,8 @@ QPair VpnConfigurator::getDnsForConfig(int serverIndex)
if (dns.first.isEmpty() || !Utils::checkIPv4Format(dns.first)) {
if (useAmneziaDns && m_settings->containers(serverIndex).contains(DockerContainer::Dns)) {
dns.first = protocols::dns::amneziaDnsIp;
- }
- else dns.first = m_settings->primaryDns();
+ } else
+ dns.first = m_settings->primaryDns();
}
if (dns.second.isEmpty() || !Utils::checkIPv4Format(dns.second)) {
dns.second = m_settings->secondaryDns();
@@ -73,8 +75,8 @@ QPair VpnConfigurator::getDnsForConfig(int serverIndex)
return dns;
}
-QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container,
- Proto proto, QString &config)
+QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto,
+ QString &config)
{
auto dns = getDnsForConfig(serverIndex);
@@ -84,8 +86,8 @@ QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerCo
return config;
}
-QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container,
- Proto proto, QString &config)
+QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto,
+ QString &config)
{
processConfigWithDnsSettings(serverIndex, container, proto, config);
@@ -95,8 +97,8 @@ QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, Docker
return config;
}
-QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container,
- Proto proto, QString &config)
+QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto,
+ QString &config)
{
processConfigWithDnsSettings(serverIndex, container, proto, config);
@@ -107,7 +109,7 @@ QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, Docke
}
void VpnConfigurator::updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig,
- const QString &stdOut)
+ const QString &stdOut)
{
Proto mainProto = ContainerProps::defaultProtocol(container);
diff --git a/client/configurators/vpn_configurator.h b/client/configurators/vpn_configurator.h
index 3b9c761b..ac89b0e4 100644
--- a/client/configurators/vpn_configurator.h
+++ b/client/configurators/vpn_configurator.h
@@ -13,13 +13,14 @@ class CloakConfigurator;
class WireguardConfigurator;
class Ikev2Configurator;
class SshConfigurator;
+class AwgConfigurator;
// Retrieve connection settings from server
class VpnConfigurator : ConfiguratorBase
{
Q_OBJECT
public:
- VpnConfigurator(std::shared_ptr settings, QObject *parent = nullptr);
+ explicit VpnConfigurator(std::shared_ptr settings, QObject *parent = nullptr);
QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr);
@@ -40,6 +41,7 @@ public:
std::shared_ptr wireguardConfigurator;
std::shared_ptr ikev2Configurator;
std::shared_ptr sshConfigurator;
+ std::shared_ptr awgConfigurator;
};
#endif // VPN_CONFIGURATOR_H
diff --git a/client/configurators/wireguard_configurator.cpp b/client/configurators/wireguard_configurator.cpp
index 54ee320c..e22c8282 100644
--- a/client/configurators/wireguard_configurator.cpp
+++ b/client/configurators/wireguard_configurator.cpp
@@ -1,30 +1,38 @@
#include "wireguard_configurator.h"
-#include
+
+#include
+#include
#include
#include
#include
-#include
#include
-#include
-
+#include
#include
#include
#include
-#include
-
#include "containers/containers_defs.h"
-#include "core/server_defs.h"
#include "core/scripts_registry.h"
-#include "utilities.h"
+#include "core/server_defs.h"
#include "core/servercontroller.h"
#include "settings.h"
+#include "utilities.h"
-WireguardConfigurator::WireguardConfigurator(std::shared_ptr settings, QObject *parent):
- ConfiguratorBase(settings, parent)
+WireguardConfigurator::WireguardConfigurator(std::shared_ptr settings, bool isAwg, QObject *parent)
+ : ConfiguratorBase(settings, parent), m_isAwg(isAwg)
{
+ m_serverConfigPath = m_isAwg ? amnezia::protocols::awg::serverConfigPath
+ : amnezia::protocols::wireguard::serverConfigPath;
+ m_serverPublicKeyPath = m_isAwg ? amnezia::protocols::awg::serverPublicKeyPath
+ : amnezia::protocols::wireguard::serverPublicKeyPath;
+ m_serverPskKeyPath = m_isAwg ? amnezia::protocols::awg::serverPskKeyPath
+ : amnezia::protocols::wireguard::serverPskKeyPath;
+ m_configTemplate = m_isAwg ? ProtocolScriptType::awg_template
+ : ProtocolScriptType::wireguard_template;
+ m_protocolName = m_isAwg ? config_key::awg : config_key::wireguard;
+ m_defaultPort = m_isAwg ? protocols::wireguard::defaultPort : protocols::awg::defaultPort;
}
WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
@@ -36,37 +44,40 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
unsigned char buff[EDDSA_KEY_LENGTH];
int ret = RAND_priv_bytes(buff, EDDSA_KEY_LENGTH);
- if (ret <=0) return connData;
+ if (ret <= 0)
+ return connData;
- EVP_PKEY * pKey = EVP_PKEY_new();
+ EVP_PKEY *pKey = EVP_PKEY_new();
q_check_ptr(pKey);
pKey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, &buff[0], EDDSA_KEY_LENGTH);
-
size_t keySize = EDDSA_KEY_LENGTH;
// save private key
unsigned char priv[EDDSA_KEY_LENGTH];
EVP_PKEY_get_raw_private_key(pKey, priv, &keySize);
- connData.clientPrivKey = QByteArray::fromRawData((char*)priv, keySize).toBase64();
+ connData.clientPrivKey = QByteArray::fromRawData((char *)priv, keySize).toBase64();
// save public key
unsigned char pub[EDDSA_KEY_LENGTH];
EVP_PKEY_get_raw_public_key(pKey, pub, &keySize);
- connData.clientPubKey = QByteArray::fromRawData((char*)pub, keySize).toBase64();
+ connData.clientPubKey = QByteArray::fromRawData((char *)pub, keySize).toBase64();
return connData;
}
WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials,
- DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
+ DockerContainer container,
+ const QJsonObject &containerConfig,
+ ErrorCode *errorCode)
{
WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys();
connData.host = credentials.hostName;
- connData.port = containerConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
+ connData.port = containerConfig.value(m_protocolName).toObject().value(config_key::port).toString(m_defaultPort);
if (connData.clientPrivKey.isEmpty() || connData.clientPubKey.isEmpty()) {
- if (errorCode) *errorCode = ErrorCode::InternalError;
+ if (errorCode)
+ *errorCode = ErrorCode::InternalError;
return connData;
}
@@ -76,7 +87,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
// Get list of already created clients (only IP addresses)
QString nextIpNumber;
{
- QString script = QString("cat %1 | grep AllowedIPs").arg(amnezia::protocols::wireguard::serverConfigPath);
+ QString script = QString("cat %1 | grep AllowedIPs").arg(m_serverConfigPath);
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
stdOut += data + "\n";
@@ -96,22 +107,24 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
// Calc next IP address
if (ips.isEmpty()) {
nextIpNumber = "2";
- }
- else {
+ } else {
int next = ips.last().split(".").last().toInt() + 1;
if (next > 254) {
- if (errorCode) *errorCode = ErrorCode::AddressPoolError;
+ if (errorCode)
+ *errorCode = ErrorCode::AddressPoolError;
return connData;
}
nextIpNumber = QString::number(next);
}
}
- QString subnetIp = containerConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
+ QString subnetIp =
+ containerConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
{
QStringList l = subnetIp.split(".", Qt::SkipEmptyParts);
if (l.isEmpty()) {
- if (errorCode) *errorCode = ErrorCode::AddressPoolError;
+ if (errorCode)
+ *errorCode = ErrorCode::AddressPoolError;
return connData;
}
l.removeLast();
@@ -121,52 +134,55 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
}
// Get keys
- connData.serverPubKey = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPublicKeyPath, &e);
+ connData.serverPubKey = serverController.getTextFileFromContainer(container, credentials, m_serverPublicKeyPath, &e);
connData.serverPubKey.replace("\n", "");
if (e) {
- if (errorCode) *errorCode = e;
+ if (errorCode)
+ *errorCode = e;
return connData;
}
- connData.pskKey = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPskKeyPath, &e);
+ connData.pskKey = serverController.getTextFileFromContainer(container, credentials, m_serverPskKeyPath, &e);
connData.pskKey.replace("\n", "");
if (e) {
- if (errorCode) *errorCode = e;
+ if (errorCode)
+ *errorCode = e;
return connData;
}
// Add client to config
- QString configPart = QString(
- "[Peer]\n"
- "PublicKey = %1\n"
- "PresharedKey = %2\n"
- "AllowedIPs = %3/32\n\n").
- arg(connData.clientPubKey).
- arg(connData.pskKey).
- arg(connData.clientIP);
+ QString configPart = QString("[Peer]\n"
+ "PublicKey = %1\n"
+ "PresharedKey = %2\n"
+ "AllowedIPs = %3/32\n\n")
+ .arg(connData.clientPubKey, connData.pskKey, connData.clientIP);
- e = serverController.uploadTextFileToContainer(container, credentials, configPart,
- protocols::wireguard::serverConfigPath, libssh::SftpOverwriteMode::SftpAppendToExisting);
+ e = serverController.uploadTextFileToContainer(container, credentials, configPart, m_serverConfigPath,
+ libssh::SftpOverwriteMode::SftpAppendToExisting);
if (e) {
- if (errorCode) *errorCode = e;
+ if (errorCode)
+ *errorCode = e;
return connData;
}
- e = serverController.runScript(credentials,
- serverController.replaceVars("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip /opt/amnezia/wireguard/wg0.conf)'",
- serverController.genVarsForScript(credentials, container)));
+ QString script = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'")
+ .arg(m_serverConfigPath);
+
+ e = serverController.runScript(
+ credentials, serverController.replaceVars(script, serverController.genVarsForScript(credentials, container)));
return connData;
}
-QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials,
- DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
+QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
+ const QJsonObject &containerConfig, ErrorCode *errorCode)
{
ServerController serverController(m_settings);
- QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container),
- serverController.genVarsForScript(credentials, container, containerConfig));
+ QString scriptData = amnezia::scriptData(m_configTemplate, container);
+ QString config = serverController.replaceVars(
+ scriptData, serverController.genVarsForScript(credentials, container, containerConfig));
ConnectionData connData = prepareWireguardConfig(credentials, container, containerConfig, errorCode);
if (errorCode && *errorCode) {
diff --git a/client/configurators/wireguard_configurator.h b/client/configurators/wireguard_configurator.h
index 7674eb06..7f8e1587 100644
--- a/client/configurators/wireguard_configurator.h
+++ b/client/configurators/wireguard_configurator.h
@@ -6,35 +6,44 @@
#include "configurator_base.h"
#include "core/defs.h"
+#include "core/scripts_registry.h"
-class WireguardConfigurator : ConfiguratorBase
+class WireguardConfigurator : public ConfiguratorBase
{
Q_OBJECT
public:
- WireguardConfigurator(std::shared_ptr settings, QObject *parent = nullptr);
+ WireguardConfigurator(std::shared_ptr settings, bool isAwg, QObject *parent = nullptr);
- struct ConnectionData {
+ struct ConnectionData
+ {
QString clientPrivKey; // client private key
- QString clientPubKey; // client public key
- QString clientIP; // internal client IP address
- QString serverPubKey; // tls-auth key
- QString pskKey; // preshared key
- QString host; // host ip
+ QString clientPubKey; // client public key
+ QString clientIP; // internal client IP address
+ QString serverPubKey; // tls-auth key
+ QString pskKey; // preshared key
+ QString host; // host ip
QString port;
};
QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
- const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
+ const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
QString processConfigWithLocalSettings(QString config);
QString processConfigWithExportSettings(QString config);
-
private:
- ConnectionData prepareWireguardConfig(const ServerCredentials &credentials,
- DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
+ ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
+ const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
ConnectionData genClientKeys();
+
+ bool m_isAwg;
+ QString m_serverConfigPath;
+ QString m_serverPublicKeyPath;
+ QString m_serverPskKeyPath;
+ amnezia::ProtocolScriptType m_configTemplate;
+ QString m_protocolName;
+ QString m_defaultPort;
};
#endif // WIREGUARD_CONFIGURATOR_H
diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp
index 92066dab..b6f1b111 100644
--- a/client/containers/containers_defs.cpp
+++ b/client/containers/containers_defs.cpp
@@ -8,18 +8,23 @@ QDebug operator<<(QDebug debug, const amnezia::DockerContainer &c)
return debug;
}
-amnezia::DockerContainer ContainerProps::containerFromString(const QString &container){
+amnezia::DockerContainer ContainerProps::containerFromString(const QString &container)
+{
QMetaEnum metaEnum = QMetaEnum::fromType();
for (int i = 0; i < metaEnum.keyCount(); ++i) {
DockerContainer c = static_cast(i);
- if (container == containerToString(c)) return c;
+ if (container == containerToString(c))
+ return c;
}
return DockerContainer::None;
}
-QString ContainerProps::containerToString(amnezia::DockerContainer c){
- if (c == DockerContainer::None) return "none";
- if (c == DockerContainer::Cloak) return "amnezia-openvpn-cloak";
+QString ContainerProps::containerToString(amnezia::DockerContainer c)
+{
+ if (c == DockerContainer::None)
+ return "none";
+ if (c == DockerContainer::Cloak)
+ return "amnezia-openvpn-cloak";
QMetaEnum metaEnum = QMetaEnum::fromType();
QString containerKey = metaEnum.valueToKey(static_cast(c));
@@ -27,9 +32,12 @@ QString ContainerProps::containerToString(amnezia::DockerContainer c){
return "amnezia-" + containerKey.toLower();
}
-QString ContainerProps::containerTypeToString(amnezia::DockerContainer c){
- if (c == DockerContainer::None) return "none";
- if (c == DockerContainer::Ipsec) return "ikev2";
+QString ContainerProps::containerTypeToString(amnezia::DockerContainer c)
+{
+ if (c == DockerContainer::None)
+ return "none";
+ if (c == DockerContainer::Ipsec)
+ return "ikev2";
QMetaEnum metaEnum = QMetaEnum::fromType();
QString containerKey = metaEnum.valueToKey(static_cast(c));
@@ -40,29 +48,21 @@ QString ContainerProps::containerTypeToString(amnezia::DockerContainer c){
QVector ContainerProps::protocolsForContainer(amnezia::DockerContainer container)
{
switch (container) {
- case DockerContainer::None:
- return { };
+ case DockerContainer::None: return {};
- case DockerContainer::OpenVpn:
- return { Proto::OpenVpn };
+ case DockerContainer::OpenVpn: return { Proto::OpenVpn };
- case DockerContainer::ShadowSocks:
- return { Proto::OpenVpn, Proto::ShadowSocks };
+ case DockerContainer::ShadowSocks: return { Proto::OpenVpn, Proto::ShadowSocks };
- case DockerContainer::Cloak:
- return { Proto::OpenVpn, Proto::ShadowSocks, Proto::Cloak };
+ case DockerContainer::Cloak: return { Proto::OpenVpn, Proto::ShadowSocks, Proto::Cloak };
- case DockerContainer::Ipsec:
- return { Proto::Ikev2 /*, Protocol::L2tp */};
+ case DockerContainer::Ipsec: return { Proto::Ikev2 /*, Protocol::L2tp */ };
- case DockerContainer::Dns:
- return { };
+ case DockerContainer::Dns: return {};
- case DockerContainer::Sftp:
- return { Proto::Sftp};
+ case DockerContainer::Sftp: return { Proto::Sftp };
- default:
- return { defaultProtocol(container) };
+ default: return { defaultProtocol(container) };
}
}
@@ -79,70 +79,164 @@ QList ContainerProps::allContainers()
QMap ContainerProps::containerHumanNames()
{
- return {
- {DockerContainer::None, "Not installed"},
- {DockerContainer::OpenVpn, "OpenVPN"},
- {DockerContainer::ShadowSocks, "OpenVpn over ShadowSocks"},
- {DockerContainer::Cloak, "OpenVpn over Cloak"},
- {DockerContainer::WireGuard, "WireGuard"},
- {DockerContainer::Ipsec, QObject::tr("IPsec")},
+ return { { DockerContainer::None, "Not installed" },
+ { DockerContainer::OpenVpn, "OpenVPN" },
+ { DockerContainer::ShadowSocks, "ShadowSocks" },
+ { DockerContainer::Cloak, "OpenVPN over Cloak" },
+ { DockerContainer::WireGuard, "WireGuard" },
+ { DockerContainer::Awg, "AmneziaWG" },
+ { DockerContainer::Ipsec, QObject::tr("IPsec") },
- {DockerContainer::TorWebSite, QObject::tr("Web site in Tor network")},
- {DockerContainer::Dns, QObject::tr("DNS Service")},
- //{DockerContainer::FileShare, QObject::tr("SMB file sharing service")},
- {DockerContainer::Sftp, QObject::tr("Sftp file sharing service")}
- };
+ { DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
+ { DockerContainer::Dns, QObject::tr("Amnezia DNS") },
+ { DockerContainer::Sftp, QObject::tr("Sftp file sharing service") } };
}
QMap ContainerProps::containerDescriptions()
{
- return {
- {DockerContainer::OpenVpn, QObject::tr("OpenVPN container")},
- {DockerContainer::ShadowSocks, QObject::tr("Container with OpenVpn and ShadowSocks")},
- {DockerContainer::Cloak, QObject::tr("Container with OpenVpn and ShadowSocks protocols "
- "configured with traffic masking by Cloak plugin")},
- {DockerContainer::WireGuard, QObject::tr("WireGuard container")},
- {DockerContainer::Ipsec, QObject::tr("IPsec container")},
+ return { { DockerContainer::OpenVpn,
+ QObject::tr("OpenVPN is the most popular VPN protocol, with flexible configuration options. It uses its "
+ "own security protocol with SSL/TLS for key exchange.") },
+ { DockerContainer::ShadowSocks,
+ QObject::tr("ShadowSocks - masks VPN traffic, making it similar to normal web traffic, but is "
+ "recognised by analysis systems in some highly censored regions.") },
+ { DockerContainer::Cloak,
+ QObject::tr("OpenVPN over Cloak - OpenVPN with VPN masquerading as web traffic and protection against "
+ "active-probbing detection. Ideal for bypassing blocking in regions with the highest levels "
+ "of censorship.") },
+ { DockerContainer::WireGuard,
+ QObject::tr("WireGuard - New popular VPN protocol with high performance, high speed and low power "
+ "consumption. Recommended for regions with low levels of censorship.") },
+ { DockerContainer::Awg,
+ QObject::tr("AmneziaWG - Special protocol from Amnezia, based on WireGuard. It's fast like WireGuard, "
+ "but very resistant to blockages. "
+ "Recommended for regions with high levels of censorship.") },
+ { DockerContainer::Ipsec,
+ QObject::tr("IKEv2 - 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("Web site in Tor network")},
- {DockerContainer::Dns, QObject::tr("DNS Service")},
- //{DockerContainer::FileShare, QObject::tr("SMB file sharing service - is Window file sharing protocol")},
- {DockerContainer::Sftp, QObject::tr("Sftp file sharing service - is secure FTP service")}
+ { 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("Creates a file vault on your server to securely store and transfer files.") } };
+}
+
+QMap ContainerProps::containerDetailedDescriptions()
+{
+ return {
+ { DockerContainer::OpenVpn,
+ 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, "
+ "catering to a wide range of devices and operating systems. "
+ "Due to its open-source nature, OpenVPN benefits from extensive scrutiny by the global community, "
+ "which continually reinforces its security. "
+ "With a strong balance of performance, security, and compatibility, "
+ "OpenVPN remains a top choice for privacy-conscious individuals and businesses alike.\n\n"
+ "* Available in the AmneziaVPN across all platforms\n"
+ "* Normal power consumption on mobile devices\n"
+ "* Flexible customisation to suit user needs to work with different operating systems and devices\n"
+ "* Recognised by DPI analysis systems and therefore susceptible to blocking\n"
+ "* 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."
+ "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"
+ "* Normal power consumption on mobile devices\n\n"
+ "* Configurable encryption protocol\n"
+ "* Detectable by some DPI systems\n"
+ "* Works over TCP network protocol.") },
+ { DockerContainer::Cloak,
+ QObject::tr("This is a combination of the OpenVPN protocol and the Cloak plugin designed specifically for "
+ "blocking protection.\n\n"
+ "OpenVPN provides a secure VPN connection by encrypting all Internet traffic between the client "
+ "and the server.\n\n"
+ "Cloak protects OpenVPN from detection and blocking. \n\n"
+ "Cloak can modify packet metadata so that it completely masks VPN traffic as normal web traffic, "
+ "and also protects the VPN from detection by Active Probing. This makes it very resistant to "
+ "being detected\n\n"
+ "Immediately after receiving the first data packet, Cloak authenticates the incoming connection. "
+ "If authentication fails, the plugin masks the server as a fake website and your VPN becomes "
+ "invisible to analysis systems.\n\n"
+ "If there is a extreme level of Internet censorship in your region, we advise you to use only "
+ "OpenVPN over Cloak from the first connection\n\n"
+ "* Available in the AmneziaVPN across all platforms\n"
+ "* High power consumption on mobile devices\n"
+ "* Flexible settings\n"
+ "* Not recognised by DPI analysis systems\n"
+ "* Works over TCP network protocol, 443 port.\n") },
+ { DockerContainer::WireGuard,
+ QObject::tr("A relatively new popular VPN protocol with a simplified architecture.\n"
+ "Provides stable VPN connection, high performance on all devices. Uses hard-coded encryption "
+ "settings. WireGuard compared to OpenVPN has lower latency and better data transfer throughput.\n"
+ "WireGuard is very susceptible to blocking due to its distinct packet signatures. "
+ "Unlike some other VPN protocols that employ obfuscation techniques, "
+ "the consistent signature patterns of WireGuard packets can be more easily identified and "
+ "thus blocked by advanced Deep Packet Inspection (DPI) systems and other network monitoring tools.\n\n"
+ "* Available in the AmneziaVPN across all platforms\n"
+ "* Low power consumption\n"
+ "* Minimum number of settings\n"
+ "* Easily recognised by DPI analysis systems, susceptible to blocking\n"
+ "* Works over UDP network protocol.") },
+ { DockerContainer::Awg,
+ QObject::tr("A modern iteration of the popular VPN protocol, "
+ "AmneziaWG builds upon the foundation set by WireGuard, "
+ "retaining its simplified architecture and high-performance capabilities across devices.\n"
+ "While WireGuard is known for its efficiency, "
+ "it had issues with being easily detected due to its distinct packet signatures. "
+ "AmneziaWG solves this problem by using better obfuscation methods, "
+ "making its traffic blend in with regular internet traffic.\n"
+ "This means that AmneziaWG keeps the fast performance of the original "
+ "while adding an extra layer of stealth, "
+ "making it a great choice for those wanting a fast and discreet VPN connection.\n\n"
+ "* Available in the AmneziaVPN across all platforms\n"
+ "* Low power consumption\n"
+ "* Minimum number of settings\n"
+ "* Not recognised by DPI analysis systems, resistant to blocking\n"
+ "* Works over UDP network protocol.") },
+ { 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, "
+ "making it particularly adaptive in dynamic network environments. \n"
+ "While it offers a blend of security, stability, and speed, "
+ "it's essential to note that IKEv2 can be easily detected and is susceptible to blocking.\n\n"
+ "* Available in the AmneziaVPN only on Windows\n"
+ "* Low power consumption, on mobile devices\n"
+ "* Minimal configuration\n"
+ "* Recognised by DPI analysis systems\n"
+ "* Works over UDP network protocol, ports 500 and 4500.") },
+
+ { DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
+ { DockerContainer::Dns, QObject::tr("DNS Service") },
+ { DockerContainer::Sftp, QObject::tr("Sftp file sharing service - is secure FTP service") }
};
}
amnezia::ServiceType ContainerProps::containerService(DockerContainer c)
{
- switch (c) {
- case DockerContainer::None : return ServiceType::None;
- case DockerContainer::OpenVpn : return ServiceType::Vpn;
- case DockerContainer::Cloak : return ServiceType::Vpn;
- case DockerContainer::ShadowSocks : return ServiceType::Vpn;
- case DockerContainer::WireGuard : return ServiceType::Vpn;
- case DockerContainer::Ipsec : return ServiceType::Vpn;
- case DockerContainer::TorWebSite : return ServiceType::Other;
- case DockerContainer::Dns : return ServiceType::Other;
- //case DockerContainer::FileShare : return ServiceType::Other;
- case DockerContainer::Sftp : return ServiceType::Other;
- default: return ServiceType::Other;
- }
+ return ProtocolProps::protocolService(defaultProtocol(c));
}
Proto ContainerProps::defaultProtocol(DockerContainer c)
{
switch (c) {
- case DockerContainer::None : return Proto::Any;
- case DockerContainer::OpenVpn : return Proto::OpenVpn;
- case DockerContainer::Cloak : return Proto::Cloak;
- case DockerContainer::ShadowSocks : return Proto::ShadowSocks;
- case DockerContainer::WireGuard : return Proto::WireGuard;
- case DockerContainer::Ipsec : return Proto::Ikev2;
+ case DockerContainer::None: return Proto::Any;
+ case DockerContainer::OpenVpn: return Proto::OpenVpn;
+ case DockerContainer::Cloak: return Proto::Cloak;
+ case DockerContainer::ShadowSocks: return Proto::ShadowSocks;
+ case DockerContainer::WireGuard: return Proto::WireGuard;
+ case DockerContainer::Awg: return Proto::Awg;
+ case DockerContainer::Ipsec: return Proto::Ikev2;
- case DockerContainer::TorWebSite : return Proto::TorWebSite;
- case DockerContainer::Dns : return Proto::Dns;
- //case DockerContainer::FileShare : return Protocol::FileShare;
- case DockerContainer::Sftp : return Proto::Sftp;
- default: return Proto::Any;
+ case DockerContainer::TorWebSite: return Proto::TorWebSite;
+ case DockerContainer::Dns: return Proto::Dns;
+ case DockerContainer::Sftp: return Proto::Sftp;
+ default: return Proto::Any;
}
}
@@ -151,31 +245,34 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
#ifdef Q_OS_WINDOWS
return true;
-#elif defined (Q_OS_IOS)
+#elif defined(Q_OS_IOS)
switch (c) {
case DockerContainer::WireGuard: return true;
case DockerContainer::OpenVpn: return true;
- case DockerContainer::Cloak: return true;
-// case DockerContainer::ShadowSocks: return true;
+ case DockerContainer::Awg: return true;
+ case DockerContainer::Cloak:
+ return true;
+ // case DockerContainer::ShadowSocks: return true;
default: return false;
}
-#elif defined (Q_OS_MAC)
+#elif defined(Q_OS_MAC)
switch (c) {
case DockerContainer::WireGuard: return true;
case DockerContainer::Ipsec: return false;
default: return true;
}
-#elif defined (Q_OS_ANDROID)
+#elif defined(Q_OS_ANDROID)
switch (c) {
case DockerContainer::WireGuard: return true;
case DockerContainer::OpenVpn: return true;
case DockerContainer::ShadowSocks: return true;
+ case DockerContainer::Awg: return true;
case DockerContainer::Cloak: return true;
default: return false;
}
-#elif defined (Q_OS_LINUX)
+#elif defined(Q_OS_LINUX)
switch (c) {
case DockerContainer::WireGuard: return true;
case DockerContainer::Ipsec: return false;
@@ -183,14 +280,65 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
}
#else
-return false;
+ return false;
#endif
}
QStringList ContainerProps::fixedPortsForContainer(DockerContainer c)
{
switch (c) {
- case DockerContainer::Ipsec : return QStringList{"500", "4500"};
- default: return {};
+ case DockerContainer::Ipsec: return QStringList { "500", "4500" };
+ default: return {};
+ }
+}
+
+bool ContainerProps::isEasySetupContainer(DockerContainer container)
+{
+ switch (container) {
+ case DockerContainer::WireGuard: return true;
+ case DockerContainer::Awg: return true;
+ case DockerContainer::Cloak: return true;
+ default: return false;
+ }
+}
+
+QString ContainerProps::easySetupHeader(DockerContainer container)
+{
+ switch (container) {
+ case DockerContainer::WireGuard: return tr("Low");
+ case DockerContainer::Awg: return tr("Medium or High");
+ case DockerContainer::Cloak: return tr("Extreme");
+ default: return "";
+ }
+}
+
+QString ContainerProps::easySetupDescription(DockerContainer container)
+{
+ switch (container) {
+ case DockerContainer::WireGuard: return tr("I just want to increase the level of my privacy.");
+ case DockerContainer::Awg: return tr("I want to bypass censorship. This option recommended in most cases.");
+ case DockerContainer::Cloak:
+ return tr("Most VPN protocols are blocked. Recommended if other options are not working.");
+ default: return "";
+ }
+}
+
+int ContainerProps::easySetupOrder(DockerContainer container)
+{
+ switch (container) {
+ case DockerContainer::WireGuard: return 3;
+ case DockerContainer::Awg: return 2;
+ case DockerContainer::Cloak: return 1;
+ default: return 0;
+ }
+}
+
+bool ContainerProps::isShareable(DockerContainer container)
+{
+ switch (container) {
+ case DockerContainer::TorWebSite: return false;
+ case DockerContainer::Dns: return false;
+ case DockerContainer::Sftp: return false;
+ default: return true;
}
}
diff --git a/client/containers/containers_defs.h b/client/containers/containers_defs.h
index ff230c3e..92ca4f18 100644
--- a/client/containers/containers_defs.h
+++ b/client/containers/containers_defs.h
@@ -8,68 +8,72 @@
using namespace amnezia;
-namespace amnezia {
-
-namespace ContainerEnumNS {
-Q_NAMESPACE
-enum DockerContainer {
- None = 0,
- OpenVpn,
- ShadowSocks,
- Cloak,
- WireGuard,
- Ipsec,
-
- //non-vpn
- TorWebSite,
- Dns,
- //FileShare,
- Sftp
-};
-Q_ENUM_NS(DockerContainer)
-} // namespace ContainerEnumNS
-
-using namespace ContainerEnumNS;
-using namespace ProtocolEnumNS;
-
-class ContainerProps : public QObject
+namespace amnezia
{
- Q_OBJECT
-public:
- Q_INVOKABLE static amnezia::DockerContainer containerFromString(const QString &container);
- Q_INVOKABLE static QString containerToString(amnezia::DockerContainer container);
- Q_INVOKABLE static QString containerTypeToString(amnezia::DockerContainer c);
+ namespace ContainerEnumNS
+ {
+ Q_NAMESPACE
+ enum DockerContainer {
+ None = 0,
+ Awg,
+ WireGuard,
+ OpenVpn,
+ Cloak,
+ ShadowSocks,
+ Ipsec,
- Q_INVOKABLE static QList allContainers();
+ // non-vpn
+ TorWebSite,
+ Dns,
+ Sftp
+ };
+ Q_ENUM_NS(DockerContainer)
+ } // namespace ContainerEnumNS
- Q_INVOKABLE static QMap containerHumanNames();
- Q_INVOKABLE static QMap containerDescriptions();
+ using namespace ContainerEnumNS;
+ using namespace ProtocolEnumNS;
- // these protocols will be displayed in container settings
- Q_INVOKABLE static QVector protocolsForContainer(amnezia::DockerContainer container);
+ class ContainerProps : public QObject
+ {
+ Q_OBJECT
- Q_INVOKABLE static amnezia::ServiceType containerService(amnezia::DockerContainer c);
+ public:
+ Q_INVOKABLE static amnezia::DockerContainer containerFromString(const QString &container);
+ Q_INVOKABLE static QString containerToString(amnezia::DockerContainer container);
+ Q_INVOKABLE static QString containerTypeToString(amnezia::DockerContainer c);
- // binding between Docker container and main protocol of given container
- // it may be changed fot future containers :)
- Q_INVOKABLE static amnezia::Proto defaultProtocol(amnezia::DockerContainer c);
+ Q_INVOKABLE static QList allContainers();
- Q_INVOKABLE static bool isSupportedByCurrentPlatform(amnezia::DockerContainer c);
- Q_INVOKABLE static QStringList fixedPortsForContainer(amnezia::DockerContainer c);
-};
+ Q_INVOKABLE static QMap containerHumanNames();
+ Q_INVOKABLE static QMap containerDescriptions();
+ Q_INVOKABLE static QMap containerDetailedDescriptions();
+ // these protocols will be displayed in container settings
+ Q_INVOKABLE static QVector protocolsForContainer(amnezia::DockerContainer container);
+ Q_INVOKABLE static amnezia::ServiceType containerService(amnezia::DockerContainer c);
-static void declareQmlContainerEnum() {
- qmlRegisterUncreatableMetaObject(
- ContainerEnumNS::staticMetaObject,
- "ContainerEnum",
- 1, 0,
- "ContainerEnum",
- "Error: only enums"
- );
-}
+ // binding between Docker container and main protocol of given container
+ // it may be changed fot future containers :)
+ Q_INVOKABLE static amnezia::Proto defaultProtocol(amnezia::DockerContainer c);
+
+ Q_INVOKABLE static bool isSupportedByCurrentPlatform(amnezia::DockerContainer c);
+ Q_INVOKABLE static QStringList fixedPortsForContainer(amnezia::DockerContainer c);
+
+ static bool isEasySetupContainer(amnezia::DockerContainer container);
+ static QString easySetupHeader(amnezia::DockerContainer container);
+ static QString easySetupDescription(amnezia::DockerContainer container);
+ static int easySetupOrder(amnezia::DockerContainer container);
+
+ static bool isShareable(amnezia::DockerContainer container);
+ };
+
+ static void declareQmlContainerEnum()
+ {
+ qmlRegisterUncreatableMetaObject(ContainerEnumNS::staticMetaObject, "ContainerEnum", 1, 0, "ContainerEnum",
+ "Error: only enums");
+ }
} // namespace amnezia
diff --git a/client/core/defs.h b/client/core/defs.h
index 4fb140e4..35515103 100644
--- a/client/core/defs.h
+++ b/client/core/defs.h
@@ -12,10 +12,10 @@ struct ServerCredentials
{
QString hostName;
QString userName;
- QString password;
+ QString secretData;
int port = 22;
- bool isValid() const { return !hostName.isEmpty() && !userName.isEmpty() && !password.isEmpty() && port > 0; }
+ bool isValid() const { return !hostName.isEmpty() && !userName.isEmpty() && !secretData.isEmpty() && port > 0; }
};
enum ErrorCode
@@ -37,7 +37,7 @@ enum ErrorCode
// Ssh connection errors
SshRequsetDeniedError, SshInterruptedError, SshInternalError,
- SshPrivateKeyError, SshPrivateKeyFormatError,
+ SshPrivateKeyError, SshPrivateKeyFormatError, SshTimeoutError,
// Ssh sftp errors
SshSftpEofError, SshSftpNoSuchFileError, SshSftpPermissionDeniedError,
@@ -69,7 +69,10 @@ enum ErrorCode
OpenSslFailed,
OpenVpnExecutableCrashed,
ShadowSocksExecutableCrashed,
- CloakExecutableCrashed
+ CloakExecutableCrashed,
+
+ // import and install errors
+ ImportInvalidConfigError
};
} // namespace amnezia
diff --git a/client/core/errorstrings.cpp b/client/core/errorstrings.cpp
index 17b40b09..cd66186d 100644
--- a/client/core/errorstrings.cpp
+++ b/client/core/errorstrings.cpp
@@ -24,6 +24,7 @@ QString errorString(ErrorCode code){
case(SshInternalError): return QObject::tr("Ssh internal error");
case(SshPrivateKeyError): return QObject::tr("Invalid private key or invalid passphrase entered");
case(SshPrivateKeyFormatError): return QObject::tr("The selected private key format is not supported, use openssh ED25519 key types or PEM key types");
+ case(SshTimeoutError): return QObject::tr("Timeout connecting to server");
// Libssh sftp errors
case(SshSftpEofError): return QObject::tr("Sftp error: End-of-file encountered");
@@ -57,6 +58,8 @@ QString errorString(ErrorCode code){
case (OpenVpnTapAdapterError): return QObject::tr("Can't setup OpenVPN TAP network adapter");
case (AddressPoolError): return QObject::tr("VPN pool error: no available addresses");
+ case (ImportInvalidConfigError): return QObject::tr("The config does not contain any containers and credentiaks for connecting to the server");
+
case(InternalError):
default:
return QObject::tr("Internal error");
diff --git a/client/core/scripts_registry.cpp b/client/core/scripts_registry.cpp
index 1b379ea1..61ae8962 100644
--- a/client/core/scripts_registry.cpp
+++ b/client/core/scripts_registry.cpp
@@ -1,8 +1,8 @@
#include "scripts_registry.h"
-#include
#include
#include
+#include
QString amnezia::scriptFolder(amnezia::DockerContainer container)
{
@@ -11,11 +11,11 @@ QString amnezia::scriptFolder(amnezia::DockerContainer container)
case DockerContainer::Cloak: return QLatin1String("openvpn_cloak");
case DockerContainer::ShadowSocks: return QLatin1String("openvpn_shadowsocks");
case DockerContainer::WireGuard: return QLatin1String("wireguard");
+ case DockerContainer::Awg: return QLatin1String("awg");
case DockerContainer::Ipsec: return QLatin1String("ipsec");
case DockerContainer::TorWebSite: return QLatin1String("website_tor");
case DockerContainer::Dns: return QLatin1String("dns");
- //case DockerContainer::FileShare: return QLatin1String("file_share");
case DockerContainer::Sftp: return QLatin1String("sftp");
default: return "";
}
@@ -45,6 +45,7 @@ QString amnezia::scriptName(ProtocolScriptType type)
case ProtocolScriptType::container_startup: return QLatin1String("start.sh");
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
case ProtocolScriptType::wireguard_template: return QLatin1String("template.conf");
+ case ProtocolScriptType::awg_template: return QLatin1String("template.conf");
}
}
@@ -52,7 +53,7 @@ QString amnezia::scriptData(amnezia::SharedScriptType type)
{
QString fileName = QString(":/server_scripts/%1").arg(amnezia::scriptName(type));
QFile file(fileName);
- if (! file.open(QIODevice::ReadOnly)) {
+ if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Warning: script missing" << fileName;
return "";
}
@@ -67,7 +68,7 @@ QString amnezia::scriptData(amnezia::ProtocolScriptType type, DockerContainer co
{
QString fileName = QString(":/server_scripts/%1/%2").arg(amnezia::scriptFolder(container), amnezia::scriptName(type));
QFile file(fileName);
- if (! file.open(QIODevice::ReadOnly)) {
+ if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Warning: script missing" << fileName;
return "";
}
diff --git a/client/core/scripts_registry.h b/client/core/scripts_registry.h
index b30be2ff..02fc94fd 100644
--- a/client/core/scripts_registry.h
+++ b/client/core/scripts_registry.h
@@ -26,7 +26,8 @@ enum ProtocolScriptType {
configure_container,
container_startup,
openvpn_template,
- wireguard_template
+ wireguard_template,
+ awg_template
};
diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp
index e5505d46..da76e1ff 100644
--- a/client/core/servercontroller.cpp
+++ b/client/core/servercontroller.cpp
@@ -2,22 +2,21 @@
#include
#include
-#include
#include
+#include
+#include
+#include
+#include
#include
#include
-#include
-#include
-#include
-#include
#include
-#include
#include
+#include
#include
#include
-#include
#include
+#include
#include
#include
@@ -25,15 +24,14 @@
#include "containers/containers_defs.h"
#include "logger.h"
+#include "scripts_registry.h"
#include "server_defs.h"
#include "settings.h"
-#include "scripts_registry.h"
#include "utilities.h"
#include
-ServerController::ServerController(std::shared_ptr settings, QObject *parent) :
- m_settings(settings)
+ServerController::ServerController(std::shared_ptr settings, QObject *parent) : m_settings(settings)
{
}
@@ -42,10 +40,10 @@ ServerController::~ServerController()
m_sshClient.disconnectFromHost();
}
-
ErrorCode ServerController::runScript(const ServerCredentials &credentials, QString script,
- const std::function &cbReadStdOut,
- const std::function &cbReadStdErr) {
+ const std::function &cbReadStdOut,
+ const std::function &cbReadStdErr)
+{
auto error = m_sshClient.connectToHost(credentials);
if (error != ErrorCode::NoError) {
@@ -92,36 +90,36 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
return ErrorCode::NoError;
}
-ErrorCode ServerController::runContainerScript(const ServerCredentials &credentials,
- DockerContainer container, QString script,
- const std::function &cbReadStdOut,
- const std::function &cbReadStdErr)
+ErrorCode
+ServerController::runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
+ const std::function &cbReadStdOut,
+ const std::function &cbReadStdErr)
{
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
Logger::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + ":\n" + script);
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
- if (e) return e;
+ if (e)
+ return e;
QString runner = QString("sudo docker exec -i $CONTAINER_NAME bash %1 ").arg(fileName);
- e = runScript(credentials,
- replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
+ e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
- runScript(credentials,
- replaceVars(remover, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
+ runScript(credentials, replaceVars(remover, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
return e;
}
-ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
- const ServerCredentials &credentials, const QString &file, const QString &path,
- libssh::SftpOverwriteMode overwriteMode)
+ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials,
+ const QString &file, const QString &path,
+ libssh::SftpOverwriteMode overwriteMode)
{
ErrorCode e = ErrorCode::NoError;
QString tmpFileName = QString("/tmp/%1.tmp").arg(Utils::getRandomString(16));
e = uploadFileToHost(credentials, file.toUtf8(), tmpFileName);
- if (e) return e;
+ if (e)
+ return e;
QString stdOut;
auto cbReadStd = [&](const QString &data, libssh::Client &) {
@@ -130,61 +128,63 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
};
// mkdir
- QString mkdir = QString("sudo docker exec -i $CONTAINER_NAME mkdir -p \"$(dirname %1)\"")
- .arg(path);
-
- e = runScript(credentials,
- replaceVars(mkdir, genVarsForScript(credentials, container)));
- if (e) return e;
+ QString mkdir = QString("sudo docker exec -i $CONTAINER_NAME mkdir -p \"$(dirname %1)\"").arg(path);
+ e = runScript(credentials, replaceVars(mkdir, genVarsForScript(credentials, container)));
+ if (e)
+ return e;
if (overwriteMode == libssh::SftpOverwriteMode::SftpOverwriteExisting) {
e = runScript(credentials,
- replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
- genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
+ replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
+ genVarsForScript(credentials, container)),
+ cbReadStd, cbReadStd);
- if (e) return e;
- }
- else if (overwriteMode == libssh::SftpOverwriteMode::SftpAppendToExisting) {
+ if (e)
+ return e;
+ } else if (overwriteMode == libssh::SftpOverwriteMode::SftpAppendToExisting) {
e = runScript(credentials,
- replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(tmpFileName),
- genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
+ replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(tmpFileName),
+ genVarsForScript(credentials, container)),
+ cbReadStd, cbReadStd);
- if (e) return e;
+ if (e)
+ return e;
- e = runScript(credentials,
- replaceVars(QString("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName).arg(path),
- genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
-
- if (e) return e;
- }
- else return ErrorCode::NotImplementedError;
+ e = runScript(
+ credentials,
+ replaceVars(
+ QString("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName).arg(path),
+ genVarsForScript(credentials, container)),
+ cbReadStd, cbReadStd);
+ if (e)
+ return e;
+ } else
+ return ErrorCode::NotImplementedError;
if (stdOut.contains("Error: No such container:")) {
return ErrorCode::ServerContainerMissingError;
}
runScript(credentials,
- replaceVars(QString("sudo shred %1").arg(tmpFileName),
- genVarsForScript(credentials, container)));
+ replaceVars(QString("sudo shred %1").arg(tmpFileName), genVarsForScript(credentials, container)));
- runScript(credentials,
- replaceVars(QString("sudo rm %1").arg(tmpFileName),
- genVarsForScript(credentials, container)));
+ runScript(credentials, replaceVars(QString("sudo rm %1").arg(tmpFileName), genVarsForScript(credentials, container)));
return e;
}
-QByteArray ServerController::getTextFileFromContainer(DockerContainer container,
- const ServerCredentials &credentials, const QString &path, ErrorCode *errorCode)
+QByteArray ServerController::getTextFileFromContainer(DockerContainer container, const ServerCredentials &credentials,
+ const QString &path, ErrorCode *errorCode)
{
- if (errorCode) *errorCode = ErrorCode::NoError;
-
- QString script = QString("sudo docker exec -i %1 sh -c \"xxd -p \'%2\'\"").
- arg(ContainerProps::containerToString(container)).arg(path);
+ if (errorCode)
+ *errorCode = ErrorCode::NoError;
+ QString script = QString("sudo docker exec -i %1 sh -c \"xxd -p \'%2\'\"")
+ .arg(ContainerProps::containerToString(container))
+ .arg(path);
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
@@ -196,8 +196,8 @@ QByteArray ServerController::getTextFileFromContainer(DockerContainer container,
return QByteArray::fromHex(stdOut.toUtf8());
}
-ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath,
- libssh::SftpOverwriteMode overwriteMode)
+ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data,
+ const QString &remotePath, libssh::SftpOverwriteMode overwriteMode)
{
auto error = m_sshClient.connectToHost(credentials);
if (error != ErrorCode::NoError) {
@@ -209,7 +209,8 @@ ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credential
localFile.write(data);
localFile.close();
- error = m_sshClient.sftpFileCopy(overwriteMode, localFile.fileName().toStdString(), remotePath.toStdString(), "non_desc");
+ error = m_sshClient.sftpFileCopy(overwriteMode, localFile.fileName().toStdString(), remotePath.toStdString(),
+ "non_desc");
if (error != ErrorCode::NoError) {
return error;
}
@@ -218,15 +219,14 @@ ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credential
ErrorCode ServerController::removeAllContainers(const ServerCredentials &credentials)
{
- return runScript(credentials,
- amnezia::scriptData(SharedScriptType::remove_all_containers));
+ return runScript(credentials, amnezia::scriptData(SharedScriptType::remove_all_containers));
}
ErrorCode ServerController::removeContainer(const ServerCredentials &credentials, DockerContainer container)
{
return runScript(credentials,
- replaceVars(amnezia::scriptData(SharedScriptType::remove_container),
- genVarsForScript(credentials, container)));
+ replaceVars(amnezia::scriptData(SharedScriptType::remove_container),
+ genVarsForScript(credentials, container)));
}
ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container,
@@ -236,22 +236,33 @@ ErrorCode ServerController::setupContainer(const ServerCredentials &credentials,
ErrorCode e = ErrorCode::NoError;
e = isUserInSudo(credentials, container);
- if (e) return e;
+ if (e)
+ return e;
e = isServerDpkgBusy(credentials, container);
- if (e) return e;
+ if (e)
+ return e;
e = installDockerWorker(credentials, container);
- if (e) return e;
+ if (e)
+ return e;
qDebug().noquote() << "ServerController::setupContainer installDockerWorker finished";
if (!isUpdate) {
e = isServerPortBusy(credentials, container, config);
- if (e) return e;
+ if (e)
+ return e;
+ }
+
+ if (!isUpdate) {
+ e = isServerPortBusy(credentials, container, config);
+ if (e)
+ return e;
}
e = prepareHostWorker(credentials, container, config);
- if (e) return e;
+ if (e)
+ return e;
qDebug().noquote() << "ServerController::setupContainer prepareHostWorker finished";
removeContainer(credentials, container);
@@ -259,15 +270,18 @@ ErrorCode ServerController::setupContainer(const ServerCredentials &credentials,
qDebug().noquote() << "buildContainerWorker start";
e = buildContainerWorker(credentials, container, config);
- if (e) return e;
+ if (e)
+ return e;
qDebug().noquote() << "ServerController::setupContainer buildContainerWorker finished";
e = runContainerWorker(credentials, container, config);
- if (e) return e;
+ if (e)
+ return e;
qDebug().noquote() << "ServerController::setupContainer runContainerWorker finished";
e = configureContainerWorker(credentials, container, config);
- if (e) return e;
+ if (e)
+ return e;
qDebug().noquote() << "ServerController::setupContainer configureContainerWorker finished";
setupServerFirewall(credentials);
@@ -277,46 +291,25 @@ ErrorCode ServerController::setupContainer(const ServerCredentials &credentials,
}
ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container,
- const QJsonObject &oldConfig, QJsonObject &newConfig)
+ const QJsonObject &oldConfig, QJsonObject &newConfig)
{
bool reinstallRequired = isReinstallContainerRequired(container, oldConfig, newConfig);
- qDebug() << "ServerController::updateContainer for container" << container << "reinstall required is" << reinstallRequired;
+ qDebug() << "ServerController::updateContainer for container" << container << "reinstall required is"
+ << reinstallRequired;
if (reinstallRequired) {
return setupContainer(credentials, container, newConfig, true);
- }
- else {
+ } else {
ErrorCode e = configureContainerWorker(credentials, container, newConfig);
- if (e) return e;
+ if (e)
+ return e;
return startupContainerWorker(credentials, container, newConfig);
}
}
-QJsonObject ServerController::createContainerInitialConfig(DockerContainer container, int port, TransportProto tp)
-{
- Proto mainProto = ContainerProps::defaultProtocol(container);
-
- QJsonObject config {
- { config_key::container, ContainerProps::containerToString(container) }
- };
-
- QJsonObject protoConfig;
- protoConfig.insert(config_key::port, QString::number(port));
- protoConfig.insert(config_key::transport_proto, ProtocolProps::transportProtoToString(tp, mainProto));
-
-
- if (container == DockerContainer::Sftp) {
- protoConfig.insert(config_key::userName, protocols::sftp::defaultUserName);
- protoConfig.insert(config_key::password, Utils::getRandomString(10));
- }
-
- config.insert(ProtocolProps::protoToString(mainProto), protoConfig);
-
- return config;
-}
-
-bool ServerController::isReinstallContainerRequired(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig)
+bool ServerController::isReinstallContainerRequired(DockerContainer container, const QJsonObject &oldConfig,
+ const QJsonObject &newConfig)
{
Proto mainProto = ContainerProps::defaultProtocol(container);
@@ -324,25 +317,29 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
const QJsonObject &newProtoConfig = newConfig.value(ProtocolProps::protoToString(mainProto)).toObject();
if (container == DockerContainer::OpenVpn) {
- if (oldProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) !=
- newProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto))
- return true;
+ if (oldProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto)
+ != newProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto))
+ return true;
- if (oldProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort) !=
- newProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort))
- return true;
+ if (oldProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort)
+ != newProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort))
+ return true;
}
if (container == DockerContainer::Cloak) {
- if (oldProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort) !=
- newProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort))
- return true;
+ if (oldProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort)
+ != newProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort))
+ return true;
}
if (container == DockerContainer::ShadowSocks) {
- if (oldProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) !=
- newProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort))
- return true;
+ if (oldProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort)
+ != newProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort))
+ return true;
+ }
+
+ if (container == DockerContainer::Awg) {
+ return true;
}
return false;
@@ -364,75 +361,86 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent
return ErrorCode::NoError;
};
- ErrorCode error = runScript(credentials,
- replaceVars(amnezia::scriptData(SharedScriptType::install_docker),
- genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr);
+ ErrorCode error =
+ runScript(credentials,
+ replaceVars(amnezia::scriptData(SharedScriptType::install_docker), genVarsForScript(credentials)),
+ cbReadStdOut, cbReadStdErr);
qDebug().noquote() << "ServerController::installDockerWorker" << stdOut;
- if (stdOut.contains("lock")) return ErrorCode::ServerPacketManagerError;
- if (stdOut.contains("command not found")) return ErrorCode::ServerDockerFailedError;
+ if (stdOut.contains("lock"))
+ return ErrorCode::ServerPacketManagerError;
+ if (stdOut.contains("command not found"))
+ return ErrorCode::ServerDockerFailedError;
return error;
}
-ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
+ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container,
+ const QJsonObject &config)
{
// create folder on host
- return runScript(credentials,
- replaceVars(amnezia::scriptData(SharedScriptType::prepare_host),
- genVarsForScript(credentials, container)));
+ return runScript(
+ credentials,
+ replaceVars(amnezia::scriptData(SharedScriptType::prepare_host), genVarsForScript(credentials, container)));
}
-ErrorCode ServerController::buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
+ErrorCode ServerController::buildContainerWorker(const ServerCredentials &credentials, DockerContainer container,
+ const QJsonObject &config)
{
ErrorCode e = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(),
- amnezia::server::getDockerfileFolder(container) + "/Dockerfile");
+ amnezia::server::getDockerfileFolder(container) + "/Dockerfile");
- if (e) return e;
+ if (e)
+ return e;
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
stdOut += data + "\n";
return ErrorCode::NoError;
};
-// auto cbReadStdErr = [&](const QString &data, QSharedPointer proc) {
-// stdOut += data + "\n";
-// };
+ // auto cbReadStdErr = [&](const QString &data, QSharedPointer