Compare commits

..

1 Commits

Author SHA1 Message Date
Vladyslav Miachkov
dad2dc0ab0 Hide error on clear server button 2024-04-06 23:07:46 +03:00
192 changed files with 1145 additions and 10943 deletions

View File

@@ -233,7 +233,7 @@ jobs:
- name: 'Setup xcode'
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '14.3.1'
xcode-version: '13.4'
- name: 'Install Qt'
uses: jurplel/install-qt-action@v3

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 4.5.3.0
project(${PROJECT} VERSION 4.5.0.0
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
@@ -11,7 +11,7 @@ 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})
set(APP_ANDROID_VERSION_CODE 52)
set(APP_ANDROID_VERSION_CODE 50)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux")

View File

@@ -72,7 +72,7 @@ namespace QSimpleCrypto
/// \param notAfter - X509 end date.
/// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak.
///
X509* generateSelfSignedCertificate(RSA* rsa, const QMap<QByteArray, QByteArray>& additionalData,
X509* generateSelfSignedCertificate(const RSA* rsa, const QMap<QByteArray, QByteArray>& additionalData,
const QByteArray& certificateFileName = "", const EVP_MD* md = EVP_sha512(),
const long& serialNumber = 1, const long& version = x509LastVersion,
const long& notBefore = 0, const long& notAfter = oneYear);

View File

@@ -139,7 +139,7 @@ X509* QSimpleCrypto::QX509::verifyCertificate(X509* x509, X509_STORE* store)
/// \param notAfter - X509 end date.
/// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak.
///
X509* QSimpleCrypto::QX509::generateSelfSignedCertificate(RSA* rsa, const QMap<QByteArray, QByteArray>& additionalData,
X509* QSimpleCrypto::QX509::generateSelfSignedCertificate(const RSA* rsa, const QMap<QByteArray, QByteArray>& additionalData,
const QByteArray& certificateFileName, const EVP_MD* md,
const long& serialNumber, const long& version,
const long& notBefore, const long& notAfter)

View File

@@ -69,8 +69,6 @@ set(AMNEZIAVPN_TS_FILES
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ar_EG.ts
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_my_MM.ts
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_uk_UA.ts
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ur_PK.ts
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_hi_IN.ts
)
file(GLOB_RECURSE AMNEZIAVPN_TS_SOURCES *.qrc *.cpp *.h *.ui)

View File

@@ -9,16 +9,17 @@
#include <QTextDocument>
#include <QTimer>
#include <QTranslator>
#include <QQuickItem>
#include "logger.h"
#include "ui/models/installedAppsModel.h"
#include "version.h"
#include "ui/models/installedAppsModel.h"
#include "platforms/ios/QRCodeReaderBase.h"
#if defined(Q_OS_ANDROID)
#include "core/installedAppsImageProvider.h"
#include "platforms/android/android_controller.h"
#include "core/installedAppsImageProvider.h"
#endif
#include "protocols/qml_register_protocols.h"
@@ -31,8 +32,8 @@
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
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)
AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, SingleApplication::Options options,
int timeout, const QString &userData)
: SingleApplication(argc, argv, allowSecondary, options, timeout, userData)
#endif
{
@@ -45,12 +46,12 @@ AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecond
s.setValue("permFixed", true);
}
QString configLoc1 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/" + ORGANIZATION_NAME + "/"
+ APPLICATION_NAME + ".conf";
QString configLoc1 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + ".conf";
QFile::setPermissions(configLoc1, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
QString configLoc2 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/" + ORGANIZATION_NAME + "/"
+ APPLICATION_NAME + "/" + APPLICATION_NAME + ".conf";
QString configLoc2 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + "/" + APPLICATION_NAME + ".conf";
QFile::setPermissions(configLoc2, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
#endif
@@ -99,17 +100,20 @@ void AmneziaApplication::init()
connect(m_settings.get(), &Settings::saveLogsChanged, AndroidController::instance(), &AndroidController::setSaveLogs);
AndroidController::instance()->setScreenshotsEnabled(m_settings->isScreenshotsEnabled());
connect(m_settings.get(), &Settings::screenshotsEnabledChanged, AndroidController::instance(), &AndroidController::setScreenshotsEnabled);
connect(m_settings.get(), &Settings::screenshotsEnabledChanged, AndroidController::instance(),
&AndroidController::setScreenshotsEnabled);
connect(m_settings.get(), &Settings::serverRemoved, AndroidController::instance(), &AndroidController::resetLastServer);
connect(m_settings.get(), &Settings::serverRemoved, AndroidController::instance(),
&AndroidController::resetLastServer);
connect(m_settings.get(), &Settings::settingsCleared, []() { AndroidController::instance()->resetLastServer(-1); });
connect(AndroidController::instance(), &AndroidController::initConnectionState, this, [this](Vpn::ConnectionState state) {
m_connectionController->onConnectionStateChanged(state);
if (m_vpnConnection)
m_vpnConnection->restoreConnection();
});
connect(AndroidController::instance(), &AndroidController::initConnectionState, this,
[this](Vpn::ConnectionState state) {
m_connectionController->onConnectionStateChanged(state);
if (m_vpnConnection)
m_vpnConnection->restoreConnection();
});
if (!AndroidController::instance()->initialize()) {
qFatal("Android controller initialization failed");
}
@@ -123,6 +127,8 @@ void AmneziaApplication::init()
m_engine->addImageProvider(QLatin1String("installedAppImage"), new InstalledAppsImageProvider);
#endif
#ifdef Q_OS_IOS
IosController::Instance()->initialize();
connect(IosController::Instance(), &IosController::importConfigFromOutside, [this](QString data) {
@@ -139,7 +145,8 @@ void AmneziaApplication::init()
QTimer::singleShot(0, this, [this]() { AmneziaVPN::toggleScreenshots(m_settings->isScreenshotsEnabled()); });
connect(m_settings.get(), &Settings::screenshotsEnabledChanged, [](bool enabled) { AmneziaVPN::toggleScreenshots(enabled); });
connect(m_settings.get(), &Settings::screenshotsEnabledChanged,
[](bool enabled) { AmneziaVPN::toggleScreenshots(enabled); });
#endif
m_notificationHandler.reset(NotificationHandler::create(nullptr));
@@ -147,12 +154,14 @@ void AmneziaApplication::init()
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::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);
connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(),
&NotificationHandler::onTranslationsUpdated);
m_engine->load(url);
m_systemController->setQmlRoot(m_engine->rootObjects().value(0));
@@ -303,7 +312,8 @@ void AmneziaApplication::initModels()
m_serversModel.reset(new ServersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(), &ContainersModel::updateModel);
connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(),
&ContainersModel::updateModel);
connect(m_serversModel.get(), &ServersModel::defaultServerContainersUpdated, m_defaultServerContainersModel.get(),
&ContainersModel::updateModel);
m_serversModel->resetModel();
@@ -356,23 +366,26 @@ void AmneziaApplication::initModels()
void AmneziaApplication::initControllers()
{
m_connectionController.reset(
new ConnectionController(m_serversModel, m_containersModel, m_clientManagementModel, m_vpnConnection, m_settings));
m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_clientManagementModel,
m_vpnConnection, m_settings));
m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
connect(m_connectionController.get(), &ConnectionController::connectionErrorOccurred, this, [this](const QString &errorMessage) {
emit m_pageController->showErrorMessage(errorMessage);
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
});
connect(m_connectionController.get(), &ConnectionController::connectionErrorOccurred, this,
[this](const QString &errorMessage) {
emit m_pageController->showErrorMessage(errorMessage);
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
});
connect(m_connectionController.get(), &ConnectionController::connectButtonClicked, m_connectionController.get(),
&ConnectionController::toggleConnection, Qt::QueuedConnection);
connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(), &ConnectionController::onTranslationsUpdated);
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_clientManagementModel, m_settings));
m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel,
m_clientManagementModel, m_settings));
m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());
connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(),
&PageController::showPassphraseRequestDrawer);
@@ -388,12 +401,13 @@ void AmneziaApplication::initControllers()
m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
m_settingsController.reset(
new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_appSplitTunnelingModel, m_settings));
new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_settings));
m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
if (m_settingsController->isAutoConnectEnabled() && m_serversModel->getDefaultServerIndex() >= 0) {
QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); });
}
connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled, m_serversModel.get(), &ServersModel::toggleAmneziaDns);
connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled, m_serversModel.get(),
&ServersModel::toggleAmneziaDns);
m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel));
m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get());

View File

@@ -14,6 +14,8 @@
#include "settings.h"
#include "vpnconnection.h"
#include "core/controllers/apiController.h"
#include "ui/controllers/connectionController.h"
#include "ui/controllers/exportController.h"
#include "ui/controllers/importController.h"
@@ -123,6 +125,7 @@ private:
QScopedPointer<SettingsController> m_settingsController;
QScopedPointer<SitesController> m_sitesController;
QScopedPointer<SystemController> m_systemController;
QScopedPointer<ApiController> m_apiController;
QScopedPointer<AppSplitTunnelingController> m_appSplitTunnelingController;
};

View File

@@ -118,12 +118,12 @@ abstract class Protocol {
}
for (app in config.includedApplications) {
Log.d(TAG, "addAllowedApplication")
Log.d(TAG, "addAllowedApplication: $app")
vpnBuilder.addAllowedApplication(app)
}
for (app in config.excludedApplications) {
Log.d(TAG, "addDisallowedApplication")
Log.d(TAG, "addDisallowedApplication: $app")
vpnBuilder.addDisallowedApplication(app)
}

View File

@@ -453,7 +453,7 @@ class AmneziaActivity : QtActivity() {
@Suppress("unused")
fun setSaveLogs(enabled: Boolean) {
Log.v(TAG, "Set save logs: $enabled")
Log.d(TAG, "Set save logs: $enabled")
mainScope.launch {
Log.saveLogs = enabled
vpnServiceMessenger.send {
@@ -473,9 +473,7 @@ class AmneziaActivity : QtActivity() {
@Suppress("unused")
fun clearLogs() {
Log.v(TAG, "Clear logs")
mainScope.launch {
Log.clearLogs()
}
Log.clearLogs()
}
@Suppress("unused")
@@ -511,7 +509,7 @@ class AmneziaActivity : QtActivity() {
@Suppress("unused")
fun getAppIcon(packageName: String, width: Int, height: Int): Bitmap {
Log.v(TAG, "Get app icon")
Log.v(TAG, "Get app icon: $packageName")
return AppListProvider.getAppIcon(packageManager, packageName, width, height)
}
}

View File

@@ -109,11 +109,9 @@ object Log {
"${deviceInfo()}\n${readLogs()}\nLOGCAT:\n${getLogcat()}"
fun clearLogs() {
if (logDir.exists()) {
withLock {
logFile.delete()
rotateLogFile.delete()
}
withLock {
logFile.delete()
rotateLogFile.delete()
}
}

View File

@@ -49,8 +49,8 @@ foreach(abi IN ITEMS ${QT_ANDROID_ABIS})
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/android/${abi}/libovpn3.so
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/android/${abi}/libovpnutil.so
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/android/${abi}/librsapss.so
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openssl/android/${abi}/libcrypto_3.so
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openssl/android/${abi}/libssl_3.so
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/libssh/android/${abi}/libssh.so
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openssl3/android/${abi}/libcrypto_3.so
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openssl3/android/${abi}/libssl_3.so
)
endforeach()

View File

@@ -108,7 +108,6 @@ target_sources(${PROJECT} PRIVATE
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
${CLIENT_ROOT_DIR}/platforms/ios/ScreenProtection.swift
${CLIENT_ROOT_DIR}/platforms/ios/VPNCController.swift
)
target_sources(${PROJECT} PRIVATE

View File

@@ -3,13 +3,15 @@
#include <QJsonDocument>
#include <QJsonObject>
AwgConfigurator::AwgConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
: WireguardConfigurator(settings, serverController, true, parent)
#include "core/controllers/serverController.h"
AwgConfigurator::AwgConfigurator(std::shared_ptr<Settings> settings, QObject *parent)
: WireguardConfigurator(settings, true, parent)
{
}
QString AwgConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
ErrorCode errorCode)
QString AwgConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode)
{
QString config = WireguardConfigurator::createConfig(credentials, container, containerConfig, errorCode);
@@ -39,8 +41,8 @@ QString AwgConfigurator::createConfig(const ServerCredentials &credentials, Dock
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);
jsonConfig[config_key::mtu] =
containerConfig.value(ProtocolProps::protoToString(Proto::Awg)).toObject().value(config_key::mtu).toString(protocols::awg::defaultMtu);
jsonConfig[config_key::mtu] = containerConfig.value(ProtocolProps::protoToString(Proto::Awg)).toObject().
value(config_key::mtu).toString(protocols::awg::defaultMtu);
return QJsonDocument(jsonConfig).toJson();
}

View File

@@ -9,7 +9,7 @@ class AwgConfigurator : public WireguardConfigurator
{
Q_OBJECT
public:
AwgConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent = nullptr);
AwgConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
QString createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode);

View File

@@ -1,30 +1,33 @@
#include "cloak_configurator.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonDocument>
#include "containers/containers_defs.h"
#include "core/controllers/serverController.h"
#include "containers/containers_defs.h"
CloakConfigurator::CloakConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
: ConfiguratorBase(settings, serverController, parent)
CloakConfigurator::CloakConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
ConfiguratorBase(settings, parent)
{
}
QString CloakConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
ErrorCode errorCode)
QString CloakConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode)
{
QString cloakPublicKey =
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::cloak::ckPublicKeyPath, errorCode);
ServerController serverController(m_settings);
QString cloakPublicKey = serverController.getTextFileFromContainer(container, credentials,
amnezia::protocols::cloak::ckPublicKeyPath, errorCode);
cloakPublicKey.replace("\n", "");
if (errorCode != ErrorCode::NoError) {
return "";
}
QString cloakBypassUid =
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::cloak::ckBypassUidKeyPath, errorCode);
QString cloakBypassUid = serverController.getTextFileFromContainer(container, credentials,
amnezia::protocols::cloak::ckBypassUidKeyPath, errorCode);
cloakBypassUid.replace("\n", "");
if (errorCode != ErrorCode::NoError) {
@@ -44,8 +47,8 @@ QString CloakConfigurator::createConfig(const ServerCredentials &credentials, Do
config.insert("RemoteHost", credentials.hostName);
config.insert("RemotePort", "$CLOAK_SERVER_PORT");
QString textCfg = m_serverController->replaceVars(QJsonDocument(config).toJson(),
m_serverController->genVarsForScript(credentials, container, containerConfig));
QString textCfg = serverController.replaceVars(QJsonDocument(config).toJson(),
serverController.genVarsForScript(credentials, container, containerConfig));
return textCfg;
}

View File

@@ -11,7 +11,7 @@ class CloakConfigurator : public ConfiguratorBase
{
Q_OBJECT
public:
CloakConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent = nullptr);
CloakConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
QString createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode);

View File

@@ -1,7 +1,7 @@
#include "configurator_base.h"
ConfiguratorBase::ConfiguratorBase(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
: QObject { parent }, m_settings(settings), m_serverController(serverController)
ConfiguratorBase::ConfiguratorBase(std::shared_ptr<Settings> settings, QObject *parent)
: QObject { parent }, m_settings(settings)
{
}

View File

@@ -5,14 +5,13 @@
#include "containers/containers_defs.h"
#include "core/defs.h"
#include "core/controllers/serverController.h"
#include "settings.h"
class ConfiguratorBase : public QObject
{
Q_OBJECT
public:
explicit ConfiguratorBase(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent = nullptr);
explicit ConfiguratorBase(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
virtual QString createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode) = 0;
@@ -26,8 +25,6 @@ protected:
void processConfigWithDnsSettings(const QPair<QString, QString> &dns, QString &protocolConfigString);
std::shared_ptr<Settings> m_settings;
QSharedPointer<ServerController> m_serverController;
};
#endif // CONFIGURATORBASE_H

View File

@@ -9,18 +9,18 @@
#include <QUuid>
#include "containers/containers_defs.h"
#include "core/controllers/serverController.h"
#include "core/scripts_registry.h"
#include "core/server_defs.h"
#include "core/controllers/serverController.h"
#include "utilities.h"
Ikev2Configurator::Ikev2Configurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
: ConfiguratorBase(settings, serverController, parent)
Ikev2Configurator::Ikev2Configurator(std::shared_ptr<Settings> settings, QObject *parent)
: ConfiguratorBase(settings, parent)
{
}
Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials, DockerContainer container,
ErrorCode errorCode)
Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials,
DockerContainer container, ErrorCode errorCode)
{
Ikev2Configurator::ConnectionData connData;
connData.host = credentials.hostName;
@@ -39,14 +39,18 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
"--extKeyUsage serverAuth,clientAuth -8 \"%1\"")
.arg(connData.clientId);
errorCode = m_serverController->runContainerScript(credentials, container, scriptCreateCert);
ServerController serverController(m_settings);
errorCode = 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);
errorCode = m_serverController->runContainerScript(credentials, container, scriptExportCert);
QString scriptExportCert = QString("pk12util -W \"%1\" -d sql:/etc/ipsec.d -n \"%2\" -o \"%3\"")
.arg(connData.password)
.arg(connData.clientId)
.arg(certFileName);
errorCode = serverController.runContainerScript(credentials, container, scriptExportCert);
connData.clientCert = m_serverController->getTextFileFromContainer(container, credentials, certFileName, errorCode);
connData.caCert = m_serverController->getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", errorCode);
connData.clientCert = serverController.getTextFileFromContainer(container, credentials, certFileName, errorCode);
connData.caCert =
serverController.getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", errorCode);
qDebug() << "Ikev2Configurator::ConnectionData client cert size:" << connData.clientCert.size();
qDebug() << "Ikev2Configurator::ConnectionData ca cert size:" << connData.caCert.size();
@@ -54,8 +58,8 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
return connData;
}
QString Ikev2Configurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
ErrorCode errorCode)
QString Ikev2Configurator::createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode)
{
Q_UNUSED(containerConfig)

View File

@@ -11,7 +11,7 @@ class Ikev2Configurator : public ConfiguratorBase
{
Q_OBJECT
public:
Ikev2Configurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent = nullptr);
Ikev2Configurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
struct ConnectionData {
QByteArray clientCert; // p12 client cert

View File

@@ -24,14 +24,14 @@
#include <openssl/rsa.h>
#include <openssl/x509.h>
OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController,
QObject *parent)
: ConfiguratorBase(settings, serverController, parent)
OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> 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;
@@ -43,7 +43,8 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
QString reqFileName = QString("%1/%2.req").arg(amnezia::protocols::openvpn::clientsDirPath).arg(connData.clientId);
errorCode = m_serverController->uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
ServerController serverController(m_settings);
errorCode = serverController.uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
if (errorCode != ErrorCode::NoError) {
return connData;
}
@@ -53,16 +54,18 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
return connData;
}
connData.caCert =
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::caCertPath, errorCode);
connData.clientCert = m_serverController->getTextFileFromContainer(
container, credentials, QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), errorCode);
connData.caCert = serverController.getTextFileFromContainer(container, credentials,
amnezia::protocols::openvpn::caCertPath, errorCode);
connData.clientCert = serverController.getTextFileFromContainer(
container, credentials,
QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), errorCode);
if (errorCode != ErrorCode::NoError) {
return connData;
}
connData.taKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath, errorCode);
connData.taKey = serverController.getTextFileFromContainer(container, credentials,
amnezia::protocols::openvpn::taKeyPath, errorCode);
if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) {
errorCode = ErrorCode::SshScpFailureError;
@@ -74,8 +77,10 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
QString OpenVpnConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode)
{
QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
m_serverController->genVarsForScript(credentials, container, containerConfig));
ServerController serverController(m_settings);
QString config =
serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
serverController.genVarsForScript(credentials, container, containerConfig));
ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode);
if (errorCode != ErrorCode::NoError) {
@@ -116,16 +121,18 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPair<QString,
if (!isApiConfig) {
QRegularExpression regex("redirect-gateway.*");
config.replace(regex, "");
if (!m_settings->isSitesSplitTunnelingEnabled()) {
if (m_settings->routeMode() == Settings::VpnAllSites) {
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
// Prevent ipv6 leak
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
config.append("block-ipv6\n");
} else if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
}
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
// no redirect-gateway
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
}
if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
#ifndef Q_OS_ANDROID
config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
#endif
@@ -189,10 +196,12 @@ ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, const ServerC
.arg(ContainerProps::containerToString(container))
.arg(clientId);
ServerController serverController(m_settings);
QStringList scriptList { script_import, script_sign };
QString script = m_serverController->replaceVars(scriptList.join("\n"), m_serverController->genVarsForScript(credentials, container));
QString script = serverController.replaceVars(scriptList.join("\n"),
serverController.genVarsForScript(credentials, container));
return m_serverController->runScript(credentials, script);
return serverController.runScript(credentials, script);
}
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
@@ -226,8 +235,8 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
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<unsigned char const *>(clientIdUtf8.data()),
clientIdUtf8.size(), -1, 0);
X509_NAME_add_entry_by_txt(x509_name, "CN", MBSTRING_ASC,
reinterpret_cast<unsigned char const *>(clientIdUtf8.data()), clientIdUtf8.size(), -1, 0);
// 4. set public key of x509 req
ret = X509_REQ_set_pubkey(x509_req, pKey);

View File

@@ -11,7 +11,7 @@ class OpenVpnConfigurator : public ConfiguratorBase
{
Q_OBJECT
public:
OpenVpnConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent = nullptr);
OpenVpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
struct ConnectionData
{

View File

@@ -1,23 +1,25 @@
#include "shadowsocks_configurator.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonDocument>
#include "containers/containers_defs.h"
#include "core/controllers/serverController.h"
ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController,
QObject *parent)
: ConfiguratorBase(settings, serverController, parent)
ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
ConfiguratorBase(settings, parent)
{
}
QString ShadowSocksConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode)
{
QString ssKey =
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::shadowsocks::ssKeyPath, errorCode);
ServerController serverController(m_settings);
QString ssKey = serverController.getTextFileFromContainer(container, credentials,
amnezia::protocols::shadowsocks::ssKeyPath, errorCode);
ssKey.replace("\n", "");
if (errorCode != ErrorCode::NoError) {
@@ -32,9 +34,10 @@ QString ShadowSocksConfigurator::createConfig(const ServerCredentials &credentia
config.insert("timeout", 60);
config.insert("method", "$SHADOWSOCKS_CIPHER");
QString textCfg = m_serverController->replaceVars(QJsonDocument(config).toJson(),
m_serverController->genVarsForScript(credentials, container, containerConfig));
// qDebug().noquote() << textCfg;
QString textCfg = serverController.replaceVars(QJsonDocument(config).toJson(),
serverController.genVarsForScript(credentials, container, containerConfig));
//qDebug().noquote() << textCfg;
return textCfg;
}

View File

@@ -10,7 +10,7 @@ class ShadowSocksConfigurator : public ConfiguratorBase
{
Q_OBJECT
public:
ShadowSocksConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent = nullptr);
ShadowSocksConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
QString createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode);

View File

@@ -17,8 +17,8 @@
#include "core/server_defs.h"
#include "utilities.h"
SshConfigurator::SshConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
: ConfiguratorBase(settings, serverController, parent)
SshConfigurator::SshConfigurator(std::shared_ptr<Settings> settings, QObject *parent)
: ConfiguratorBase(settings, parent)
{
}
@@ -82,7 +82,8 @@ void SshConfigurator::openSshTerminal(const ServerCredentials &credentials)
// 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));
p->setNativeArguments(
QString("%1@%2 -pw %3").arg(credentials.userName).arg(credentials.hostName).arg(credentials.secretData));
}
#else
p->setProgram("/bin/bash");

View File

@@ -11,7 +11,7 @@ class SshConfigurator : ConfiguratorBase
{
Q_OBJECT
public:
SshConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent = nullptr);
SshConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
QProcessEnvironment prepareEnv();
QString convertOpenSShKey(const QString &key);

View File

@@ -19,13 +19,15 @@
#include "settings.h"
#include "utilities.h"
WireguardConfigurator::WireguardConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController,
bool isAwg, QObject *parent)
: ConfiguratorBase(settings, serverController, parent), m_isAwg(isAwg)
WireguardConfigurator::WireguardConfigurator(std::shared_ptr<Settings> 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_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;
@@ -65,7 +67,8 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials,
DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode)
const QJsonObject &containerConfig,
ErrorCode errorCode)
{
WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys();
connData.host = credentials.hostName;
@@ -76,6 +79,8 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
return connData;
}
ServerController serverController(m_settings);
// Get list of already created clients (only IP addresses)
QString nextIpNumber;
{
@@ -86,7 +91,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
return ErrorCode::NoError;
};
errorCode = m_serverController->runContainerScript(credentials, container, script, cbReadStdOut);
errorCode = serverController.runContainerScript(credentials, container, script, cbReadStdOut);
if (errorCode != ErrorCode::NoError) {
return connData;
}
@@ -108,7 +113,8 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
}
}
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()) {
@@ -122,13 +128,14 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
}
// Get keys
connData.serverPubKey = m_serverController->getTextFileFromContainer(container, credentials, m_serverPublicKeyPath, errorCode);
connData.serverPubKey =
serverController.getTextFileFromContainer(container, credentials, m_serverPublicKeyPath, errorCode);
connData.serverPubKey.replace("\n", "");
if (errorCode != ErrorCode::NoError) {
return connData;
}
connData.pskKey = m_serverController->getTextFileFromContainer(container, credentials, m_serverPskKeyPath, errorCode);
connData.pskKey = serverController.getTextFileFromContainer(container, credentials, m_serverPskKeyPath, errorCode);
connData.pskKey.replace("\n", "");
if (errorCode != ErrorCode::NoError) {
@@ -142,17 +149,18 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
"AllowedIPs = %3/32\n\n")
.arg(connData.clientPubKey, connData.pskKey, connData.clientIP);
errorCode = m_serverController->uploadTextFileToContainer(container, credentials, configPart, m_serverConfigPath,
libssh::ScpOverwriteMode::ScpAppendToExisting);
errorCode = serverController.uploadTextFileToContainer(container, credentials, configPart, m_serverConfigPath,
libssh::ScpOverwriteMode::ScpAppendToExisting);
if (errorCode != ErrorCode::NoError) {
return connData;
}
QString script = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'").arg(m_serverConfigPath);
QString script = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'")
.arg(m_serverConfigPath);
errorCode = m_serverController->runScript(
credentials, m_serverController->replaceVars(script, m_serverController->genVarsForScript(credentials, container)));
errorCode = serverController.runScript(
credentials, serverController.replaceVars(script, serverController.genVarsForScript(credentials, container)));
return connData;
}
@@ -160,9 +168,10 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
QString WireguardConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode)
{
ServerController serverController(m_settings);
QString scriptData = amnezia::scriptData(m_configTemplate, container);
QString config =
m_serverController->replaceVars(scriptData, m_serverController->genVarsForScript(credentials, container, containerConfig));
QString config = serverController.replaceVars(
scriptData, serverController.genVarsForScript(credentials, container, containerConfig));
ConnectionData connData = prepareWireguardConfig(credentials, container, containerConfig, errorCode);
if (errorCode != ErrorCode::NoError) {
@@ -192,16 +201,16 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials
return QJsonDocument(jConfig).toJson();
}
QString WireguardConfigurator::processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
QString &protocolConfigString)
QString WireguardConfigurator::processConfigWithLocalSettings(const QPair<QString, QString> &dns,
const bool isApiConfig, QString &protocolConfigString)
{
processConfigWithDnsSettings(dns, protocolConfigString);
return protocolConfigString;
}
QString WireguardConfigurator::processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
QString &protocolConfigString)
QString WireguardConfigurator::processConfigWithExportSettings(const QPair<QString, QString> &dns,
const bool isApiConfig, QString &protocolConfigString)
{
processConfigWithDnsSettings(dns, protocolConfigString);

View File

@@ -12,8 +12,7 @@ class WireguardConfigurator : public ConfiguratorBase
{
Q_OBJECT
public:
WireguardConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, bool isAwg,
QObject *parent = nullptr);
WireguardConfigurator(std::shared_ptr<Settings> settings, bool isAwg, QObject *parent = nullptr);
struct ConnectionData
{
@@ -26,11 +25,13 @@ public:
QString port;
};
QString createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
ErrorCode errorCode);
QString createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode);
QString processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig, QString &protocolConfigString);
QString processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig, QString &protocolConfigString);
QString processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
QString &protocolConfigString);
QString processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
QString &protocolConfigString);
static ConnectionData genClientKeys();

View File

@@ -8,26 +8,26 @@
#include "core/controllers/serverController.h"
#include "core/scripts_registry.h"
XrayConfigurator::XrayConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
: ConfiguratorBase(settings, serverController, parent)
XrayConfigurator::XrayConfigurator(std::shared_ptr<Settings> settings, QObject *parent) : ConfiguratorBase(settings, parent)
{
}
QString XrayConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
ErrorCode errorCode)
{
QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::xray_template, container),
m_serverController->genVarsForScript(credentials, container, containerConfig));
ServerController serverController(m_settings);
QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::xray_template, container),
serverController.genVarsForScript(credentials, container, containerConfig));
QString xrayPublicKey =
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::PublicKeyPath, errorCode);
serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::xray::PublicKeyPath, errorCode);
xrayPublicKey.replace("\n", "");
QString xrayUuid = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::uuidPath, errorCode);
QString xrayUuid = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::xray::uuidPath, errorCode);
xrayUuid.replace("\n", "");
QString xrayShortId =
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::shortidPath, errorCode);
QString xrayShortId = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::xray::shortidPath, errorCode);
xrayShortId.replace("\n", "");
if (errorCode != ErrorCode::NoError) {

View File

@@ -10,7 +10,7 @@ class XrayConfigurator : public ConfiguratorBase
{
Q_OBJECT
public:
XrayConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent = nullptr);
XrayConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
QString createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
ErrorCode errorCode);

View File

@@ -321,7 +321,7 @@ bool ContainerProps::isEasySetupContainer(DockerContainer container)
switch (container) {
case DockerContainer::WireGuard: return true;
case DockerContainer::Awg: return true;
// case DockerContainer::Cloak: return true;
case DockerContainer::Cloak: return true;
default: return false;
}
}
@@ -330,8 +330,8 @@ QString ContainerProps::easySetupHeader(DockerContainer container)
{
switch (container) {
case DockerContainer::WireGuard: return tr("Low");
case DockerContainer::Awg: return tr("High");
// case DockerContainer::Cloak: return tr("Extreme");
case DockerContainer::Awg: return tr("Medium or High");
case DockerContainer::Cloak: return tr("Extreme");
default: return "";
}
}
@@ -341,8 +341,8 @@ 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.");
case DockerContainer::Cloak:
return tr("Most VPN protocols are blocked. Recommended if other options are not working.");
default: return "";
}
}
@@ -352,7 +352,7 @@ int ContainerProps::easySetupOrder(DockerContainer container)
switch (container) {
case DockerContainer::WireGuard: return 3;
case DockerContainer::Awg: return 2;
// case DockerContainer::Cloak: return 1;
case DockerContainer::Cloak: return 1;
default: return 0;
}
}

View File

@@ -5,6 +5,7 @@
#include <QNetworkReply>
#include <QtConcurrent>
#include "core/errorstrings.h"
#include "configurators/wireguard_configurator.h"
namespace
@@ -19,7 +20,6 @@ namespace
constexpr char certificate[] = "certificate";
constexpr char publicKey[] = "public_key";
constexpr char protocol[] = "protocol";
constexpr char uuid[] = "installation_uuid";
}
}
@@ -64,11 +64,11 @@ QJsonObject ApiController::fillApiPayload(const QString &protocol, const ApiCont
return obj;
}
ErrorCode ApiController::updateServerConfigFromApi(const QString &installationUuid, QJsonObject &serverConfig)
ErrorCode ApiController::updateServerConfigFromApi(QJsonObject &serverConfig)
{
QFutureWatcher<ErrorCode> watcher;
QFuture<ErrorCode> future = QtConcurrent::run([this, &serverConfig, &installationUuid]() {
QFuture<ErrorCode> future = QtConcurrent::run([this, &serverConfig]() {
auto containerConfig = serverConfig.value(config_key::containers).toArray();
if (serverConfig.value(config_key::configVersion).toInt()) {
@@ -86,10 +86,7 @@ ErrorCode ApiController::updateServerConfigFromApi(const QString &installationUu
auto apiPayloadData = generateApiPayloadData(protocol);
auto apiPayload = fillApiPayload(protocol, apiPayloadData);
apiPayload[configKey::uuid] = installationUuid;
QByteArray requestBody = QJsonDocument(apiPayload).toJson();
QByteArray requestBody = QJsonDocument(fillApiPayload(protocol, apiPayloadData)).toJson();
QScopedPointer<QNetworkReply> reply;
reply.reset(manager.post(request, requestBody));

View File

@@ -13,7 +13,7 @@ public:
explicit ApiController(QObject *parent = nullptr);
public slots:
ErrorCode updateServerConfigFromApi(const QString &installationUuid, QJsonObject &serverConfig);
ErrorCode updateServerConfigFromApi(QJsonObject &serverConfig);
private:
struct ApiPayloadData {

View File

@@ -23,10 +23,10 @@
#include <thread>
#include "containers/containers_defs.h"
#include "core/networkUtilities.h"
#include "logger.h"
#include "core/scripts_registry.h"
#include "core/server_defs.h"
#include "logger.h"
#include "core/networkUtilities.h"
#include "settings.h"
#include "utilities.h"
#include "vpnConfigurationController.h"
@@ -95,9 +95,10 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
return ErrorCode::NoError;
}
ErrorCode ServerController::runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdOut,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
ErrorCode
ServerController::runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdOut,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
{
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
Logger::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + ":\n" + script);
@@ -115,8 +116,9 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
return e;
}
ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials, const QString &file,
const QString &path, libssh::ScpOverwriteMode overwriteMode)
ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials,
const QString &file, const QString &path,
libssh::ScpOverwriteMode overwriteMode)
{
ErrorCode e = ErrorCode::NoError;
QString tmpFileName = QString("/tmp/%1.tmp").arg(Utils::getRandomString(16));
@@ -154,10 +156,12 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
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);
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;
@@ -168,17 +172,20 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
return ErrorCode::ServerContainerMissingError;
}
runScript(credentials, replaceVars(QString("sudo shred -u %1").arg(tmpFileName), genVarsForScript(credentials, container)));
runScript(credentials,
replaceVars(QString("sudo shred -u %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)
{
errorCode = ErrorCode::NoError;
QString script = QString("sudo docker exec -i %1 sh -c \"xxd -p \'%2\'\"").arg(ContainerProps::containerToString(container)).arg(path);
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 &) {
@@ -190,8 +197,8 @@ QByteArray ServerController::getTextFileFromContainer(DockerContainer container,
return QByteArray::fromHex(stdOut.toUtf8());
}
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath,
libssh::ScpOverwriteMode overwriteMode)
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data,
const QString &remotePath, libssh::ScpOverwriteMode overwriteMode)
{
auto error = m_sshClient.connectToHost(credentials);
if (error != ErrorCode::NoError) {
@@ -237,10 +244,12 @@ ErrorCode ServerController::removeAllContainers(const ServerCredentials &credent
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, QJsonObject &config, bool isUpdate)
ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container,
QJsonObject &config, bool isUpdate)
{
qDebug().noquote() << "ServerController::setupContainer" << ContainerProps::containerToString(container);
ErrorCode e = ErrorCode::NoError;
@@ -300,11 +309,12 @@ ErrorCode ServerController::setupContainer(const ServerCredentials &credentials,
return startupContainerWorker(credentials, container, config);
}
ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &oldConfig,
QJsonObject &newConfig)
ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container,
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);
@@ -317,7 +327,8 @@ ErrorCode ServerController::updateContainer(const ServerCredentials &credentials
}
}
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);
@@ -348,7 +359,7 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
if (container == DockerContainer::Awg) {
if ((oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)
!= newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort))
!= newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort))
|| (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)
!= newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount))
|| (oldProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize)
@@ -370,7 +381,7 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
return true;
}
if (container == DockerContainer::WireGuard) {
if (container == DockerContainer::WireGuard){
if (oldProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)
!= newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort))
return true;
@@ -396,7 +407,8 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent
};
ErrorCode error =
runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::install_docker), genVarsForScript(credentials)),
runScript(credentials,
replaceVars(amnezia::scriptData(SharedScriptType::install_docker), genVarsForScript(credentials)),
cbReadStdOut, cbReadStdErr);
qDebug().noquote() << "ServerController::installDockerWorker" << stdOut;
@@ -408,13 +420,17 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent
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");
@@ -429,7 +445,8 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
};
e = runScript(credentials,
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
replaceVars(amnezia::scriptData(SharedScriptType::build_container),
genVarsForScript(credentials, container, config)),
cbReadStdOut);
if (e)
return e;
@@ -437,7 +454,8 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
return e;
}
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container,
QJsonObject &config)
{
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
@@ -460,7 +478,8 @@ ErrorCode ServerController::runContainerWorker(const ServerCredentials &credenti
return e;
}
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container,
QJsonObject &config)
{
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
@@ -482,7 +501,8 @@ ErrorCode ServerController::configureContainerWorker(const ServerCredentials &cr
return e;
}
ErrorCode ServerController::startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
ErrorCode ServerController::startupContainerWorker(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &config)
{
QString script = amnezia::scriptData(ProtocolScriptType::container_startup, container);
@@ -490,7 +510,8 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred
return ErrorCode::NoError;
}
ErrorCode e = uploadTextFileToContainer(container, credentials, replaceVars(script, genVarsForScript(credentials, container, config)),
ErrorCode e = uploadTextFileToContainer(container, credentials,
replaceVars(script, genVarsForScript(credentials, container, config)),
"/opt/amnezia/start.sh");
if (e)
return e;
@@ -501,8 +522,8 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred
genVarsForScript(credentials, container, config)));
}
ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &config)
ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials,
DockerContainer container, const QJsonObject &config)
{
const QJsonObject &openvpnConfig = config.value(ProtocolProps::protoToString(Proto::OpenVpn)).toObject();
const QJsonObject &cloakConfig = config.value(ProtocolProps::protoToString(Proto::Cloak)).toObject();
@@ -517,19 +538,24 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
vars.append({ { "$REMOTE_HOST", credentials.hostName } });
// OpenVPN vars
vars.append({ { "$OPENVPN_SUBNET_IP",
openvpnConfig.value(config_key::subnet_address).toString(protocols::openvpn::defaultSubnetAddress) } });
vars.append({ { "$OPENVPN_SUBNET_CIDR", openvpnConfig.value(config_key::subnet_cidr).toString(protocols::openvpn::defaultSubnetCidr) } });
vars.append({ { "$OPENVPN_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(protocols::openvpn::defaultSubnetMask) } });
vars.append(
{ { "$OPENVPN_SUBNET_IP",
openvpnConfig.value(config_key::subnet_address).toString(protocols::openvpn::defaultSubnetAddress) } });
vars.append({ { "$OPENVPN_SUBNET_CIDR",
openvpnConfig.value(config_key::subnet_cidr).toString(protocols::openvpn::defaultSubnetCidr) } });
vars.append({ { "$OPENVPN_SUBNET_MASK",
openvpnConfig.value(config_key::subnet_mask).toString(protocols::openvpn::defaultSubnetMask) } });
vars.append({ { "$OPENVPN_PORT", openvpnConfig.value(config_key::port).toString(protocols::openvpn::defaultPort) } });
vars.append({ { "$OPENVPN_TRANSPORT_PROTO",
openvpnConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) } });
vars.append(
{ { "$OPENVPN_TRANSPORT_PROTO",
openvpnConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) } });
bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable);
vars.append({ { "$OPENVPN_NCP_DISABLE", isNcpDisabled ? protocols::openvpn::ncpDisableString : "" } });
vars.append({ { "$OPENVPN_CIPHER", openvpnConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher) } });
vars.append({ { "$OPENVPN_CIPHER",
openvpnConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher) } });
vars.append({ { "$OPENVPN_HASH", openvpnConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash) } });
bool isTlsAuth = openvpnConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth);
@@ -540,35 +566,43 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
}
vars.append({ { "$OPENVPN_ADDITIONAL_CLIENT_CONFIG",
openvpnConfig.value(config_key::additional_client_config).toString(protocols::openvpn::defaultAdditionalClientConfig) } });
openvpnConfig.value(config_key::additional_client_config)
.toString(protocols::openvpn::defaultAdditionalClientConfig) } });
vars.append({ { "$OPENVPN_ADDITIONAL_SERVER_CONFIG",
openvpnConfig.value(config_key::additional_server_config).toString(protocols::openvpn::defaultAdditionalServerConfig) } });
openvpnConfig.value(config_key::additional_server_config)
.toString(protocols::openvpn::defaultAdditionalServerConfig) } });
// ShadowSocks vars
vars.append({ { "$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) } });
vars.append({ { "$SHADOWSOCKS_SERVER_PORT",
ssConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) } });
vars.append({ { "$SHADOWSOCKS_LOCAL_PORT",
ssConfig.value(config_key::local_port).toString(protocols::shadowsocks::defaultLocalProxyPort) } });
vars.append({ { "$SHADOWSOCKS_CIPHER", ssConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher) } });
vars.append({ { "$SHADOWSOCKS_CIPHER",
ssConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher) } });
vars.append({ { "$CONTAINER_NAME", ContainerProps::containerToString(container) } });
vars.append({ { "$DOCKERFILE_FOLDER", "/opt/amnezia/" + ContainerProps::containerToString(container) } });
// Cloak vars
vars.append({ { "$CLOAK_SERVER_PORT", cloakConfig.value(config_key::port).toString(protocols::cloak::defaultPort) } });
vars.append({ { "$FAKE_WEB_SITE_ADDRESS", cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) } });
vars.append({ { "$FAKE_WEB_SITE_ADDRESS",
cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) } });
// Xray vars
vars.append({ { "$XRAY_SITE_NAME", xrayConfig.value(config_key::site).toString(protocols::xray::defaultSite) } });
vars.append({ { "$XRAY_SITE_NAME",
xrayConfig.value(config_key::site).toString(protocols::xray::defaultSite) } });
// Wireguard vars
vars.append({ { "$WIREGUARD_SUBNET_IP",
wireguarConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) } });
vars.append(
{ { "$WIREGUARD_SUBNET_IP",
wireguarConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) } });
vars.append({ { "$WIREGUARD_SUBNET_CIDR",
wireguarConfig.value(config_key::subnet_cidr).toString(protocols::wireguard::defaultSubnetCidr) } });
vars.append({ { "$WIREGUARD_SUBNET_MASK",
wireguarConfig.value(config_key::subnet_mask).toString(protocols::wireguard::defaultSubnetMask) } });
vars.append({ { "$WIREGUARD_SERVER_PORT", wireguarConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) } });
vars.append({ { "$WIREGUARD_SERVER_PORT",
wireguarConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) } });
// IPsec vars
vars.append({ { "$IPSEC_VPN_L2TP_NET", "192.168.42.0/24" } });
@@ -591,22 +625,30 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
vars.append({ { "$SECONDARY_SERVER_DNS", m_settings->secondaryDns() } });
// Sftp vars
vars.append({ { "$SFTP_PORT", sftpConfig.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Proto::Sftp))) } });
vars.append(
{ { "$SFTP_PORT",
sftpConfig.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Proto::Sftp))) } });
vars.append({ { "$SFTP_USER", sftpConfig.value(config_key::userName).toString() } });
vars.append({ { "$SFTP_PASSWORD", sftpConfig.value(config_key::password).toString() } });
// Amnezia wireguard vars
vars.append({ { "$AWG_SERVER_PORT", amneziaWireguarConfig.value(config_key::port).toString(protocols::awg::defaultPort) } });
vars.append({ { "$AWG_SERVER_PORT",
amneziaWireguarConfig.value(config_key::port).toString(protocols::awg::defaultPort) } });
vars.append({ { "$JUNK_PACKET_COUNT", amneziaWireguarConfig.value(config_key::junkPacketCount).toString() } });
vars.append({ { "$JUNK_PACKET_MIN_SIZE", amneziaWireguarConfig.value(config_key::junkPacketMinSize).toString() } });
vars.append({ { "$JUNK_PACKET_MAX_SIZE", amneziaWireguarConfig.value(config_key::junkPacketMaxSize).toString() } });
vars.append({ { "$INIT_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::initPacketJunkSize).toString() } });
vars.append({ { "$RESPONSE_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::responsePacketJunkSize).toString() } });
vars.append({ { "$INIT_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::initPacketMagicHeader).toString() } });
vars.append({ { "$RESPONSE_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::responsePacketMagicHeader).toString() } });
vars.append({ { "$UNDERLOAD_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::underloadPacketMagicHeader).toString() } });
vars.append({ { "$TRANSPORT_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::transportPacketMagicHeader).toString() } });
vars.append({ { "$RESPONSE_PACKET_JUNK_SIZE",
amneziaWireguarConfig.value(config_key::responsePacketJunkSize).toString() } });
vars.append({ { "$INIT_PACKET_MAGIC_HEADER",
amneziaWireguarConfig.value(config_key::initPacketMagicHeader).toString() } });
vars.append({ { "$RESPONSE_PACKET_MAGIC_HEADER",
amneziaWireguarConfig.value(config_key::responsePacketMagicHeader).toString() } });
vars.append({ { "$UNDERLOAD_PACKET_MAGIC_HEADER",
amneziaWireguarConfig.value(config_key::underloadPacketMagicHeader).toString() } });
vars.append({ { "$TRANSPORT_PACKET_MAGIC_HEADER",
amneziaWireguarConfig.value(config_key::transportPacketMagicHeader).toString() } });
QString serverIp = NetworkUtilities::getIPAddress(credentials.hostName);
if (!serverIp.isEmpty()) {
@@ -642,7 +684,9 @@ void ServerController::cancelInstallation()
ErrorCode ServerController::setupServerFirewall(const ServerCredentials &credentials)
{
return runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::setup_host_firewall), genVarsForScript(credentials)));
return runScript(
credentials,
replaceVars(amnezia::scriptData(SharedScriptType::setup_host_firewall), genVarsForScript(credentials)));
}
QString ServerController::replaceVars(const QString &script, const Vars &vars)
@@ -654,7 +698,8 @@ QString ServerController::replaceVars(const QString &script, const Vars &vars)
return s;
}
ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &config)
{
if (container == DockerContainer::Dns) {
return ErrorCode::NoError;
@@ -677,12 +722,15 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
QStringList fixedPorts = ContainerProps::fixedPortsForContainer(container);
QString defaultPort("%1");
QString port = containerConfig.value(config_key::port).toString(defaultPort.arg(ProtocolProps::defaultPort(protocol)));
QString defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(protocol), protocol);
QString port =
containerConfig.value(config_key::port).toString(defaultPort.arg(ProtocolProps::defaultPort(protocol)));
QString defaultTransportProto =
ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(protocol), protocol);
QString transportProto = containerConfig.value(config_key::transport_proto).toString(defaultTransportProto);
// TODO reimplement with netstat
QString script = QString("which lsof &>/dev/null || true && sudo lsof -i -P -n 2>/dev/null | grep -E ':%1 ").arg(port);
QString script =
QString("which lsof &>/dev/null || true && sudo lsof -i -P -n 2>/dev/null | grep -E ':%1 ").arg(port);
for (auto &port : fixedPorts) {
script = script.append("|:%1").arg(port);
}
@@ -692,7 +740,8 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
script = script.append(" | grep LISTEN");
}
ErrorCode errorCode = runScript(credentials, replaceVars(script, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
ErrorCode errorCode = runScript(credentials, replaceVars(script, genVarsForScript(credentials, container)),
cbReadStdOut, cbReadStdErr);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
@@ -720,7 +769,8 @@ ErrorCode ServerController::isUserInSudo(const ServerCredentials &credentials, D
};
const QString scriptData = amnezia::scriptData(SharedScriptType::check_user_in_sudo);
ErrorCode error = runScript(credentials, replaceVars(scriptData, genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr);
ErrorCode error =
runScript(credentials, replaceVars(scriptData, genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr);
if (!stdOut.contains("sudo"))
return ErrorCode::ServerUserNotInSudo;
@@ -750,7 +800,9 @@ ErrorCode ServerController::isServerDpkgBusy(const ServerCredentials &credential
return ErrorCode::ServerCancelInstallation;
}
stdOut.clear();
runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), genVarsForScript(credentials)),
runScript(credentials,
replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy),
genVarsForScript(credentials)),
cbReadStdOut, cbReadStdErr);
if (stdOut.contains("Packet manager not found"))

View File

@@ -25,18 +25,19 @@ public:
ErrorCode rebootServer(const ServerCredentials &credentials);
ErrorCode removeAllContainers(const ServerCredentials &credentials);
ErrorCode removeContainer(const ServerCredentials &credentials, DockerContainer container);
ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config, bool isUpdate = false);
ErrorCode updateContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &oldConfig,
QJsonObject &newConfig);
ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config,
bool isUpdate = false);
ErrorCode updateContainer(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &oldConfig, QJsonObject &newConfig);
ErrorCode startupContainerWorker(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &config = QJsonObject());
ErrorCode uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials, const QString &file,
const QString &path,
libssh::ScpOverwriteMode overwriteMode = libssh::ScpOverwriteMode::ScpOverwriteExisting);
QByteArray getTextFileFromContainer(DockerContainer container, const ServerCredentials &credentials, const QString &path,
ErrorCode errorCode);
ErrorCode uploadTextFileToContainer(
DockerContainer container, const ServerCredentials &credentials, const QString &file, const QString &path,
libssh::ScpOverwriteMode overwriteMode = libssh::ScpOverwriteMode::ScpOverwriteExisting);
QByteArray getTextFileFromContainer(DockerContainer container, const ServerCredentials &credentials,
const QString &path, ErrorCode errorCode);
QString replaceVars(const QString &script, const Vars &vars);
Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None,
@@ -46,9 +47,10 @@ public:
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdOut = nullptr,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr = nullptr);
ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdOut = nullptr,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr = nullptr);
ErrorCode
runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdOut = nullptr,
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr = nullptr);
QString checkSshConnection(const ServerCredentials &credentials, ErrorCode errorCode);
@@ -59,14 +61,18 @@ public:
private:
ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &config = QJsonObject());
ErrorCode buildContainerWorker(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &config = QJsonObject());
ErrorCode runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config);
ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config);
ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container,
QJsonObject &config);
ErrorCode isServerPortBusy(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config);
bool isReinstallContainerRequired(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig);
ErrorCode isServerPortBusy(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &config);
bool isReinstallContainerRequired(DockerContainer container, const QJsonObject &oldConfig,
const QJsonObject &newConfig);
ErrorCode isUserInSudo(const ServerCredentials &credentials, DockerContainer container);
ErrorCode isServerDpkgBusy(const ServerCredentials &credentials, DockerContainer container);

View File

@@ -8,22 +8,21 @@
#include "configurators/wireguard_configurator.h"
#include "configurators/xray_configurator.h"
VpnConfigurationsController::VpnConfigurationsController(const std::shared_ptr<Settings> &settings,
QSharedPointer<ServerController> serverController, QObject *parent)
: QObject { parent }, m_settings(settings), m_serverController(serverController)
VpnConfigurationsController::VpnConfigurationsController(const std::shared_ptr<Settings> &settings, QObject *parent)
: QObject { parent }, m_settings(settings)
{
}
QScopedPointer<ConfiguratorBase> VpnConfigurationsController::createConfigurator(const Proto protocol)
{
switch (protocol) {
case Proto::OpenVpn: return QScopedPointer<ConfiguratorBase>(new OpenVpnConfigurator(m_settings, m_serverController));
case Proto::ShadowSocks: return QScopedPointer<ConfiguratorBase>(new ShadowSocksConfigurator(m_settings, m_serverController));
case Proto::Cloak: return QScopedPointer<ConfiguratorBase>(new CloakConfigurator(m_settings, m_serverController));
case Proto::WireGuard: return QScopedPointer<ConfiguratorBase>(new WireguardConfigurator(m_settings, m_serverController, false));
case Proto::Awg: return QScopedPointer<ConfiguratorBase>(new AwgConfigurator(m_settings, m_serverController));
case Proto::Ikev2: return QScopedPointer<ConfiguratorBase>(new Ikev2Configurator(m_settings, m_serverController));
case Proto::Xray: return QScopedPointer<ConfiguratorBase>(new XrayConfigurator(m_settings, m_serverController));
case Proto::OpenVpn: return QScopedPointer<ConfiguratorBase>(new OpenVpnConfigurator(m_settings));
case Proto::ShadowSocks: return QScopedPointer<ConfiguratorBase>(new ShadowSocksConfigurator(m_settings));
case Proto::Cloak: return QScopedPointer<ConfiguratorBase>(new CloakConfigurator(m_settings));
case Proto::WireGuard: return QScopedPointer<ConfiguratorBase>(new WireguardConfigurator(m_settings, false));
case Proto::Awg: return QScopedPointer<ConfiguratorBase>(new AwgConfigurator(m_settings));
case Proto::Ikev2: return QScopedPointer<ConfiguratorBase>(new Ikev2Configurator(m_settings));
case Proto::Xray: return QScopedPointer<ConfiguratorBase>(new XrayConfigurator(m_settings));
default: return QScopedPointer<ConfiguratorBase>();
}
}

View File

@@ -12,7 +12,7 @@ class VpnConfigurationsController : public QObject
{
Q_OBJECT
public:
explicit VpnConfigurationsController(const std::shared_ptr<Settings> &settings, QSharedPointer<ServerController> serverController, QObject *parent = nullptr);
explicit VpnConfigurationsController(const std::shared_ptr<Settings> &settings, QObject *parent = nullptr);
public slots:
ErrorCode createProtocolConfigForContainer(const ServerCredentials &credentials, const DockerContainer container,
@@ -30,7 +30,6 @@ private:
QScopedPointer<ConfiguratorBase> createConfigurator(const Proto protocol);
std::shared_ptr<Settings> m_settings;
QSharedPointer<ServerController> m_serverController;
};
#endif // VPNCONFIGIRATIONSCONTROLLER_H

View File

@@ -23,13 +23,6 @@ namespace libssh {
ErrorCode Client::connectToHost(const ServerCredentials &credentials)
{
if (m_session != nullptr) {
if (!ssh_is_connected(m_session)) {
ssh_free(m_session);
m_session = nullptr;
}
}
if (m_session == nullptr) {
m_session = ssh_new();

View File

@@ -248,10 +248,9 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
GETVALUE("privateKey", config.m_privateKey, String);
GETVALUE("serverPublicKey", config.m_serverPublicKey, String);
GETVALUE("serverPskKey", config.m_serverPskKey, String);
GETVALUE("serverPort", config.m_serverPort, Double);
config.m_serverPskKey = obj.value("serverPskKey").toString();
if (!obj.contains("deviceMTU") || obj.value("deviceMTU").toString().toInt() == 0)
{
config.m_deviceMTU = 1420;
@@ -374,33 +373,19 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
return false;
}
config.m_killSwitchEnabled = QVariant(obj.value("killSwitchOption").toString()).toBool();
if (!obj.value("Jc").isNull()) {
if (!obj.value("Jc").isNull() && !obj.value("Jmin").isNull()
&& !obj.value("Jmax").isNull() && !obj.value("S1").isNull()
&& !obj.value("S2").isNull() && !obj.value("H1").isNull()
&& !obj.value("H2").isNull() && !obj.value("H3").isNull()
&& !obj.value("H4").isNull()) {
config.m_junkPacketCount = obj.value("Jc").toString();
}
if (!obj.value("Jmin").isNull()) {
config.m_junkPacketMinSize = obj.value("Jmin").toString();
}
if (!obj.value("Jmax").isNull()) {
config.m_junkPacketMaxSize = obj.value("Jmax").toString();
}
if (!obj.value("S1").isNull()) {
config.m_initPacketJunkSize = obj.value("S1").toString();
}
if (!obj.value("S2").isNull()) {
config.m_responsePacketJunkSize = obj.value("S2").toString();
}
if (!obj.value("H1").isNull()) {
config.m_initPacketMagicHeader = obj.value("H1").toString();
}
if (!obj.value("H2").isNull()) {
config.m_responsePacketMagicHeader = obj.value("H2").toString();
}
if (!obj.value("H3").isNull()) {
config.m_underloadPacketMagicHeader = obj.value("H3").toString();
}
if (!obj.value("H4").isNull()) {
config.m_transportPacketMagicHeader = obj.value("H4").toString();
}

View File

@@ -37,7 +37,6 @@ class InterfaceConfig {
QList<IPAddress> m_allowedIPAddressRanges;
QStringList m_excludedAddresses;
QStringList m_vpnDisabledApps;
bool m_killSwitchEnabled;
#if defined(MZ_ANDROID) || defined(MZ_IOS)
QString m_installationId;
#endif

View File

@@ -221,9 +221,7 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
json.insert("excludedAddresses", jsExcludedAddresses);
json.insert("vpnDisabledApps", splitTunnelApps);
json.insert(amnezia::config_key::killSwitchOption, rawConfig.value(amnezia::config_key::killSwitchOption));
if (protocolName == amnezia::config_key::awg) {
json.insert(amnezia::config_key::junkPacketCount, wgConfig.value(amnezia::config_key::junkPacketCount));
json.insert(amnezia::config_key::junkPacketMinSize, wgConfig.value(amnezia::config_key::junkPacketMinSize));
@@ -234,24 +232,6 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
json.insert(amnezia::config_key::responsePacketMagicHeader, wgConfig.value(amnezia::config_key::responsePacketMagicHeader));
json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader));
json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader));
} else if (!wgConfig.value(amnezia::config_key::junkPacketCount).isUndefined()
&& !wgConfig.value(amnezia::config_key::junkPacketMinSize).isUndefined()
&& !wgConfig.value(amnezia::config_key::junkPacketMaxSize).isUndefined()
&& !wgConfig.value(amnezia::config_key::initPacketJunkSize).isUndefined()
&& !wgConfig.value(amnezia::config_key::responsePacketJunkSize).isUndefined()
&& !wgConfig.value(amnezia::config_key::initPacketMagicHeader).isUndefined()
&& !wgConfig.value(amnezia::config_key::responsePacketMagicHeader).isUndefined()
&& !wgConfig.value(amnezia::config_key::underloadPacketMagicHeader).isUndefined()
&& !wgConfig.value(amnezia::config_key::transportPacketMagicHeader).isUndefined()) {
json.insert(amnezia::config_key::junkPacketCount, wgConfig.value(amnezia::config_key::junkPacketCount));
json.insert(amnezia::config_key::junkPacketMinSize, wgConfig.value(amnezia::config_key::junkPacketMinSize));
json.insert(amnezia::config_key::junkPacketMaxSize, wgConfig.value(amnezia::config_key::junkPacketMaxSize));
json.insert(amnezia::config_key::initPacketJunkSize, wgConfig.value(amnezia::config_key::initPacketJunkSize));
json.insert(amnezia::config_key::responsePacketJunkSize, wgConfig.value(amnezia::config_key::responsePacketJunkSize));
json.insert(amnezia::config_key::initPacketMagicHeader, wgConfig.value(amnezia::config_key::initPacketMagicHeader));
json.insert(amnezia::config_key::responsePacketMagicHeader, wgConfig.value(amnezia::config_key::responsePacketMagicHeader));
json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader));
json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader));
}
write(json);

View File

@@ -171,15 +171,9 @@ void NetworkWatcher::unsecuredNetwork(const QString& networkName,
}
QNetworkInformation::Reachability NetworkWatcher::getReachability() {
if (m_simulatedDisconnection) {
return QNetworkInformation::Reachability::Disconnected;
} else if (QNetworkInformation::instance()) {
return QNetworkInformation::instance()->reachability();
}
return QNetworkInformation::Reachability::Unknown;
}
void NetworkWatcher::simulateDisconnection(bool simulatedDisconnection) {
m_simulatedDisconnection = simulatedDisconnection;
QString NetworkWatcher::getCurrentTransport() {
auto type = m_impl->getTransportType();
QMetaEnum metaEnum = QMetaEnum::fromType<NetworkWatcherImpl::TransportType>();
return QString(metaEnum.valueToKey(type))
.remove("TransportType_", Qt::CaseSensitive);
}

View File

@@ -7,50 +7,45 @@
#include <QElapsedTimer>
#include <QMap>
#include <QNetworkInformation>
#include <QObject>
class NetworkWatcherImpl;
// This class watches for network changes to detect unsecured wifi.
class NetworkWatcher final : public QObject {
Q_OBJECT
Q_DISABLE_COPY_MOVE(NetworkWatcher)
Q_OBJECT
Q_DISABLE_COPY_MOVE(NetworkWatcher)
public:
NetworkWatcher();
~NetworkWatcher();
public:
NetworkWatcher();
~NetworkWatcher();
void initialize();
void initialize();
// Public for the Inspector.
void unsecuredNetwork(const QString& networkName, const QString& networkId);
// Used for the Inspector. simulateOffline = true to mock being disconnected,
// false to restore.
void simulateDisconnection(bool simulatedDisconnection);
// public for the inspector.
void unsecuredNetwork(const QString& networkName, const QString& networkId);
QNetworkInformation::Reachability getReachability();
QString getCurrentTransport();
signals:
void networkChange();
signals:
void networkChange();
private:
void settingsChanged();
private:
void settingsChanged();
private:
bool m_active = false;
bool m_reportUnsecuredNetwork = false;
// void notificationClicked(NotificationHandler::Message message);
// Platform-specific implementation.
NetworkWatcherImpl* m_impl = nullptr;
private:
bool m_active = false;
bool m_reportUnsecuredNetwork = false;
QMap<QString, QElapsedTimer> m_networks;
// Platform-specific implementation.
NetworkWatcherImpl* m_impl = nullptr;
// This is used to connect NotificationHandler lazily.
bool m_firstNotification = true;
QMap<QString, QElapsedTimer> m_networks;
// Used to simulate network disconnection in the Inspector
bool m_simulatedDisconnection = false;
// This is used to connect NotificationHandler lazily.
bool m_firstNotification = true;
};
#endif // NETWORKWATCHER_H

View File

@@ -5,45 +5,50 @@
#ifndef NETWORKWATCHERIMPL_H
#define NETWORKWATCHERIMPL_H
#include <QNetworkInformation>
#include <QObject>
class NetworkWatcherImpl : public QObject {
Q_OBJECT
Q_DISABLE_COPY_MOVE(NetworkWatcherImpl)
Q_OBJECT
Q_DISABLE_COPY_MOVE(NetworkWatcherImpl)
public:
NetworkWatcherImpl(QObject* parent) : QObject(parent) {}
public:
NetworkWatcherImpl(QObject* parent) : QObject(parent) {}
virtual ~NetworkWatcherImpl() = default;
virtual ~NetworkWatcherImpl() = default;
virtual void initialize() = 0;
virtual void initialize() = 0;
virtual void start() { m_active = true; }
virtual void stop() { m_active = false; }
virtual void start() { m_active = true; }
virtual void stop() { m_active = false; }
bool isActive() const { return m_active; }
bool isActive() const { return m_active; }
enum TransportType {
TransportType_Unknown = 0,
TransportType_Ethernet = 1,
TransportType_WiFi = 2,
TransportType_Cellular = 3, // In Case the API does not retun the gsm type
TransportType_Other = 4, // I.e USB thethering
TransportType_None = 5 // I.e Airplane Mode or no active network device
};
Q_ENUM(TransportType);
enum TransportType {
TransportType_Unknown = 0,
TransportType_Ethernet = 1,
TransportType_WiFi = 2,
TransportType_Cellular = 3, // In Case the API does not retun the gsm type
TransportType_Other = 4, // I.e USB thethering
TransportType_None = 5 // I.e Airplane Mode or no active network device
};
Q_ENUM(TransportType);
signals:
// Fires when the Device Connects to an unsecured Network
void unsecuredNetwork(const QString& networkName, const QString& networkId);
// Fires on when the connected WIFI Changes
// TODO: Only windows-networkwatcher has this, the other plattforms should
// too.
void networkChanged(QString newBSSID);
// Returns the current type of Network Connection
virtual TransportType getTransportType() = 0;
private:
bool m_active = false;
signals:
// Fires when the Device Connects to an unsecured Network
void unsecuredNetwork(const QString& networkName, const QString& networkId);
// Fires on when the connected WIFI Changes
// TODO: Only windows-networkwatcher has this, the other plattforms should
// too.
void networkChanged(QString newBSSID);
// Fired when the Device changed the Type of Transport
void transportChanged(NetworkWatcherImpl::TransportType transportType);
private:
bool m_active = false;
};
#endif // NETWORKWATCHERIMPL_H

View File

@@ -8,11 +8,11 @@
DummyNetworkWatcher::DummyNetworkWatcher(QObject* parent)
: NetworkWatcherImpl(parent) {
MZ_COUNT_CTOR(DummyNetworkWatcher);
MZ_COUNT_CTOR(DummyNetworkWatcher);
}
DummyNetworkWatcher::~DummyNetworkWatcher() {
MZ_COUNT_DTOR(DummyNetworkWatcher);
MZ_COUNT_DTOR(DummyNetworkWatcher);
}
void DummyNetworkWatcher::initialize() {}

View File

@@ -8,11 +8,15 @@
#include "networkwatcherimpl.h"
class DummyNetworkWatcher final : public NetworkWatcherImpl {
public:
DummyNetworkWatcher(QObject* parent);
~DummyNetworkWatcher();
public:
DummyNetworkWatcher(QObject* parent);
~DummyNetworkWatcher();
void initialize() override;
void initialize() override;
NetworkWatcherImpl::TransportType getTransportType() override {
return TransportType_Other;
};
};
#endif // DUMMYNETWORKWATCHER_H

View File

@@ -16,11 +16,6 @@ struct Log {
private static let appGroupID = "group.org.amnezia.AmneziaVPN"
static let appLogURL = {
let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)!
return sharedContainerURL.appendingPathComponent("app.log", isDirectory: false)
}()
static let neLogURL = {
let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)!
return sharedContainerURL.appendingPathComponent("ne.log", isDirectory: false)
@@ -75,12 +70,8 @@ struct Log {
}
static func log(_ type: OSLogType, title: String = "", message: String, url: URL = neLogURL) {
NSLog("\(title) \(message)")
guard isLoggingEnabled else { return }
osLog.log(level: type, "\(title) \(message)")
let date = Date()
let level = Record.Level(from: type)
let messages = message.split(whereSeparator: \.isNewline)
@@ -116,7 +107,3 @@ extension Log: CustomStringConvertible {
.joined(separator: "\n")
}
}
func log(_ type: OSLogType, title: String = "", message: String) {
Log.log(type, title: "App: \(title)", message: message, url: Log.appLogURL)
}

View File

@@ -1,33 +1,50 @@
import Foundation
import NetworkExtension
public func swiftUpdateLogData(_ qtString: std.string) -> std.string {
let qtLog = Log(String(describing: qtString))
var log = qtLog
if let appLog = Log(at: Log.appLogURL) {
appLog.records.forEach {
log.records.append($0)
}
}
if let neLog = Log(at: Log.neLogURL) {
neLog.records.forEach {
log.records.append($0)
}
}
log.records.sort {
$0.date < $1.date
log.records.sort {
$0.date < $1.date
}
}
return std.string(log.description)
}
public func swiftDeleteLog() {
Log.clear(at: Log.appLogURL)
Log.clear(at: Log.neLogURL)
}
public func toggleLogging(_ isEnabled: Bool) {
Log.isLoggingEnabled = isEnabled
}
public func clearSettings() {
NETunnelProviderManager.loadAllFromPreferences { managers, error in
if let error {
NSLog("clearSettings removeFromPreferences error: \(error.localizedDescription)")
return
}
managers?.forEach { manager in
manager.removeFromPreferences { error in
if let error {
NSLog("NE removeFromPreferences error: \(error.localizedDescription)")
} else {
manager.loadFromPreferences { error in
if let error {
NSLog("NE loadFromPreferences after remove error: \(error.localizedDescription)")
}
}
}
}
}
}
}

View File

@@ -94,8 +94,6 @@ extension PacketTunnelProvider {
}
func stopOpenVPN(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
ovpnLog(.info, message: "Stopping tunnel: reason: \(reason.description)")
stopHandler = completionHandler
if vpnReachability.isTracking {
vpnReachability.stopTracking()

View File

@@ -200,7 +200,7 @@ extension PacketTunnelProvider {
// }
func stopWireguard(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
wg_log(.info, message: "Stopping tunnel: reason: \(reason.description)")
wg_log(.info, staticMessage: "Stopping tunnel")
wgAdapter.stop { error in
ErrorNotifier.removeLastErrorFile()

View File

@@ -200,46 +200,3 @@ extension WireGuardLogLevel {
}
}
}
extension NEProviderStopReason: CustomStringConvertible {
public var description: String {
switch self {
case .none:
return "No specific reason"
case .userInitiated:
return "The user stopped the NE"
case .providerFailed:
return "The NE failed to function correctly"
case .noNetworkAvailable:
return "No network connectivity is currently available"
case .unrecoverableNetworkChange:
return "The devices network connectivity changed"
case .providerDisabled:
return "The NE was disabled"
case .authenticationCanceled:
return "The authentication process was canceled"
case .configurationFailed:
return "The VPNC is invalid"
case .idleTimeout:
return "The session timed out"
case .configurationDisabled:
return "The VPNC was disabled"
case .configurationRemoved:
return "The VPNC was removed"
case .superceded:
return "VPNC was superceded by a higher-priority VPNC"
case .userLogout:
return "The user logged out"
case .userSwitch:
return "The current console user changed"
case .connectionFailed:
return "The connection failed"
case .sleep:
return "A stop reason indicating the VPNC enabled disconnect on sleep and the device went to sleep"
case .appUpdate:
return "appUpdat"
@unknown default:
return "@unknown default"
}
}
}

View File

@@ -1,50 +0,0 @@
import Foundation
import NetworkExtension
public func removeVPNC(_ vpncName: std.string) {
let vpncName = String(describing: vpncName)
Task {
await getManagers()?.first { manager in
if let name = manager.localizedDescription, name == vpncName {
Task {
await remove(manager)
}
return true
} else {
return false
}
}
}
}
public func clearSettings() {
Task {
await getManagers()?.forEach { manager in
Task {
await remove(manager)
}
}
}
}
func getManagers() async -> [NETunnelProviderManager]? {
do {
return try await NETunnelProviderManager.loadAllFromPreferences()
} catch {
log(.error, title: "VPNC: ", message: "loadAllFromPreferences error: \(error.localizedDescription)")
return nil
}
}
func remove(_ manager: NETunnelProviderManager) async {
let vpncName = manager.localizedDescription ?? "Unknown"
do {
try await manager.removeFromPreferences()
try await manager.loadFromPreferences()
log(.info, title: "VPNC: ", message: "Remove \(vpncName)")
} catch {
log(.error, title: "VPNC: ", message: "Failed to remove \(vpncName) (\(error.localizedDescription))")
}
}

View File

@@ -86,9 +86,6 @@ struct WGConfig: Decodable {
AllowedIPs = \(allowedIPs.joined(separator: ", "))
Endpoint = \(hostName):\(port)
PersistentKeepalive = \(persistentKeepAlive)
SplitTunnelType = \(splitTunnelType)
SplitTunnelSites = \(splitTunnelSites.joined(separator: ", "))
"""
}
}

View File

@@ -89,11 +89,9 @@ bool IosController::initialize()
for (NETunnelProviderManager *manager in managers) {
qDebug() << "IosController::initialize : VPNC: " << manager.localizedDescription;
if (manager.connection.status == NEVPNStatusConnected) {
m_currentTunnel = manager;
qDebug() << "IosController::initialize : VPN already connected with" << manager.localizedDescription;
qDebug() << "IosController::initialize : VPN already connected";
emit connectionStateChanged(Vpn::ConnectionState::Connected);
break;
@@ -140,7 +138,7 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
@try {
if (error) {
qDebug() << "IosController::connectVpn : VPNC: loadAllFromPreferences error:" << [error.localizedDescription UTF8String];
qDebug() << "IosController::connectVpn : Error:" << [error.localizedDescription UTF8String];
emit connectionStateChanged(Vpn::ConnectionState::Error);
ok = false;
return;
@@ -153,7 +151,7 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
for (NETunnelProviderManager *manager in managers) {
if ([manager.localizedDescription isEqualToString:tunnelName.toNSString()]) {
m_currentTunnel = manager;
qDebug() << "IosController::connectVpn : Using existing tunnel:" << manager.localizedDescription;
qDebug() << "IosController::connectVpn : Using existing tunnel";
if (manager.connection.status == NEVPNStatusConnected) {
emit connectionStateChanged(Vpn::ConnectionState::Connected);
return;
@@ -164,10 +162,10 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
}
if (!m_currentTunnel) {
qDebug() << "IosController::connectVpn : Creating new tunnel";
isNewTunnelCreated = true;
m_currentTunnel = [[NETunnelProviderManager alloc] init];
m_currentTunnel.localizedDescription = [NSString stringWithUTF8String:tunnelName.toStdString().c_str()];
qDebug() << "IosController::connectVpn : Creating new tunnel" << m_currentTunnel.localizedDescription;
}
}
@@ -600,14 +598,13 @@ void IosController::startTunnel()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (saveError) {
qDebug().nospace() << "IosController::startTunnel" << protocolName << ": Connect " << protocolName << " Tunnel Save Error" << saveError.localizedDescription.UTF8String;
emit connectionStateChanged(Vpn::ConnectionState::Error);
return;
}
[m_currentTunnel loadFromPreferencesWithCompletionHandler:^(NSError *loadError) {
if (loadError) {
qDebug().nospace() << "IosController::startTunnel :" << m_currentTunnel.localizedDescription << protocolName << ": Connect " << protocolName << " Tunnel Load Error" << loadError.localizedDescription.UTF8String;
qDebug().nospace() << "IosController::start" << protocolName << ": Connect " << protocolName << " Tunnel Load Error" << loadError.localizedDescription.UTF8String;
emit connectionStateChanged(Vpn::ConnectionState::Error);
return;
}
@@ -618,11 +615,11 @@ void IosController::startTunnel()
BOOL started = [m_currentTunnel.connection startVPNTunnelWithOptions:nil andReturnError:&startError];
if (!started || startError) {
qDebug().nospace() << "IosController::startTunnel :" << m_currentTunnel.localizedDescription << protocolName << " : Connect " << protocolName << " Tunnel Start Error"
qDebug().nospace() << "IosController::start" << protocolName << " : Connect " << protocolName << " Tunnel Start Error"
<< (startError ? startError.localizedDescription.UTF8String : "");
emit connectionStateChanged(Vpn::ConnectionState::Error);
} else {
qDebug().nospace() << "IosController::startTunnel :" << m_currentTunnel.localizedDescription << protocolName << " : Starting the tunnel succeeded";
qDebug().nospace() << "IosController::start" << protocolName << " : Starting the tunnel succeeded";
}
}];
});

View File

@@ -15,6 +15,7 @@ class IOSNetworkWatcher : public NetworkWatcherImpl {
~IOSNetworkWatcher();
void initialize() override;
NetworkWatcherImpl::TransportType getTransportType() override;
private:
NetworkWatcherImpl::TransportType toTransportType(nw_path_t path);

View File

@@ -37,6 +37,16 @@ void IOSNetworkWatcher::initialize() {
//TODO IMPL FOR AMNEZIA
}
NetworkWatcherImpl::TransportType IOSNetworkWatcher::getTransportType() {
//TODO IMPL FOR AMNEZIA
if (m_observableConnection != nil) {
return m_currentVPNTransport;
}
// If we don't have an open tunnel-observer, m_currentVPNTransport is probably wrong.
return NetworkWatcherImpl::TransportType_Unknown;
}
NetworkWatcherImpl::TransportType IOSNetworkWatcher::toTransportType(nw_path_t path) {
if (path == nil) {
return NetworkWatcherImpl::TransportType_Unknown;

View File

@@ -103,32 +103,15 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) {
out << "private_key=" << QString(privateKey.toHex()) << "\n";
out << "replace_peers=true\n";
if (!config.m_junkPacketCount.isEmpty()) {
if (config.m_junkPacketCount != "") {
out << "jc=" << config.m_junkPacketCount << "\n";
}
if (!config.m_junkPacketMinSize.isEmpty()) {
out << "jmin=" << config.m_junkPacketMinSize << "\n";
}
if (!config.m_junkPacketMaxSize.isEmpty()) {
out << "jmax=" << config.m_junkPacketMaxSize << "\n";
}
if (!config.m_initPacketJunkSize.isEmpty()) {
out << "s1=" << config.m_initPacketJunkSize << "\n";
}
if (!config.m_responsePacketJunkSize.isEmpty()) {
out << "s2=" << config.m_responsePacketJunkSize << "\n";
}
if (!config.m_initPacketMagicHeader.isEmpty()) {
out << "h1=" << config.m_initPacketMagicHeader << "\n";
}
if (!config.m_responsePacketMagicHeader.isEmpty()) {
out << "h2=" << config.m_responsePacketMagicHeader << "\n";
}
if (!config.m_underloadPacketMagicHeader.isEmpty()) {
out << "h3=" << config.m_underloadPacketMagicHeader << "\n";
}
if (!config.m_transportPacketMagicHeader.isEmpty()) {
out << "h4=" << config.m_transportPacketMagicHeader << "\n";
}
@@ -136,25 +119,24 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) {
if (err != 0) {
logger.error() << "Interface configuration failed:" << strerror(err);
} else {
if (config.m_killSwitchEnabled) {
FirewallParams params { };
params.dnsServers.append(config.m_dnsServer);
if (config.m_allowedIPAddressRanges.at(0).toString() == "0.0.0.0/0"){
params.blockAll = true;
if (config.m_excludedAddresses.size()) {
params.allowNets = true;
foreach (auto net, config.m_excludedAddresses) {
params.allowAddrs.append(net.toUtf8());
}
}
} else {
params.blockNets = true;
foreach (auto net, config.m_allowedIPAddressRanges) {
params.blockAddrs.append(net.toString());
FirewallParams params { };
params.dnsServers.append(config.m_dnsServer);
if (config.m_allowedIPAddressRanges.at(0).toString() == "0.0.0.0/0"){
params.blockAll = true;
if (config.m_excludedAddresses.size()) {
params.allowNets = true;
foreach (auto net, config.m_excludedAddresses) {
params.allowAddrs.append(net.toUtf8());
}
}
applyFirewallRules(params);
} else {
params.blockNets = true;
foreach (auto net, config.m_allowedIPAddressRanges) {
params.blockAddrs.append(net.toString());
}
}
applyFirewallRules(params);
}
return (err == 0);
@@ -200,9 +182,7 @@ bool WireguardUtilsLinux::updatePeer(const InterfaceConfig& config) {
QTextStream out(&message);
out << "set=1\n";
out << "public_key=" << QString(publicKey.toHex()) << "\n";
if (!config.m_serverPskKey.isNull()) {
out << "preshared_key=" << QString(pskKey.toHex()) << "\n";
}
out << "preshared_key=" << QString(pskKey.toHex()) << "\n";
if (!config.m_serverIpv4AddrIn.isNull()) {
out << "endpoint=" << config.m_serverIpv4AddrIn << ":";
} else if (!config.m_serverIpv6AddrIn.isNull()) {

5
client/platforms/linux/linuxnetworkwatcher.h Executable file → Normal file
View File

@@ -22,6 +22,11 @@ class LinuxNetworkWatcher final : public NetworkWatcherImpl {
void start() override;
NetworkWatcherImpl::TransportType getTransportType() {
// TODO: Find out how to do that on linux generally. (VPN-2382)
return NetworkWatcherImpl::TransportType_Unknown;
};
signals:
void checkDevicesInThread();

View File

@@ -95,11 +95,6 @@ void MacosRouteMonitor::handleRtmDelete(const struct rt_msghdr* rtm,
!(rtm->rtm_addrs & RTA_NETMASK) || (addrlist.count() < 3)) {
return;
}
// Ignore interface-scoped routes, we want to find the default route to the
// internet in the global scope.
if (rtm->rtm_flags & RTF_IFSCOPE) {
return;
}
// Check for a default route, which should have a netmask of zero.
const struct sockaddr* sa =
@@ -161,11 +156,6 @@ void MacosRouteMonitor::handleRtmUpdate(const struct rt_msghdr* rtm,
!(rtm->rtm_addrs & RTA_NETMASK) || (addrlist.count() < 3)) {
return;
}
// Ignore interface-scoped routes, we want to find the default route to the
// internet in the global scope.
if (rtm->rtm_flags & RTF_IFSCOPE) {
return;
}
// Ignore route changes that we caused, or routes on the tunnel interface.
if (rtm->rtm_index == m_ifindex) {
return;

View File

@@ -101,31 +101,15 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
out << "private_key=" << QString(privateKey.toHex()) << "\n";
out << "replace_peers=true\n";
if (!config.m_junkPacketCount.isEmpty()) {
if (config.m_junkPacketCount != "") {
out << "jc=" << config.m_junkPacketCount << "\n";
}
if (!config.m_junkPacketMinSize.isEmpty()) {
out << "jmin=" << config.m_junkPacketMinSize << "\n";
}
if (!config.m_junkPacketMaxSize.isEmpty()) {
out << "jmax=" << config.m_junkPacketMaxSize << "\n";
}
if (!config.m_initPacketJunkSize.isEmpty()) {
out << "s1=" << config.m_initPacketJunkSize << "\n";
}
if (!config.m_responsePacketJunkSize.isEmpty()) {
out << "s2=" << config.m_responsePacketJunkSize << "\n";
}
if (!config.m_initPacketMagicHeader.isEmpty()) {
out << "h1=" << config.m_initPacketMagicHeader << "\n";
}
if (!config.m_responsePacketMagicHeader.isEmpty()) {
out << "h2=" << config.m_responsePacketMagicHeader << "\n";
}
if (!config.m_underloadPacketMagicHeader.isEmpty()) {
out << "h3=" << config.m_underloadPacketMagicHeader << "\n";
}
if (!config.m_transportPacketMagicHeader.isEmpty()) {
out << "h4=" << config.m_transportPacketMagicHeader << "\n";
}
@@ -134,26 +118,26 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
if (err != 0) {
logger.error() << "Interface configuration failed:" << strerror(err);
} else {
if (config.m_killSwitchEnabled) {
FirewallParams params { };
params.dnsServers.append(config.m_dnsServer);
if (config.m_allowedIPAddressRanges.at(0).toString() == "0.0.0.0/0"){
params.blockAll = true;
if (config.m_excludedAddresses.size()) {
FirewallParams params { };
params.dnsServers.append(config.m_dnsServer);
if (config.m_allowedIPAddressRanges.at(0).toString() == "0.0.0.0/0"){
params.blockAll = true;
if (config.m_excludedAddresses.size()) {
params.allowNets = true;
foreach (auto net, config.m_excludedAddresses) {
params.allowAddrs.append(net.toUtf8());
params.allowAddrs.append(net.toUtf8());
}
}
} else {
params.blockNets = true;
foreach (auto net, config.m_allowedIPAddressRanges) {
params.blockAddrs.append(net.toString());
}
}
applyFirewallRules(params);
} else {
params.blockNets = true;
foreach (auto net, config.m_allowedIPAddressRanges) {
params.blockAddrs.append(net.toString());
}
}
applyFirewallRules(params);
}
return (err == 0);
}
@@ -199,9 +183,7 @@ bool WireguardUtilsMacos::updatePeer(const InterfaceConfig& config) {
QTextStream out(&message);
out << "set=1\n";
out << "public_key=" << QString(publicKey.toHex()) << "\n";
if (!config.m_serverPskKey.isNull()) {
out << "preshared_key=" << QString(pskKey.toHex()) << "\n";
}
out << "preshared_key=" << QString(pskKey.toHex()) << "\n";
if (!config.m_serverIpv4AddrIn.isNull()) {
out << "endpoint=" << config.m_serverIpv4AddrIn << ":";
} else if (!config.m_serverIpv6AddrIn.isNull()) {

View File

@@ -83,7 +83,7 @@ void MacOSPingSender::sendPing(const QHostAddress& dest, quint16 sequence) {
packet.icmp_seq = htons(sequence);
packet.icmp_cksum = inetChecksum(&packet, sizeof(packet));
if (sendto(m_socket, (char*)&packet, sizeof(packet), MSG_NOSIGNAL,
if (sendto(m_socket, (char*)&packet, sizeof(packet), 0,
(struct sockaddr*)&addr, sizeof(addr)) != sizeof(packet)) {
logger.error() << "ping sending failed:" << strerror(errno);
emit criticalPingError();
@@ -107,9 +107,9 @@ void MacOSPingSender::socketReady() {
iov.iov_base = packet;
iov.iov_len = IP_MAXPACKET;
ssize_t rc = recvmsg(m_socket, &msg, MSG_DONTWAIT | MSG_NOSIGNAL);
ssize_t rc = recvmsg(m_socket, &msg, MSG_DONTWAIT);
if (rc <= 0) {
logger.error() << "Recvmsg failed:" << strerror(errno);
logger.error() << "Recvmsg failed";
return;
}

View File

@@ -41,33 +41,11 @@ void MacOSUtils::enableLoginItem(bool startAtBoot) {
Q_ASSERT(appId);
NSString* loginItemAppId =
QString("%1.login-item").arg(QString::fromNSString(appId)).toNSString();
QString("%1.login-item").arg(QString::fromNSString(appId)).toNSString();
CFStringRef cfs = (__bridge CFStringRef)loginItemAppId;
// For macOS 13 and beyond, register() and unregister() methods
// are used for managing login items since SMLoginItemSetEnabled() is deprecated.
// For versions prior to macOS 13, SMLoginItemSetEnabled() is used.
if (@available(macOS 13, *)) {
// Use register() or unregister() based on the startAtBoot flag
NSError* error = nil;
if (startAtBoot) {
if (![[SMAppService mainAppService] registerAndReturnError: & error]) {
logger.error() << "Failed to register Amnezia VPN LoginItem: " << error.localizedDescription;
} else {
logger.debug() << "Amnezia VPN LoginItem registered successfully.";
}
} else {
if (![[SMAppService mainAppService] unregisterAndReturnError: & error]) {
logger.error() << "Failed to unregister Amnezia VPN LoginItem: " << error.localizedDescription;
} else {
logger.debug() << "LoginItem unregistered successfully.";
}
}
} else {
CFStringRef cfs = (__bridge CFStringRef) loginItemAppId;
Boolean ok = SMLoginItemSetEnabled(cfs, startAtBoot ? YES : NO);
logger.debug() << "Result: " << ok;
}
Boolean ok = SMLoginItemSetEnabled(cfs, startAtBoot ? YES : NO);
logger.debug() << "Result: " << ok;
}
namespace {

View File

@@ -4,11 +4,8 @@
#include "dnsutilswindows.h"
#include <WS2tcpip.h>
#include <iphlpapi.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2ipdef.h>
#include <QProcess>
#include <QTextStream>
@@ -42,27 +39,30 @@ DnsUtilsWindows::~DnsUtilsWindows() {
bool DnsUtilsWindows::updateResolvers(const QString& ifname,
const QList<QHostAddress>& resolvers) {
MIB_IF_ROW2 entry;
if (ConvertInterfaceAliasToLuid((wchar_t*)ifname.utf16(),
&entry.InterfaceLuid) != 0) {
NET_LUID luid;
if (ConvertInterfaceAliasToLuid((wchar_t*)ifname.utf16(), &luid) != 0) {
logger.error() << "Failed to resolve LUID for" << ifname;
return false;
}
if (GetIfEntry2(&entry) != NO_ERROR) {
logger.error() << "Failed to resolve interface for" << ifname;
return false;
}
m_luid = entry.InterfaceLuid.Value;
m_luid = luid.Value;
logger.debug() << "Configuring DNS for" << ifname;
if (m_setInterfaceDnsSettingsProcAddr == nullptr) {
return updateResolversNetsh(entry.InterfaceIndex, resolvers);
return updateResolversNetsh(resolvers);
}
return updateResolversWin32(entry.InterfaceGuid, resolvers);
return updateResolversWin32(resolvers);
}
bool DnsUtilsWindows::updateResolversWin32(
GUID guid, const QList<QHostAddress>& resolvers) {
const QList<QHostAddress>& resolvers) {
GUID guid;
NET_LUID luid;
luid.Value = m_luid;
if (ConvertInterfaceLuidToGuid(&luid, &guid) != NO_ERROR) {
logger.error() << "Failed to resolve GUID";
return false;
}
QStringList v4resolvers;
QStringList v6resolvers;
for (const QHostAddress& addr : resolvers) {
@@ -113,8 +113,16 @@ constexpr const char* netshAddTemplate =
"interface %1 add dnsservers name=%2 address=%3 validate=no\r\n";
bool DnsUtilsWindows::updateResolversNetsh(
int ifindex, const QList<QHostAddress>& resolvers) {
const QList<QHostAddress>& resolvers) {
QProcess netsh;
NET_LUID luid;
NET_IFINDEX ifindex;
luid.Value = m_luid;
if (ConvertInterfaceLuidToIndex(&luid, &ifindex) != NO_ERROR) {
logger.error() << "Failed to resolve GUID";
return false;
}
netsh.setProgram("netsh");
netsh.start();
if (!netsh.waitForStarted(WINDOWS_NETSH_TIMEOUT_MSEC)) {
@@ -158,26 +166,12 @@ bool DnsUtilsWindows::updateResolversNetsh(
bool DnsUtilsWindows::restoreResolvers() {
if (m_luid == 0) {
// If the DNS hasn't been configured, there is nothing to restore.
return true;
}
MIB_IF_ROW2 entry;
DWORD error;
entry.InterfaceLuid.Value = m_luid;
error = GetIfEntry2(&entry);
if (error == ERROR_FILE_NOT_FOUND) {
// If the interface no longer exists, there is nothing to restore.
return true;
}
if (error != NO_ERROR) {
logger.error() << "Failed to resolve interface entry:" << error;
return false;
}
QList<QHostAddress> empty;
if (m_setInterfaceDnsSettingsProcAddr == nullptr) {
return updateResolversNetsh(entry.InterfaceIndex, empty);
return updateResolversNetsh(empty);
}
return updateResolversWin32(entry.InterfaceGuid, empty);
return updateResolversWin32(empty);
}

View File

@@ -27,8 +27,8 @@ class DnsUtilsWindows final : public DnsUtils {
quint64 m_luid = 0;
DWORD (*m_setInterfaceDnsSettingsProcAddr)(GUID, const void*) = nullptr;
bool updateResolversWin32(GUID, const QList<QHostAddress>& resolvers);
bool updateResolversNetsh(int ifindex, const QList<QHostAddress>& resolvers);
bool updateResolversWin32(const QList<QHostAddress>& resolvers);
bool updateResolversNetsh(const QList<QHostAddress>& resolvers);
};
#endif // DNSUTILSWINDOWS_H

View File

@@ -38,6 +38,7 @@ class WindowsDaemon final : public Daemon {
Inactive,
};
State m_state = Inactive;
int m_inetAdapterIndex = -1;
WireguardUtilsWindows* m_wgutils = nullptr;

View File

@@ -114,7 +114,7 @@ void WindowsRouteMonitor::updateValidInterfaces(int family) {
void WindowsRouteMonitor::updateExclusionRoute(MIB_IPFORWARD_ROW2* data,
void* ptable) {
PMIB_IPFORWARD_TABLE2 table = reinterpret_cast<PMIB_IPFORWARD_TABLE2>(ptable);
SOCKADDR_INET nexthop = {};
SOCKADDR_INET nexthop = {0};
quint64 bestLuid = 0;
int bestMatch = -1;
ULONG bestMetric = ULONG_MAX;

View File

@@ -18,7 +18,6 @@
#include <QFileInfo>
#include <QNetworkInterface>
#include <QScopeGuard>
#include <QThread>
namespace {
Logger logger("WindowsSplitTunnel");
@@ -30,9 +29,6 @@ WindowsSplitTunnel::WindowsSplitTunnel(QObject* parent) : QObject(parent) {
uninstallDriver();
return;
}
m_tries = 0;
if (!isInstalled()) {
logger.debug() << "Driver is not Installed, doing so";
auto handle = installDriver();
@@ -63,10 +59,10 @@ void WindowsSplitTunnel::initDriver() {
m_driver = CreateFileW(DRIVER_SYMLINK, GENERIC_READ | GENERIC_WRITE, 0,
nullptr, OPEN_EXISTING, 0, nullptr);
;
if (m_driver == INVALID_HANDLE_VALUE && m_tries < 500) {
if (m_driver == INVALID_HANDLE_VALUE) {
WindowsUtils::windowsLog("Failed to open Driver: ");
m_tries++;
Sleep(100);
// If the handle is not present, try again after the serivce has started;
auto driver_manager = WindowsServiceManager(DRIVER_SERVICE_NAME);
QObject::connect(&driver_manager, &WindowsServiceManager::serviceStarted,

View File

@@ -158,7 +158,6 @@ class WindowsSplitTunnel final : public QObject {
constexpr static const auto MV_SERVICE_NAME = L"MullvadVPN";
DRIVER_STATE getState();
int m_tries;
// Initializes the WFP Sublayer
bool initSublayer();

View File

@@ -39,7 +39,7 @@ Logger logger("tunnel.dll");
WindowsTunnelLogger::WindowsTunnelLogger(const QString& filename,
QObject* parent)
: QObject(parent), m_timer(this), m_logfile(filename, this) {
: QObject(parent), m_logfile(filename, this), m_timer(this) {
MZ_COUNT_CTOR(WindowsTunnelLogger);
m_startTime = QDateTime::currentMSecsSinceEpoch() * 1000000;

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "windowstunnelservice.h"
#include "WindowsTunnelService.h"
#include <Windows.h>
@@ -30,22 +30,12 @@ static bool waitForServiceStatus(SC_HANDLE service, DWORD expectedStatus);
WindowsTunnelService::WindowsTunnelService(QObject* parent) : QObject(parent) {
MZ_COUNT_CTOR(WindowsTunnelService);
logger.debug() << "WindowsTunnelService created.";
m_scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS);
if (m_scm == nullptr) {
WindowsUtils::windowsLog("Failed to open SCManager");
}
// Is the service already running? Terminate it.
SC_HANDLE service =
OpenService((SC_HANDLE)m_scm, TUNNEL_SERVICE_NAME, SERVICE_ALL_ACCESS);
if (service != nullptr) {
logger.info() << "Tunnel already exists. Terminating it.";
stopAndDeleteTunnelService(service);
CloseServiceHandle(service);
}
connect(&m_timer, &QTimer::timeout, this, &WindowsTunnelService::timeout);
}
@@ -148,7 +138,7 @@ bool WindowsTunnelService::start(const QString& configData) {
logger.debug() << "Service:" << qApp->applicationFilePath();
service = CreateService(scm, TUNNEL_SERVICE_NAME, L"Amnezia VPN (tunnel)",
service = CreateService(scm, TUNNEL_SERVICE_NAME, L"Amezia VPN (tunnel)",
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
(const wchar_t*)serviceCmdline.utf16(), nullptr, 0,

View File

@@ -116,12 +116,10 @@ bool WireguardUtilsWindows::addInterface(const InterfaceConfig& config) {
m_luid = luid.Value;
m_routeMonitor.setLuid(luid.Value);
if (config.m_killSwitchEnabled) {
// Enable the windows firewall
NET_IFINDEX ifindex;
ConvertInterfaceLuidToIndex(&luid, &ifindex);
WindowsFirewall::instance()->enableKillSwitch(ifindex);
}
// Enable the windows firewall
NET_IFINDEX ifindex;
ConvertInterfaceLuidToIndex(&luid, &ifindex);
WindowsFirewall::instance()->enableKillSwitch(ifindex);
logger.debug() << "Registration completed";
return true;
@@ -139,10 +137,9 @@ bool WireguardUtilsWindows::updatePeer(const InterfaceConfig& config) {
QByteArray pskKey =
QByteArray::fromBase64(qPrintable(config.m_serverPskKey));
if (config.m_killSwitchEnabled) {
// Enable the windows firewall for this peer.
WindowsFirewall::instance()->enablePeerTraffic(config);
}
// Enable the windows firewall for this peer.
WindowsFirewall::instance()->enablePeerTraffic(config);
logger.debug() << "Configuring peer" << publicKey.toHex()
<< "via" << config.m_serverIpv4AddrIn;
@@ -151,9 +148,7 @@ bool WireguardUtilsWindows::updatePeer(const InterfaceConfig& config) {
QTextStream out(&message);
out << "set=1\n";
out << "public_key=" << QString(publicKey.toHex()) << "\n";
if (!config.m_serverPskKey.isNull()) {
out << "preshared_key=" << QString(pskKey.toHex()) << "\n";
}
out << "preshared_key=" << QString(pskKey.toHex()) << "\n";
if (!config.m_serverIpv4AddrIn.isNull()) {
out << "endpoint=" << config.m_serverIpv4AddrIn << ":";
} else if (!config.m_serverIpv6AddrIn.isNull()) {

View File

@@ -8,7 +8,6 @@
#include <d3d11.h>
#include <dxgi.h>
#include <iphlpapi.h>
#include <shlobj_core.h>
#include <QDir>
#include <QHostAddress>
@@ -20,9 +19,9 @@
#include "logger.h"
#include "platforms/windows/windowsutils.h"
#define TUNNEL_SERVICE_NAME L"WireGuardTunnel$amnvpn"
constexpr const char* VPN_NAME = "AmneziaVPN";
constexpr const char* WIREGUARD_DIR = "WireGuard";
constexpr const char* DATA_DIR = "Data";
namespace {
Logger logger("WindowsCommons");
@@ -68,67 +67,27 @@ QString WindowsCommons::tunnelConfigFile() {
return QString();
}
// static
QString WindowsCommons::tunnelLogFile() {
static QString tunnelLogFilePath = getTunnelLogFilePath();
return tunnelLogFilePath;
}
QStringList paths =
QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
// static
QString WindowsCommons::getProgramFilesPath() {
wchar_t* path = nullptr;
if (SUCCEEDED(
SHGetKnownFolderPath(FOLDERID_ProgramFiles, 0, nullptr, &path))) {
auto guard = qScopeGuard([&] { CoTaskMemFree(path); });
return QString::fromWCharArray(path);
}
return QString();
}
// static
QString WindowsCommons::getTunnelLogFilePath() {
// Return WireGuard's log file path, "\Program Files\WireGuard\Data\log.bin",
// if the directory path exists
auto programFilesPath = getProgramFilesPath();
if (!programFilesPath.isEmpty()) {
QDir programFilesDir(programFilesPath);
if (programFilesDir.exists()) {
QDir wireGuardDir(programFilesDir.filePath(WIREGUARD_DIR));
if (wireGuardDir.exists()) {
QDir wireGuardDataDir(wireGuardDir.filePath(DATA_DIR));
if (wireGuardDataDir.exists()) {
return wireGuardDataDir.filePath("log.bin");
}
}
for (const QString& path : paths) {
QDir dir(path);
if (!dir.exists()) {
continue;
}
QDir vpnDir(dir.filePath(VPN_NAME));
if (!vpnDir.exists()) {
continue;
}
return vpnDir.filePath("log.bin");
}
logger.debug() << "Failed to find WireGuard Tunnel log file";
return QString();
}
// static
int WindowsCommons::AdapterIndexTo(const QHostAddress& dst) {
logger.debug() << "Getting Current Internet Adapter that routes to"
<< logger.sensitive(dst.toString());
quint32_be ipBigEndian;
quint32 ip = dst.toIPv4Address();
qToBigEndian(ip, &ipBigEndian);
_MIB_IPFORWARDROW routeInfo;
auto result = GetBestRoute(ipBigEndian, 0, &routeInfo);
if (result != NO_ERROR) {
return -1;
}
auto adapter =
QNetworkInterface::interfaceFromIndex(routeInfo.dwForwardIfIndex);
logger.debug() << "Internet Adapter:" << adapter.name();
return routeInfo.dwForwardIfIndex;
}
// static
int WindowsCommons::VPNAdapterIndex() {
// For someReason QNetworkInterface::fromName(MozillaVPN) does not work >:(
@@ -143,7 +102,7 @@ int WindowsCommons::VPNAdapterIndex() {
// Static
QString WindowsCommons::getCurrentPath() {
QByteArray buffer(2048, 0xFFu);
QByteArray buffer(2048, 0xFF);
auto ok = GetModuleFileNameA(NULL, buffer.data(), buffer.size());
if (ok == ERROR_INSUFFICIENT_BUFFER) {

View File

@@ -19,14 +19,9 @@ class WindowsCommons final {
// Returns the Interface Index of the VPN Adapter
static int VPNAdapterIndex();
// Returns the Interface Index that could Route to dst
static int AdapterIndexTo(const QHostAddress& dst);
// Returns the Path of the Current process
static QString getCurrentPath();
private:
static QString getTunnelLogFilePath();
static QString getProgramFilesPath();
};
#endif // WINDOWSCOMMONS_H

View File

@@ -4,7 +4,6 @@
#include "windowsnetworkwatcher.h"
#include <QNetworkInformation>
#include <QScopeGuard>
#include "leakdetector.h"
@@ -137,4 +136,9 @@ void WindowsNetworkWatcher::processWlan(PWLAN_NOTIFICATION_DATA data) {
logger.debug() << "Unsecure network:" << logger.sensitive(ssid)
<< "id:" << logger.sensitive(bssid);
emit unsecuredNetwork(ssid, bssid);
}
}
NetworkWatcherImpl::TransportType WindowsNetworkWatcher::getTransportType() {
// TODO: Implement this once we update to Qt6.3 (VPN-3511)
return TransportType_Other;
}

View File

@@ -17,6 +17,8 @@ class WindowsNetworkWatcher final : public NetworkWatcherImpl {
void initialize() override;
NetworkWatcherImpl::TransportType getTransportType() override;
private:
static void wlanCallback(PWLAN_NOTIFICATION_DATA data, PVOID context);

View File

@@ -7,8 +7,6 @@
#include <WS2tcpip.h>
#include <Windows.h>
#include <iphlpapi.h>
#include <winternl.h>
// Note: This important must come after the previous three.
// clang-format off
#include <IcmpAPI.h>
@@ -18,58 +16,17 @@
#include "leakdetector.h"
#include "logger.h"
#include "platforms/windows/windowsutils.h"
#include "windowscommons.h"
#include "platforms/windows/windowsutils.h"
#pragma comment(lib, "Ws2_32")
/*
* On 64 Bit systems we need to use another struct.
*/
#ifdef _WIN64
using MZ_ICMP_ECHO_REPLY = ICMP_ECHO_REPLY32;
#else
using MZ_ICMP_ECHO_REPLY = ICMP_ECHO_REPLY;
#endif
constexpr WORD WindowsPingPayloadSize = sizeof(quint16);
constexpr size_t ICMP_ERR_SIZE = 8;
/*
* IcmpSendEcho2 expects us to provide a Buffer that is
* at least this size
*/
constexpr size_t MinimumReplyBufferSize =
sizeof(ICMP_ECHO_REPLY) + WindowsPingPayloadSize + ICMP_ERR_SIZE +
sizeof(IO_STATUS_BLOCK);
/**
* ICMP_ECHO_REPLY32 is smaller than ICMP_ECHO_REPLY, so if we use that due to
* binary compat Windows will add some padding.
*/
constexpr auto reply_padding =
sizeof(ICMP_ECHO_REPLY) - sizeof(MZ_ICMP_ECHO_REPLY);
// Disable Packing, so the compiler does not add padding in this struct between
// different sized types.
#pragma pack(push, 1)
struct ICMP_ECHO_REPLY_BUFFER {
MZ_ICMP_ECHO_REPLY reply;
std::array<uint8_t, reply_padding> padding;
quint16 payload;
std::array<char8_t, ICMP_ERR_SIZE> icmp_error;
IO_STATUS_BLOCK status;
};
#pragma pack(pop)
// If the Size is not the MinimumReplyBufferSize, the compiler added
// padding, so the fields will not be properly aligned with
// what IcmpSendEcho2 will write.
static_assert(sizeof(ICMP_ECHO_REPLY_BUFFER) == MinimumReplyBufferSize,
"Fulfills the size requirements");
struct WindowsPingSenderPrivate {
HANDLE m_handle;
HANDLE m_event;
ICMP_ECHO_REPLY_BUFFER m_replyBuffer;
unsigned char m_buffer[sizeof(ICMP_ECHO_REPLY) + WindowsPingPayloadSize + 8];
};
namespace {
@@ -101,7 +58,7 @@ WindowsPingSender::WindowsPingSender(const QHostAddress& source,
QObject::connect(m_notifier, &QWinEventNotifier::activated, this,
&WindowsPingSender::pingEventReady);
m_private->m_replyBuffer = {};
memset(m_private->m_buffer, 0, sizeof(m_private->m_buffer));
}
WindowsPingSender::~WindowsPingSender() {
@@ -129,33 +86,16 @@ void WindowsPingSender::sendPing(const QHostAddress& dest, quint16 sequence) {
quint32 v4dst = dest.toIPv4Address();
if (m_source.isNull()) {
IcmpSendEcho2(m_private->m_handle, // IcmpHandle,
m_private->m_event, // Event
nullptr, // ApcRoutine
nullptr, // ApcContext
qToBigEndian<quint32>(v4dst), // DestinationAddress
&sequence, // RequestData
sizeof(sequence), // RequestSize
nullptr, // RequestOptions
&m_private->m_replyBuffer, // [OUT] ReplyBuffer
sizeof(m_private->m_replyBuffer), // ReplySize
10000 // Timeout
);
IcmpSendEcho2(m_private->m_handle, m_private->m_event, nullptr, nullptr,
qToBigEndian<quint32>(v4dst), &sequence, sizeof(sequence),
nullptr, m_private->m_buffer, sizeof(m_private->m_buffer),
10000);
} else {
quint32 v4src = m_source.toIPv4Address();
IcmpSendEcho2Ex(m_private->m_handle, // IcmpHandle
m_private->m_event, // Event
nullptr, // ApcRoutine
nullptr, // ApcContext
qToBigEndian<quint32>(v4src), // SourceAddress
qToBigEndian<quint32>(v4dst), // DestinationAddress
&sequence, // RequestData
sizeof(sequence), // RequestSize
nullptr, // RequestOptions
&m_private->m_replyBuffer, // [OUT] ReplyBuffer
sizeof(m_private->m_replyBuffer), // ReplySize
10000 // Timeout
);
IcmpSendEcho2Ex(m_private->m_handle, m_private->m_event, nullptr, nullptr,
qToBigEndian<quint32>(v4src), qToBigEndian<quint32>(v4dst),
&sequence, sizeof(sequence), nullptr, m_private->m_buffer,
sizeof(m_private->m_buffer), 10000);
}
DWORD status = GetLastError();
@@ -168,11 +108,8 @@ void WindowsPingSender::sendPing(const QHostAddress& dest, quint16 sequence) {
}
void WindowsPingSender::pingEventReady() {
// Cleanup all data once we're done with m_replyBuffer.
const auto guard = qScopeGuard([this]() { m_private->m_replyBuffer = {}; });
DWORD replyCount = IcmpParseReplies(&m_private->m_replyBuffer,
sizeof(m_private->m_replyBuffer));
DWORD replyCount =
IcmpParseReplies(m_private->m_buffer, sizeof(m_private->m_buffer));
if (replyCount == 0) {
DWORD error = GetLastError();
if (error == IP_REQ_TIMED_OUT) {
@@ -183,25 +120,14 @@ void WindowsPingSender::pingEventReady() {
<< " Message: " << errmsg;
return;
}
// We only allocated for one reply, so more should be impossible.
if (replyCount != 1) {
logger.error() << "Invalid amount of responses recieved";
return;
}
if (m_private->m_replyBuffer.reply.Data == nullptr) {
logger.error() << "Did get a ping response without payload";
return;
}
// Assert that the (void*) pointer of Data is pointing
// to our ReplyBuffer payload.
if (m_private->m_replyBuffer.reply.Data == nullptr) {
logger.error() << "Did get a ping response without payload";
return;
}
// Assert that the (void*) pointer of Data is pointing
// to our ReplyBuffer payload.
assert(m_private->m_replyBuffer.reply.Data ==
static_cast<PVOID>(&m_private->m_replyBuffer.payload));
emit recvPing(m_private->m_replyBuffer.payload);
const ICMP_ECHO_REPLY* replies = (const ICMP_ECHO_REPLY*)m_private->m_buffer;
for (DWORD i = 0; i < replyCount; i++) {
if (replies[i].DataSize < sizeof(quint16)) {
continue;
}
quint16 sequence;
memcpy(&sequence, replies[i].Data, sizeof(quint16));
emit recvPing(sequence);
}
}

View File

@@ -336,11 +336,8 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j=0; j < netInterfaces.at(i).addressEntries().size(); j++)
{
// killSwitch toggle
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
}
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer", m_configData.value(amnezia::config_key::hostName).toString());
@@ -350,10 +347,7 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
}
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
#endif
qDebug() << QString("Set vpn local address %1, gw %2").arg(m_vpnLocalAddress).arg(vpnGateway());
}

View File

@@ -92,8 +92,6 @@ namespace amnezia
constexpr char splitTunnelApps[] = "splitTunnelApps";
constexpr char appSplitTunnelType[] = "appSplitTunnelType";
constexpr char killSwitchOption[] = "killSwitchOption";
constexpr char crc[] = "crc";
constexpr char clientId[] = "clientId";

View File

@@ -142,6 +142,7 @@ ErrorCode XrayProtocol::startTun2Sock()
QThread::msleep(5000);
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
#endif
#ifdef Q_OS_WINDOWS
QThread::msleep(15000);
@@ -150,12 +151,7 @@ ErrorCode XrayProtocol::startTun2Sock()
QThread::msleep(1000);
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
#endif
if (m_routeMode == 0) {
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "0.0.0.0/1");
@@ -169,11 +165,8 @@ ErrorCode XrayProtocol::startTun2Sock()
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j=0; j < netInterfaces.at(i).addressEntries().size(); j++)
{
// killSwitch toggle
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
}
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer", m_remoteAddress);
@@ -207,7 +200,6 @@ void XrayProtocol::stop()
{
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
IpcClient::Interface()->disableKillSwitch();
IpcClient::Interface()->StartRoutingIpv6();
#endif
qDebug() << "XrayProtocol::stop()";
m_xrayProcess.terminate();

View File

@@ -125,10 +125,6 @@ QByteArray SecureQSettings::backupAppConfig() const
QJsonObject cfg;
for (const QString &key : m_settings.allKeys()) {
if (key == "Conf/installationUuid") {
continue;
}
cfg.insert(key, QJsonValue::fromVariant(value(key)));
}
@@ -142,10 +138,6 @@ bool SecureQSettings::restoreAppConfig(const QByteArray &json)
return false;
for (const QString &key : cfg.keys()) {
if (key == "Conf/installationUuid") {
continue;
}
setValue(key, cfg.value(key).toVariant());
}

View File

@@ -256,7 +256,7 @@ Settings::RouteMode Settings::routeMode() const
return static_cast<RouteMode>(value("Conf/routeMode", 0).toInt());
}
bool Settings::isSitesSplitTunnelingEnabled() const
bool Settings::getSitesSplitTunnelingEnabled() const
{
return value("Conf/sitesSplitTunnelingEnabled", false).toBool();
}
@@ -361,9 +361,7 @@ QString Settings::secondaryDns() const
void Settings::clearSettings()
{
auto uuid = getInstallationUuid(false);
m_settings.clearSettings();
setInstallationUuid(uuid);
emit settingsCleared();
}
@@ -415,7 +413,7 @@ void Settings::setVpnApps(AppsRouteMode mode, const QVector<InstalledAppInfo> &a
m_settings.sync();
}
bool Settings::isAppsSplitTunnelingEnabled() const
bool Settings::getAppsSplitTunnelingEnabled() const
{
return value("Conf/appsSplitTunnelingEnabled", false).toBool();
}
@@ -425,31 +423,6 @@ void Settings::setAppsSplitTunnelingEnabled(bool enabled)
setValue("Conf/appsSplitTunnelingEnabled", enabled);
}
bool Settings::isKillSwitchEnabled() const
{
return value("Conf/killSwitchEnabled", true).toBool();
}
void Settings::setKillSwitchEnabled(bool enabled)
{
setValue("Conf/killSwitchEnabled", enabled);
}
QString Settings::getInstallationUuid(const bool needCreate)
{
auto uuid = value("Conf/installationUuid", "").toString();
if (needCreate && uuid.isEmpty()) {
uuid = QUuid::createUuid().toString();
setInstallationUuid(uuid);
}
return uuid;
}
void Settings::setInstallationUuid(const QString &uuid)
{
setValue("Conf/installationUuid", uuid);
}
ServerCredentials Settings::defaultServerCredentials() const
{
return serverCredentials(defaultServerIndex());

View File

@@ -115,7 +115,7 @@ public:
RouteMode routeMode() const;
void setRouteMode(RouteMode mode) { setValue("Conf/routeMode", mode); }
bool isSitesSplitTunnelingEnabled() const;
bool getSitesSplitTunnelingEnabled() const;
void setSitesSplitTunnelingEnabled(bool enabled);
QVariantMap vpnSites(RouteMode mode) const
@@ -211,13 +211,9 @@ public:
QVector<InstalledAppInfo> getVpnApps(AppsRouteMode mode) const;
void setVpnApps(AppsRouteMode mode, const QVector<InstalledAppInfo> &apps);
bool isAppsSplitTunnelingEnabled() const;
bool getAppsSplitTunnelingEnabled() const;
void setAppsSplitTunnelingEnabled(bool enabled);
bool isKillSwitchEnabled() const;
void setKillSwitchEnabled(bool enabled);
QString getInstallationUuid(const bool needCreate);
signals:
void saveLogsChanged(bool enabled);
void screenshotsEnabledChanged(bool enabled);
@@ -228,8 +224,6 @@ private:
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
void setValue(const QString &key, const QVariant &value);
void setInstallationUuid(const QString &uuid);
mutable SecureQSettings m_settings;
};

View File

@@ -613,7 +613,7 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolOpenVpnSettings.qml" line="384"/>
<source>Remove OpenVPN from server?</source>
<source>Remove OpenVpn from server?</source>
<translation>احذف OpenVPN من الخادم?</translation>
</message>
<message>
@@ -2104,8 +2104,8 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="116"/>
<source>OpenVPN native format</source>
<translation>تنسيق OpenVPN الاصلي</translation>
<source>OpenVpn native format</source>
<translation>تنسيق OpenVpn الاصلي</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="121"/>
@@ -2716,7 +2716,7 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<message>
<location filename="../core/errorstrings.cpp" line="35"/>
<source>OpenVPN config missing</source>
<translation>OpenVPN تكوين مفقود</translation>
<translation>OpenVpn تكوين مفقود</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="32"/>
@@ -2726,12 +2726,12 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<message>
<location filename="../core/errorstrings.cpp" line="36"/>
<source>OpenVPN management server error</source>
<translation>OpenVPN خطأ في إدارة الخادم</translation>
<translation>OpenVpn خطأ في إدارة الخادم</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="39"/>
<source>OpenVPN executable missing</source>
<translation>OpenVPN executable مفقود</translation>
<translation>OpenVpn executeable مفقود</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="40"/>
@@ -2968,7 +2968,7 @@ It employs its unique security protocol, leveraging the strength of SSL/TLS for
* Recognised by DPI analysis systems and therefore susceptible to blocking
* Can operate over both TCP and UDP network protocols.</source>
<translation>يبقا OpenVPN كأحد اشهر بروتوكولات VPN و التي تم اختبارها عبر الزمن.
ينشأ بروتوكول امان مميز, يستفيد من SSL/TLS للتشفير و تغير المفاتيح. واكثر من ذلك, OpenVPN يدعم تعدد طرق المصادقة يجعلة متعدد الاستخدامات وقابلة للتكيف, تلبية مجموعة واسعة من الأجهزة وأنظمة التشغيل. بسبب طبيعتة مفتوحة المصدر, يستفيد OpenVPN من التدقيق الشامل من قبل المجتمع العالمي, مما يعزز أمنها باستمرار. مع توازن قوي بين الأداء والأمان والتوافق, يظل OpenVPN الخيار الأفضل للأفراد والشركات المهتمين بالخصوصية على حدٍ سواء.
ينشأ بروتوكول امان مميز, يستفيد من SSL/TLS للتشفير و تغير المفاتيح. واكثر من ذلك, OpenVpn يدعم تعدد طرق المصادقة يجعلة متعدد الاستخدامات وقابلة للتكيف, تلبية مجموعة واسعة من الأجهزة وأنظمة التشغيل. بسبب طبيعتة مفتوحة المصدر, يستفيد OpenVPN من التدقيق الشامل من قبل المجتمع العالمي, مما يعزز أمنها باستمرار. مع توازن قوي بين الأداء والأمان والتوافق, يظل OpenVPN الخيار الأفضل للأفراد والشركات المهتمين بالخصوصية على حدٍ سواء.
* مٌتاح في AmneziaVPN عبر جميع المنصات
* استهلاك طاقة عادي علي اجهزة المحمول
@@ -3330,7 +3330,7 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="313"/>
<source>High</source>
<source>Medium or High</source>
<translation>متوسط او عالي</translation>
</message>
<message>

View File

@@ -589,7 +589,7 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolOpenVpnSettings.qml" line="384"/>
<source>Remove OpenVPN from server?</source>
<source>Remove OpenVpn from server?</source>
<translation>آیا میخواهید OpenVPN از سرور حذف شود؟</translation>
</message>
<message>
@@ -1986,7 +1986,7 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<name>PageShare</name>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="116"/>
<source>OpenVPN native format</source>
<source>OpenVpn native format</source>
<translation>فرمت OpenVPN</translation>
</message>
<message>
@@ -3234,7 +3234,7 @@ For more detailed information, you can
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="313"/>
<source>High</source>
<source>Medium or High</source>
<translation>متوسط یا بالا</translation>
</message>
<message>

File diff suppressed because it is too large Load Diff

View File

@@ -589,7 +589,7 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolOpenVpnSettings.qml" line="384"/>
<source>Remove OpenVPN from server?</source>
<source>Remove OpenVpn from server?</source>
<translation>AmneziaWG က ?</translation>
</message>
<message>
@@ -1987,8 +1987,8 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<name>PageShare</name>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="116"/>
<source>OpenVPN native format</source>
<translation>OpenVPN </translation>
<source>OpenVpn native format</source>
<translation>OpenVpn </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="121"/>
@@ -3232,7 +3232,7 @@ For more detailed information, you can
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="313"/>
<source>High</source>
<source>Medium or High</source>
<translation>Medium High</translation>
</message>
<message>

View File

@@ -589,8 +589,8 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolOpenVpnSettings.qml" line="384"/>
<source>Remove OpenVPN from server?</source>
<translation>Удалить OpenVPN с сервера?</translation>
<source>Remove OpenVpn from server?</source>
<translation>Удалить OpenVpn с сервера?</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolOpenVpnSettings.qml" line="385"/>
@@ -1724,14 +1724,6 @@ Already installed containers were found on the server. All installed containers
<translation>Добавить импортированные сайты к существующим</translation>
</message>
</context>
<context>
<name>PageSettingsAppSplitTunneling</name>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="26"/>
<source>Cannot change split tunneling settings during active connection</source>
<translation>Невозможно изменить настройки раздельного туннелирования при включенном VPN</translation>
</message>
</context>
<context>
<name>PageSetupWizardConfigSource</name>
<message>
@@ -2095,7 +2087,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<name>PageShare</name>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="116"/>
<source>OpenVPN native format</source>
<source>OpenVpn native format</source>
<translation>OpenVPN нативный формат</translation>
</message>
<message>
@@ -2884,23 +2876,7 @@ If there is a extreme level of Internet censorship in your region, we advise you
* Not recognised by DPI analysis systems
* Works over TCP network protocol, 443 port.
</source>
<translation>Это связка протокола OpenVPN и плагина Cloak, разработанная специально для защиты от блокировки.
OpenVPN обеспечивает безопасное VPN-соединение, шифруя весь интернет-трафик между клиентом и сервером.
Cloak защищает OpenVPN от обнаружения и блокировки.
Cloak изменяет метаданные пакетов таким образом, что полностью маскирует VPN-трафик под обычный веб-трафик, а также защищает VPN от обнаружения с помощью Active Probing. Это делает его очень защищенным от обнаружения
Сразу после получения первого пакета данных Cloak устанавливает подлинность входящего соединения. Если аутентификация не проходит, плагин маскирует сервер под фальшивый сайт, и ваш VPN становится невидимым для систем анализа.
Если в вашем регионе наблюдается жесткая интернет-цензура, мы советуем вам уже при первом подключении использовать только OpenVPN через Cloak.
* Доступен в AmneziaVPN на всех платформах
* Высокое энергопотребление на мобильных устройствах
* Гибкие настройки
* Не распознается системами DPI-анализа
* Работает по сетевому протоколу TCP, порт 443.</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="174"/>
@@ -2913,15 +2889,7 @@ WireGuard is very susceptible to blocking due to its distinct packet signatures.
* Minimum number of settings
* Easily recognised by DPI analysis systems, susceptible to blocking
* Works over UDP network protocol.</source>
<translation>Относительно новый и популярный VPN-протокол с простой архитектурой.
WireGuard обеспечивает стабильное VPN-соединение и высокую производительность на всех устройствах. Он использует строго заданные настройки шифрования. WireGuard по сравнению с OpenVPN имеет меньшую задержку и лучшую пропускную способность при передаче данных.
WireGuard очень уязвим для блокировки из-за характерных сигнатур пакетов. В отличие от некоторых других VPN-протоколов, использующих методы обфускации, последовательные сигнатуры пакетов WireGuard легче идентифицируются и, следовательно, могут блокироваться современными Deep Packet Inspection (DPI) системами и другими инструментами для сетевого мониторинга.
* Доступен в AmneziaVPN на всех платформах
* Низкое энергопотребление
* Минимальная конфигурация
* Легко распознается системами DPI-анализа, поддается блокировке
* Работает по сетевому протоколу UDP</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="203"/>
@@ -2982,21 +2950,16 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="115"/>
<source>XRay with REALITY - Suitable for countries with the highest level of internet censorship. Traffic masking as web traffic at the TLS level, and protection against detection by active probing methods.</source>
<translation>XRay с REALITY - подойдет для стран с самым высоким уровнем цензуры в Интернете. Маскировка трафика под веб-трафик на уровне TLS и защита от обнаружения активными методами прослушивания.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="121"/>
<source>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.</source>
<translation>IKEv2 Современный стабильный протокол, немного быстрее других восстанавливает соединение после потери сигнала. Имеет нативную поддержку последних версиий Android и iOS.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="124"/>
<location filename="../containers/containers_defs.cpp" line="118"/>
<source>Deploy a WordPress site on the Tor network in two clicks.</source>
<translation>Разверните сайт на WordPress в сети Tor в два клика.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="126"/>
<location filename="../containers/containers_defs.cpp" line="120"/>
<source>Replace the current DNS server with your own. This will increase your privacy level.</source>
<translation>Замените DNS-сервер на Amnezia DNS. Это повысит уровень конфиденциальности.</translation>
</message>
@@ -3035,17 +2998,6 @@ It employs its unique security protocol, leveraging the strength of SSL/TLS for
* Настраиваемый протокол шифрования
* Обнаруживается некоторыми DPI-системами
* Работает по сетевому протоколу TCP.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="203"/>
<source>The REALITY protocol, a pioneering development by the creators of XRay, is specifically designed to counteract the highest levels of internet censorship through its novel approach to evasion.
It uniquely identifies censors during the TLS handshake phase, seamlessly operating as a proxy for legitimate clients while diverting censors to genuine websites like google.com, thus presenting an authentic TLS certificate and data.
This advanced capability differentiates REALITY from similar technologies by its ability to disguise web traffic as coming from random, legitimate sites without the need for specific configurations.
Unlike older protocols such as VMess, VLESS, and the XTLS-Vision transport, REALITY&apos;s innovative &quot;friend or foe&quot; recognition at the TLS handshake enhances security and circumvents detection by sophisticated DPI systems employing active probing techniques. This makes REALITY a robust solution for maintaining internet freedom in environments with stringent censorship.</source>
<translation>Протокол REALITY, новаторская разработка создателей XRay, специально разработан для противодействия самым строгим мерам интернет-цензуры благодаря новому подходу к обходу.
Он уникальным образом идентифицирует цензоров на этапе TLS рукопожатия, беспрепятственно работая в качестве прокси для реальных клиентов и перенаправляя цензоров на сайты, такие как google.com, тем самым представляя подлинный TLS сертификат и данные.
Эта передовая способность отличает REALITY от аналогичных технологий благодаря способности маскировать веб-трафик так, как будто он поступает со случайных, легитимных сайтов, без необходимости специальной настройки.
В отличие от более старых протоколов, таких как VMess, VLESS и XTLS-Vision, технология распознавания REALITY &quot;друг или враг&quot; на этапе рукопожатия TLS повышает надежность и обходит обнаружение сложными системами DPI, которые используют методы активного прослушивания. Это делает REALITY эффективным решением для поддержания свободы интернета в странах с жесткой цензурой.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="217"/>
@@ -3443,8 +3395,8 @@ This means that AmneziaWG keeps the fast performance of the original while addin
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="313"/>
<source>High</source>
<translation>Высокий</translation>
<source>Medium or High</source>
<translation>Средний или Высокий</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="314"/>

View File

@@ -692,7 +692,7 @@ Already installed containers were found on the server. All installed containers
<translation type="vanished">Видалити OpenVPN</translation>
</message>
<message>
<source>Remove OpenVPN from server?</source>
<source>Remove OpenVpn from server?</source>
<translation type="vanished">Видалити OpenVPN з серверу?</translation>
</message>
<message>
@@ -1176,12 +1176,12 @@ Already installed containers were found on the server. All installed containers
<name>PageSettingsAppSplitTunneling</name>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="37"/>
<source>Only the apps from the list should have access via VPN</source>
<source>Only the Apps listed here will be accessed through the VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="42"/>
<source>Apps from the list should not have access via VPN</source>
<source>Apps from the list should not be accessed via VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -2301,7 +2301,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<name>PageShare</name>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="125"/>
<source>OpenVPN native format</source>
<source>OpenVpn native format</source>
<translation>OpenVPN нативний формат</translation>
</message>
<message>
@@ -3627,8 +3627,8 @@ This means that AmneziaWG keeps the fast performance of the original while addin
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="333"/>
<source>High</source>
<translation>Високий</translation>
<source>Medium or High</source>
<translation>Середній або високий</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="334"/>

File diff suppressed because it is too large Load Diff

View File

@@ -611,7 +611,7 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolOpenVpnSettings.qml" line="384"/>
<source>Remove OpenVPN from server?</source>
<source>Remove OpenVpn from server?</source>
<translation>OpenVPN吗?</translation>
</message>
<message>
@@ -2182,7 +2182,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="116"/>
<source>OpenVPN native format</source>
<source>OpenVpn native format</source>
<translation>OpenVPN原生格式</translation>
</message>
<message>
@@ -3216,12 +3216,12 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<translation type="vanished">OpenVPN容器</translation>
</message>
<message>
<source>Container with OpenVPN and ShadowSocks</source>
<translation type="vanished"> OpenVPN ShadowSocks </translation>
<source>Container with OpenVpn and ShadowSocks</source>
<translation type="vanished"> OpenVpn ShadowSocks </translation>
</message>
<message>
<source>Container with OpenVPN and ShadowSocks protocols configured with traffic masking by Cloak plugin</source>
<translation type="vanished"> OpenVPN ShadowSocks Cloak </translation>
<source>Container with OpenVpn and ShadowSocks protocols configured with traffic masking by Cloak plugin</source>
<translation type="vanished"> OpenVpn ShadowSocks Cloak </translation>
</message>
<message>
<source>WireGuard container</source>
@@ -3529,7 +3529,7 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="313"/>
<source>High</source>
<source>Medium or High</source>
<translation></translation>
</message>
<message>

View File

@@ -29,6 +29,7 @@ void AppSplitTunnelingController::addApp(const QString &appPath)
void AppSplitTunnelingController::addApps(QVector<QPair<QString, QString>> apps)
{
qDebug() << apps;
for (const auto &app : apps) {
InstalledAppInfo appInfo { app.first, app.second, "" };

View File

@@ -14,8 +14,8 @@
ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
const QSharedPointer<ClientManagementModel> &clientManagementModel,
const QSharedPointer<VpnConnection> &vpnConnection, const std::shared_ptr<Settings> &settings,
QObject *parent)
const QSharedPointer<VpnConnection> &vpnConnection,
const std::shared_ptr<Settings> &settings, QObject *parent)
: QObject(parent),
m_serversModel(serversModel),
m_containersModel(containersModel),
@@ -23,9 +23,12 @@ ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &s
m_vpnConnection(vpnConnection),
m_settings(settings)
{
connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, this, &ConnectionController::onConnectionStateChanged);
connect(this, &ConnectionController::connectToVpn, m_vpnConnection.get(), &VpnConnection::connectToVpn, Qt::QueuedConnection);
connect(this, &ConnectionController::disconnectFromVpn, m_vpnConnection.get(), &VpnConnection::disconnectFromVpn, Qt::QueuedConnection);
connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, this,
&ConnectionController::onConnectionStateChanged);
connect(this, &ConnectionController::connectToVpn, m_vpnConnection.get(), &VpnConnection::connectToVpn,
Qt::QueuedConnection);
connect(this, &ConnectionController::disconnectFromVpn, m_vpnConnection.get(), &VpnConnection::disconnectFromVpn,
Qt::QueuedConnection);
m_state = Vpn::ConnectionState::Disconnected;
}
@@ -42,7 +45,7 @@ void ConnectionController::openConnection()
if (serverConfig.value(config_key::configVersion).toInt()
&& !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) {
ApiController apiController;
errorCode = apiController.updateServerConfigFromApi(m_settings->getInstallationUuid(true), serverConfig);
errorCode = apiController.updateServerConfigFromApi(serverConfig);
if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(errorString(errorCode));
return;
@@ -56,7 +59,8 @@ void ConnectionController::openConnection()
return;
}
DockerContainer container = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
DockerContainer container =
qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
if (!m_containersModel->isSupportedByCurrentPlatform(container)) {
emit connectionErrorOccurred(tr("The selected protocol is not supported on the current platform"));
@@ -70,12 +74,11 @@ void ConnectionController::openConnection()
qApp->processEvents();
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
VpnConfigurationsController vpnConfigurationController(m_settings);
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
errorCode = updateProtocolConfig(container, credentials, containerConfig, serverController);
errorCode = updateProtocolConfig(container, credentials, containerConfig);
if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(errorString(errorCode));
return;
@@ -84,7 +87,8 @@ void ConnectionController::openConnection()
auto dns = m_serversModel->getDnsPair(serverIndex);
serverConfig = m_serversModel->getServerConfig(serverIndex);
auto vpnConfiguration = vpnConfigurationController.createVpnConfiguration(dns, serverConfig, containerConfig, container, errorCode);
auto vpnConfiguration =
vpnConfigurationController.createVpnConfiguration(dns, serverConfig, containerConfig, container, errorCode);
if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(tr("unable to create configuration"));
return;
@@ -211,8 +215,10 @@ bool ConnectionController::isConnected() const
bool ConnectionController::isProtocolConfigExists(const QJsonObject &containerConfig, const DockerContainer container)
{
for (Proto protocol : ContainerProps::protocolsForContainer(container)) {
QString protocolConfig =
containerConfig.value(ProtocolProps::protoToString(protocol)).toObject().value(config_key::last_config).toString();
QString protocolConfig = containerConfig.value(ProtocolProps::protoToString(protocol))
.toObject()
.value(config_key::last_config)
.toString();
if (protocolConfig.isEmpty()) {
return false;
@@ -221,27 +227,24 @@ bool ConnectionController::isProtocolConfigExists(const QJsonObject &containerCo
return true;
}
ErrorCode ConnectionController::updateProtocolConfig(const DockerContainer container, const ServerCredentials &credentials,
QJsonObject &containerConfig, QSharedPointer<ServerController> serverController)
ErrorCode ConnectionController::updateProtocolConfig(const DockerContainer container,
const ServerCredentials &credentials, QJsonObject &containerConfig)
{
QFutureWatcher<ErrorCode> watcher;
if (serverController.isNull()) {
serverController.reset(new ServerController(m_settings));
}
QFuture<ErrorCode> future = QtConcurrent::run([this, container, &credentials, &containerConfig, &serverController]() {
QFuture<ErrorCode> future = QtConcurrent::run([this, container, &credentials, &containerConfig]() {
ErrorCode errorCode = ErrorCode::NoError;
if (!isProtocolConfigExists(containerConfig, container)) {
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
errorCode = vpnConfigurationController.createProtocolConfigForContainer(credentials, container, containerConfig);
VpnConfigurationsController vpnConfigurationController(m_settings);
errorCode =
vpnConfigurationController.createProtocolConfigForContainer(credentials, container, containerConfig);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
m_serversModel->updateContainerConfig(container, containerConfig);
errorCode = m_clientManagementModel->appendClient(container, credentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName()), serverController);
QString("Admin [%1]").arg(QSysInfo::prettyProductName()));
if (errorCode != ErrorCode::NoError) {
return errorCode;
}

View File

@@ -16,10 +16,11 @@ public:
Q_PROPERTY(bool isConnectionInProgress READ isConnectionInProgress NOTIFY connectionStateChanged)
Q_PROPERTY(QString connectionStateText READ connectionStateText NOTIFY connectionStateChanged)
explicit ConnectionController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
explicit ConnectionController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
const QSharedPointer<ClientManagementModel> &clientManagementModel,
const QSharedPointer<VpnConnection> &vpnConnection, const std::shared_ptr<Settings> &settings,
QObject *parent = nullptr);
const QSharedPointer<VpnConnection> &vpnConnection,
const std::shared_ptr<Settings> &settings, QObject *parent = nullptr);
~ConnectionController() = default;
@@ -40,11 +41,12 @@ public slots:
void onTranslationsUpdated();
ErrorCode updateProtocolConfig(const DockerContainer container, const ServerCredentials &credentials, QJsonObject &containerConfig,
QSharedPointer<ServerController> serverController = nullptr);
ErrorCode updateProtocolConfig(const DockerContainer container, const ServerCredentials &credentials,
QJsonObject &containerConfig);
signals:
void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &vpnConfiguration);
void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &vpnConfiguration);
void disconnectFromVpn();
void connectionStateChanged();

View File

@@ -95,11 +95,10 @@ void ExportController::generateConnectionConfig(const QString &clientName)
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
VpnConfigurationsController vpnConfigurationController(m_settings);
ErrorCode errorCode = vpnConfigurationController.createProtocolConfigForContainer(credentials, container, containerConfig);
errorCode = m_clientManagementModel->appendClient(container, credentials, containerConfig, clientName, serverController);
errorCode = m_clientManagementModel->appendClient(container, credentials, containerConfig, clientName);
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorString(errorCode));
return;
@@ -139,10 +138,10 @@ ErrorCode ExportController::generateNativeConfig(const DockerContainer container
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
VpnConfigurationsController vpnConfigurationController(m_settings);
QString protocolConfigString;
ErrorCode errorCode = vpnConfigurationController.createProtocolConfigString(isApiConfig, dns, credentials, container, containerConfig,
protocol, protocolConfigString);
if (errorCode != ErrorCode::NoError) {
@@ -153,7 +152,7 @@ ErrorCode ExportController::generateNativeConfig(const DockerContainer container
if (protocol == Proto::OpenVpn || protocol == Proto::WireGuard || protocol == Proto::Awg) {
auto clientId = jsonNativeConfig.value(config_key::clientId).toString();
errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials, serverController);
errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
}
return errorCode;
}
@@ -317,8 +316,7 @@ void ExportController::exportConfig(const QString &fileName)
void ExportController::updateClientManagementModel(const DockerContainer container, ServerCredentials credentials)
{
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = m_clientManagementModel->updateModel(container, credentials, serverController);
ErrorCode errorCode = m_clientManagementModel->updateModel(container, credentials);
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorString(errorCode));
}
@@ -326,9 +324,7 @@ void ExportController::updateClientManagementModel(const DockerContainer contain
void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials)
{
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode =
m_clientManagementModel->revokeClient(row, container, credentials, m_serversModel->getProcessedServerIndex(), serverController);
ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials, m_serversModel->getProcessedServerIndex());
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorString(errorCode));
}
@@ -336,8 +332,7 @@ void ExportController::revokeConfig(const int row, const DockerContainer contain
void ExportController::renameClient(const int row, const QString &clientName, const DockerContainer container, ServerCredentials credentials)
{
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = m_clientManagementModel->renameClient(row, clientName, container, credentials, serverController);
ErrorCode errorCode = m_clientManagementModel->renameClient(row, clientName, container, credentials);
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorString(errorCode));
}

View File

@@ -3,7 +3,6 @@
#include <QFile>
#include <QFileInfo>
#include <QQuickItem>
#include <QRandomGenerator>
#include <QStandardPaths>
#include "core/errorstrings.h"
@@ -16,6 +15,15 @@
namespace
{
enum class ConfigTypes {
Amnezia,
OpenVpn,
WireGuard,
Xray,
Backup,
Invalid
};
ConfigTypes checkConfigFormat(const QString &config)
{
const QString openVpnConfigPatternCli = "client";
@@ -31,23 +39,19 @@ namespace
const QString xrayConfigPatternOutbound = "outbounds";
const QString amneziaConfigPattern = "containers";
const QString amneziaConfigPatternHostName = "hostName";
const QString amneziaConfigPatternUserName = "userName";
const QString amneziaConfigPatternPassword = "password";
const QString amneziaFreeConfigPattern = "api_key";
const QString backupPattern = "Servers/serversList";
if (config.contains(backupPattern)) {
return ConfigTypes::Backup;
} else if (config.contains(amneziaConfigPattern) || config.contains(amneziaFreeConfigPattern)
|| (config.contains(amneziaConfigPatternHostName) && config.contains(amneziaConfigPatternUserName)
&& config.contains(amneziaConfigPatternPassword))) {
} else if (config.contains(amneziaConfigPattern) || config.contains(amneziaFreeConfigPattern)) {
return ConfigTypes::Amnezia;
} else if (config.contains(openVpnConfigPatternCli)
&& (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2))
&& (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
return ConfigTypes::OpenVpn;
} else if (config.contains(wireguardConfigPatternSectionInterface) && config.contains(wireguardConfigPatternSectionPeer)) {
} else if (config.contains(wireguardConfigPatternSectionInterface)
&& config.contains(wireguardConfigPatternSectionPeer)) {
return ConfigTypes::WireGuard;
} else if ((config.contains(xrayConfigPatternInbound)) && (config.contains(xrayConfigPatternOutbound))) {
return ConfigTypes::Xray;
@@ -60,7 +64,8 @@ namespace
#endif
} // namespace
ImportController::ImportController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
ImportController::ImportController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
const std::shared_ptr<Settings> &settings, QObject *parent)
: QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_settings(settings)
{
@@ -87,29 +92,25 @@ bool ImportController::extractConfigFromFile(const QString &fileName)
bool ImportController::extractConfigFromData(QString data)
{
QString config = data;
m_configType = checkConfigFormat(config);
if (m_configType == ConfigTypes::Invalid) {
auto configFormat = checkConfigFormat(config);
if (configFormat == ConfigTypes::Invalid) {
data.replace("vpn://", "");
QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
QByteArray ba =
QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
QByteArray ba_uncompressed = qUncompress(ba);
if (!ba_uncompressed.isEmpty()) {
ba = ba_uncompressed;
}
config = ba;
m_configType = checkConfigFormat(config);
configFormat = checkConfigFormat(config);
}
switch (m_configType) {
switch (configFormat) {
case ConfigTypes::OpenVpn: {
m_config = extractOpenVpnConfig(config);
if (!m_config.empty()) {
checkForMaliciousStrings(m_config);
return true;
}
return false;
return m_config.empty() ? false : true;
}
case ConfigTypes::Awg:
case ConfigTypes::WireGuard: {
m_config = extractWireGuardConfig(config);
return m_config.empty() ? false : true;
@@ -120,11 +121,7 @@ bool ImportController::extractConfigFromData(QString data)
}
case ConfigTypes::Amnezia: {
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
if (!m_config.empty()) {
checkForMaliciousStrings(m_config);
return true;
}
return false;
return m_config.empty() ? false : true;
}
case ConfigTypes::Backup: {
if (!m_serversModel->getServersCount()) {
@@ -169,44 +166,6 @@ QString ImportController::getConfigFileName()
return m_configFileName;
}
QString ImportController::getMaliciousWarningText()
{
return m_maliciousWarningText;
}
bool ImportController::isNativeWireGuardConfig()
{
return m_configType == ConfigTypes::WireGuard;
}
void ImportController::processNativeWireGuardConfig()
{
auto containers = m_config.value(config_key::containers).toArray();
if (!containers.isEmpty()) {
auto container = containers.at(0).toObject();
auto containerConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::WireGuard)).toObject();
auto protocolConfig = QJsonDocument::fromJson(containerConfig.value(config_key::last_config).toString().toUtf8()).object();
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(3, 10));
QString junkPacketMinSize = QString::number(50);
QString junkPacketMaxSize = QString::number(1000);
protocolConfig[config_key::junkPacketCount] = junkPacketCount;
protocolConfig[config_key::junkPacketMinSize] = junkPacketMinSize;
protocolConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize;
protocolConfig[config_key::initPacketJunkSize] = "0";
protocolConfig[config_key::responsePacketJunkSize] = "0";
protocolConfig[config_key::initPacketMagicHeader] = "1";
protocolConfig[config_key::responsePacketMagicHeader] = "2";
protocolConfig[config_key::underloadPacketMagicHeader] = "3";
protocolConfig[config_key::transportPacketMagicHeader] = "4";
containerConfig[config_key::last_config] = QString(QJsonDocument(protocolConfig).toJson());
container["wireguard"] = containerConfig;
containers.replace(0, container);
m_config[config_key::containers] = containers;
}
}
void ImportController::importConfig()
{
ServerCredentials credentials;
@@ -236,7 +195,6 @@ void ImportController::importConfig()
m_config = {};
m_configFileName.clear();
m_maliciousWarningText.clear();
}
QJsonObject ImportController::extractOpenVpnConfig(const QString &data)
@@ -321,7 +279,8 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
lastConfig[config_key::hostName] = hostName;
lastConfig[config_key::port] = port.toInt();
if (!configMap.value("PrivateKey").isEmpty() && !configMap.value("Address").isEmpty() && !configMap.value("PublicKey").isEmpty()) {
if (!configMap.value("PrivateKey").isEmpty() && !configMap.value("Address").isEmpty()
&& !configMap.value("PublicKey").isEmpty()) {
lastConfig[config_key::client_priv_key] = configMap.value("PrivateKey");
lastConfig[config_key::client_ip] = configMap.value("Address");
@@ -347,9 +306,12 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
QString protocolName = "wireguard";
if (!configMap.value(config_key::junkPacketCount).isEmpty() && !configMap.value(config_key::junkPacketMinSize).isEmpty()
&& !configMap.value(config_key::junkPacketMaxSize).isEmpty() && !configMap.value(config_key::initPacketJunkSize).isEmpty()
&& !configMap.value(config_key::responsePacketJunkSize).isEmpty() && !configMap.value(config_key::initPacketMagicHeader).isEmpty()
if (!configMap.value(config_key::junkPacketCount).isEmpty()
&& !configMap.value(config_key::junkPacketMinSize).isEmpty()
&& !configMap.value(config_key::junkPacketMaxSize).isEmpty()
&& !configMap.value(config_key::initPacketJunkSize).isEmpty()
&& !configMap.value(config_key::responsePacketJunkSize).isEmpty()
&& !configMap.value(config_key::initPacketMagicHeader).isEmpty()
&& !configMap.value(config_key::responsePacketMagicHeader).isEmpty()
&& !configMap.value(config_key::underloadPacketMagicHeader).isEmpty()
&& !configMap.value(config_key::transportPacketMagicHeader).isEmpty()) {
@@ -363,7 +325,6 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
lastConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader);
lastConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader);
protocolName = "awg";
m_configType = ConfigTypes::Awg;
}
QJsonObject wireguardConfig;
@@ -540,43 +501,3 @@ QString ImportController::getQrCodeScanProgressString()
return tr("Scanned %1 of %2.").arg(m_receivedQrCodeChunksCount).arg(m_totalQrCodeChunksCount);
}
#endif
void ImportController::checkForMaliciousStrings(const QJsonObject &serverConfig)
{
const QJsonArray &containers = serverConfig[config_key::containers].toArray();
for (const QJsonValue &container : containers) {
auto containerConfig = container.toObject();
auto containerName = containerConfig[config_key::container].toString();
if ((containerName == ContainerProps::containerToString(DockerContainer::OpenVpn))
|| (containerName == ContainerProps::containerToString(DockerContainer::Cloak))
|| (containerName == ContainerProps::containerToString(DockerContainer::ShadowSocks))) {
QString protocolConfig =
containerConfig[ProtocolProps::protoToString(Proto::OpenVpn)].toObject()[config_key::last_config].toString();
QString protocolConfigJson = QJsonDocument::fromJson(protocolConfig.toUtf8()).object()[config_key::config].toString();
const QRegularExpression regExp { "(\\w+-\\w+|\\w+)" };
const size_t dangerousTagsMaxCount = 3;
// https://github.com/OpenVPN/openvpn/blob/master/doc/man-sections/script-options.rst
QStringList dangerousTags {
"up", "tls-verify", "ipchange", "client-connect", "route-up", "route-pre-down", "client-disconnect", "down", "learn-address", "auth-user-pass-verify"
};
QStringList maliciousStrings;
QStringList lines = protocolConfigJson.replace("\r", "").split("\n");
for (const QString &l : lines) {
QRegularExpressionMatch match = regExp.match(l);
if (dangerousTags.contains(match.captured(0))) {
maliciousStrings << l;
}
}
if (maliciousStrings.size() >= dangerousTagsMaxCount) {
m_maliciousWarningText = tr("In the imported configuration, potentially dangerous lines were found:");
for (const auto &string : maliciousStrings) {
m_maliciousWarningText.push_back(QString("<br><i>%1</i>").arg(string));
}
}
}
}
}

View File

@@ -3,22 +3,11 @@
#include <QObject>
#include "containers/containers_defs.h"
#include "core/defs.h"
#include "ui/models/containers_model.h"
#include "ui/models/servers_model.h"
namespace
{
enum class ConfigTypes {
Amnezia,
OpenVpn,
WireGuard,
Awg,
Xray,
Backup,
Invalid
};
}
class ImportController : public QObject
{
Q_OBJECT
@@ -34,7 +23,6 @@ public slots:
bool extractConfigFromQr(const QByteArray &data);
QString getConfig();
QString getConfigFileName();
QString getMaliciousWarningText();
#if defined Q_OS_ANDROID || defined Q_OS_IOS
void startDecodingQr();
@@ -48,9 +36,6 @@ public slots:
static bool decodeQrCode(const QString &code);
#endif
bool isNativeWireGuardConfig();
void processNativeWireGuardConfig();
signals:
void importFinished();
void importErrorOccurred(const QString &errorMessage, bool goToPageHome);
@@ -64,8 +49,6 @@ private:
QJsonObject extractWireGuardConfig(const QString &data);
QJsonObject extractXrayConfig(const QString &data);
void checkForMaliciousStrings(const QJsonObject &protocolConfig);
#if defined Q_OS_ANDROID || defined Q_OS_IOS
void stopDecodingQr();
#endif
@@ -76,8 +59,6 @@ private:
QJsonObject m_config;
QString m_configFileName;
ConfigTypes m_configType;
QString m_maliciousWarningText;
#if defined Q_OS_ANDROID || defined Q_OS_IOS
QMap<int, QByteArray> m_qrCodeChunks;

View File

@@ -10,15 +10,11 @@
#include "core/controllers/serverController.h"
#include "core/controllers/vpnConfigurationController.h"
#include "core/errorstrings.h"
#include "core/networkUtilities.h"
#include "logger.h"
#include "core/networkUtilities.h"
#include "utilities.h"
#include "ui/models/protocols/awgConfigModel.h"
#include "ui/models/protocols/wireguardConfigModel.h"
#include "utilities.h"
#ifdef Q_OS_IOS
#include <AmneziaVPN-Swift.h>
#endif
namespace
{
@@ -89,20 +85,14 @@ void InstallController::install(DockerContainer container, int port, TransportPr
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(3, 10));
QString junkPacketMinSize = QString::number(50);
QString junkPacketMaxSize = QString::number(1000);
int s1 = QRandomGenerator::global()->bounded(15, 150);
int s2 = QRandomGenerator::global()->bounded(15, 150);
while (s1 + AwgConstant::messageInitiationSize == s2 + AwgConstant::messageResponseSize) {
s2 = QRandomGenerator::global()->bounded(15, 150);
}
QString initPacketJunkSize = QString::number(s1);
QString responsePacketJunkSize = QString::number(s2);
QString initPacketJunkSize = QString::number(QRandomGenerator::global()->bounded(15, 150));
QString responsePacketJunkSize = QString::number(QRandomGenerator::global()->bounded(15, 150));
QSet<QString> headersValue;
while (headersValue.size() != 4) {
auto max = (std::numeric_limits<qint32>::max)();
headersValue.insert(QString::number(QRandomGenerator::global()->bounded(5, max)));
headersValue.insert(QString::number(QRandomGenerator::global()->bounded(1, max)));
}
auto headersValueList = headersValue.values();
@@ -142,12 +132,12 @@ void InstallController::install(DockerContainer container, int port, TransportPr
serverCredentials = qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
}
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
connect(serverController.get(), &ServerController::serverIsBusy, this, &InstallController::serverIsBusy);
connect(this, &InstallController::cancelInstallation, serverController.get(), &ServerController::cancelInstallation);
ServerController serverController(m_settings);
connect(&serverController, &ServerController::serverIsBusy, this, &InstallController::serverIsBusy);
connect(this, &InstallController::cancelInstallation, &serverController, &ServerController::cancelInstallation);
QMap<DockerContainer, QJsonObject> installedContainers;
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, serverController, installedContainers);
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, installedContainers);
if (errorCode) {
emit installationErrorOccurred(errorString(errorCode));
return;
@@ -156,7 +146,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr
QString finishMessage = "";
if (!installedContainers.contains(container)) {
errorCode = serverController->setupContainer(serverCredentials, container, config);
errorCode = serverController.setupContainer(serverCredentials, container, config);
if (errorCode) {
emit installationErrorOccurred(errorString(errorCode));
return;
@@ -174,15 +164,14 @@ void InstallController::install(DockerContainer container, int port, TransportPr
}
if (m_shouldCreateServer) {
installServer(container, installedContainers, serverCredentials, serverController, finishMessage);
installServer(container, installedContainers, serverCredentials, finishMessage);
} else {
installContainer(container, installedContainers, serverCredentials, serverController, finishMessage);
installContainer(container, installedContainers, serverCredentials, finishMessage);
}
}
void InstallController::installServer(const DockerContainer container, const QMap<DockerContainer, QJsonObject> &installedContainers,
const ServerCredentials &serverCredentials, const QSharedPointer<ServerController> &serverController,
QString &finishMessage)
const ServerCredentials &serverCredentials, QString &finishMessage)
{
if (installedContainers.size() > 1) {
finishMessage += tr("\nAdded containers that were already installed on the server");
@@ -196,13 +185,13 @@ void InstallController::installServer(const DockerContainer container, const QMa
server.insert(config_key::description, m_settings->nextAvailableServerName());
QJsonArray containerConfigs;
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
VpnConfigurationsController vpnConfigurationController(m_settings);
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
auto containerConfig = iterator.value();
if (ContainerProps::isSupportedByCurrentPlatform(container)) {
auto errorCode = vpnConfigurationController.createProtocolConfigForContainer(m_processedServerCredentials, iterator.key(),
containerConfig);
auto errorCode =
vpnConfigurationController.createProtocolConfigForContainer(m_processedServerCredentials, iterator.key(), containerConfig);
if (errorCode) {
emit installationErrorOccurred(errorString(errorCode));
return;
@@ -210,7 +199,7 @@ void InstallController::installServer(const DockerContainer container, const QMa
containerConfigs.append(containerConfig);
errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName()), serverController);
QString("Admin [%1]").arg(QSysInfo::prettyProductName()));
if (errorCode) {
emit installationErrorOccurred(errorString(errorCode));
return;
@@ -229,20 +218,18 @@ void InstallController::installServer(const DockerContainer container, const QMa
}
void InstallController::installContainer(const DockerContainer container, const QMap<DockerContainer, QJsonObject> &installedContainers,
const ServerCredentials &serverCredentials,
const QSharedPointer<ServerController> &serverController, QString &finishMessage)
const ServerCredentials &serverCredentials, QString &finishMessage)
{
bool isInstalledContainerAddedToGui = false;
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
VpnConfigurationsController vpnConfigurationController(m_settings);
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
QJsonObject containerConfig = m_containersModel->getContainerConfig(iterator.key());
if (containerConfig.isEmpty()) {
containerConfig = iterator.value();
if (ContainerProps::isSupportedByCurrentPlatform(container)) {
auto errorCode =
vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, iterator.key(), containerConfig);
auto errorCode = vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, iterator.key(), containerConfig);
if (errorCode) {
emit installationErrorOccurred(errorString(errorCode));
return;
@@ -250,7 +237,7 @@ void InstallController::installContainer(const DockerContainer container, const
m_serversModel->addContainerConfig(iterator.key(), containerConfig);
errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName()), serverController);
QString("Admin [%1]").arg(QSysInfo::prettyProductName()));
if (errorCode) {
emit installationErrorOccurred(errorString(errorCode));
return;
@@ -292,13 +279,14 @@ void InstallController::scanServerForInstalledContainers()
ServerCredentials serverCredentials =
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
ServerController serverController(m_settings);
QMap<DockerContainer, QJsonObject> installedContainers;
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, serverController, installedContainers);
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, installedContainers);
if (errorCode == ErrorCode::NoError) {
bool isInstalledContainerAddedToGui = false;
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
VpnConfigurationsController vpnConfigurationController(m_settings);
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
auto container = iterator.key();
@@ -316,8 +304,7 @@ void InstallController::scanServerForInstalledContainers()
m_serversModel->addContainerConfig(container, containerConfig);
errorCode = m_clientManagementModel->appendClient(container, serverCredentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName()),
serverController);
QString("Admin [%1]").arg(QSysInfo::prettyProductName()));
if (errorCode) {
emit installationErrorOccurred(errorString(errorCode));
return;
@@ -338,7 +325,6 @@ void InstallController::scanServerForInstalledContainers()
}
ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController,
QMap<DockerContainer, QJsonObject> &installedContainers)
{
QString stdOut;
@@ -351,9 +337,10 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
return ErrorCode::NoError;
};
ServerController serverController(m_settings);
QString script = QString("sudo docker ps --format '{{.Names}} {{.Ports}}'");
ErrorCode errorCode = serverController->runScript(credentials, script, cbReadStdOut, cbReadStdErr);
ErrorCode errorCode = serverController.runScript(credentials, script, cbReadStdOut, cbReadStdErr);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
@@ -380,8 +367,8 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
containerConfig.insert(config_key::transport_proto, transportProto);
if (protocol == Proto::Awg) {
QString serverConfig = serverController->getTextFileFromContainer(container, credentials,
protocols::awg::serverConfigPath, errorCode);
QString serverConfig = serverController.getTextFileFromContainer(container, credentials,
protocols::awg::serverConfigPath, errorCode);
QMap<QString, QString> serverConfigMap;
auto serverConfigLines = serverConfig.split("\n");
@@ -412,7 +399,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
stdOut.clear();
script = QString("sudo docker inspect --format '{{.Config.Cmd}}' %1").arg(name);
ErrorCode errorCode = serverController->runScript(credentials, script, cbReadStdOut, cbReadStdErr);
ErrorCode errorCode = serverController.runScript(credentials, script, cbReadStdOut, cbReadStdErr);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
@@ -456,7 +443,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
stdOut.clear();
script = QString("sudo docker exec -i %1 sh -c 'cat /var/lib/tor/hidden_service/hostname'").arg(name);
ErrorCode errorCode = serverController->runScript(credentials, script, cbReadStdOut, cbReadStdErr);
ErrorCode errorCode = serverController.runScript(credentials, script, cbReadStdOut, cbReadStdErr);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
@@ -493,12 +480,12 @@ void InstallController::updateContainer(QJsonObject config)
ErrorCode errorCode = ErrorCode::NoError;
if (isUpdateDockerContainerRequired(container, oldContainerConfig, config)) {
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
connect(serverController.get(), &ServerController::serverIsBusy, this, &InstallController::serverIsBusy);
connect(this, &InstallController::cancelInstallation, serverController.get(), &ServerController::cancelInstallation);
ServerController serverController(m_settings);
connect(&serverController, &ServerController::serverIsBusy, this, &InstallController::serverIsBusy);
connect(this, &InstallController::cancelInstallation, &serverController, &ServerController::cancelInstallation);
errorCode = serverController->updateContainer(serverCredentials, container, oldContainerConfig, config);
clearCachedProfile(serverController);
errorCode = serverController.updateContainer(serverCredentials, container, oldContainerConfig, config);
clearCachedProfile();
}
if (errorCode == ErrorCode::NoError) {
@@ -523,13 +510,8 @@ void InstallController::rebootProcessedServer()
int serverIndex = m_serversModel->getProcessedServerIndex();
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
const auto errorCode = m_serversModel->rebootServer(serverController);
if (errorCode == ErrorCode::NoError) {
emit rebootProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName));
} else {
emit installationErrorOccurred(errorString(errorCode));
}
m_serversModel->rebootServer();
emit rebootProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName));
}
void InstallController::removeProcessedServer()
@@ -546,13 +528,13 @@ void InstallController::removeAllContainers()
int serverIndex = m_serversModel->getProcessedServerIndex();
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = m_serversModel->removeAllContainers(serverController);
ErrorCode errorCode = m_serversModel->removeAllContainers();
if (errorCode == ErrorCode::NoError) {
emit removeAllContainersFinished(tr("All containers from server '%1' have been removed").arg(serverName));
return;
}
emit installationErrorOccurred(errorString(errorCode));
qDebug() << errorString(errorCode);
}
void InstallController::removeProcessedContainer()
@@ -563,8 +545,7 @@ void InstallController::removeProcessedContainer()
int container = m_containersModel->getProcessedContainerIndex();
QString containerName = m_containersModel->getProcessedContainerName();
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = m_serversModel->removeContainer(serverController, container);
ErrorCode errorCode = m_serversModel->removeContainer(container);
if (errorCode == ErrorCode::NoError) {
emit removeProcessedContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName));
@@ -573,18 +554,9 @@ void InstallController::removeProcessedContainer()
emit installationErrorOccurred(errorString(errorCode));
}
void InstallController::removeApiConfig(const int serverIndex)
void InstallController::removeApiConfig()
{
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
#ifdef Q_OS_IOS
QString vpncName = QString("%1 (%2) %3")
.arg(serverConfig[config_key::description].toString())
.arg(serverConfig[config_key::hostName].toString())
.arg(serverConfig[config_key::vpnproto].toString());
AmneziaVPN::removeVPNC(vpncName.toStdString());
#endif
auto serverConfig = m_serversModel->getServerConfig(m_serversModel->getDefaultServerIndex());
serverConfig.remove(config_key::dns1);
serverConfig.remove(config_key::dns2);
@@ -593,15 +565,11 @@ void InstallController::removeApiConfig(const int serverIndex)
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
m_serversModel->editServer(serverConfig, serverIndex);
m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex());
}
void InstallController::clearCachedProfile(QSharedPointer<ServerController> serverController)
void InstallController::clearCachedProfile()
{
if (serverController.isNull()) {
serverController.reset(new ServerController(m_settings));
}
int serverIndex = m_serversModel->getProcessedServerIndex();
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getProcessedContainerIndex());
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
@@ -609,7 +577,7 @@ void InstallController::clearCachedProfile(QSharedPointer<ServerController> serv
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
m_serversModel->clearCachedProfile(container);
m_clientManagementModel->revokeClient(containerConfig, container, serverCredentials, serverIndex, serverController);
m_clientManagementModel->revokeClient(containerConfig, container, serverCredentials, serverIndex);
emit cachedProfileCleared(tr("%1 cached profile cleared").arg(ContainerProps::containerHumanNames().value(container)));
}
@@ -711,15 +679,13 @@ void InstallController::mountSftpDrive(const QString &port, const QString &passw
process->write((password + "\n").toUtf8());
}
#endif
}
bool InstallController::checkSshConnection(QSharedPointer<ServerController> serverController)
bool InstallController::checkSshConnection()
{
if (serverController.isNull()) {
serverController.reset(new ServerController(m_settings));
}
ServerController serverController(m_settings);
ErrorCode errorCode = ErrorCode::NoError;
m_privateKeyPassphrase = "";
@@ -734,7 +700,7 @@ bool InstallController::checkSshConnection(QSharedPointer<ServerController> serv
};
QString decryptedPrivateKey;
errorCode = serverController->getDecryptedPrivateKey(m_processedServerCredentials, decryptedPrivateKey, passphraseCallback);
errorCode = serverController.getDecryptedPrivateKey(m_processedServerCredentials, decryptedPrivateKey, passphraseCallback);
if (errorCode == ErrorCode::NoError) {
m_processedServerCredentials.secretData = decryptedPrivateKey;
} else {
@@ -744,7 +710,7 @@ bool InstallController::checkSshConnection(QSharedPointer<ServerController> serv
}
QString output;
output = serverController->checkSshConnection(m_processedServerCredentials, errorCode);
output = serverController.checkSshConnection(m_processedServerCredentials, errorCode);
if (errorCode != ErrorCode::NoError) {
emit installationErrorOccurred(errorString(errorCode));
@@ -781,8 +747,7 @@ void InstallController::addEmptyServer()
emit installServerFinished(tr("Server added successfully"));
}
bool InstallController::isUpdateDockerContainerRequired(const DockerContainer container, const QJsonObject &oldConfig,
const QJsonObject &newConfig)
bool InstallController::isUpdateDockerContainerRequired(const DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig)
{
Proto mainProto = ContainerProps::defaultProtocol(container);

View File

@@ -35,16 +35,16 @@ public slots:
void removeAllContainers();
void removeProcessedContainer();
void removeApiConfig(const int serverIndex);
void removeApiConfig();
void clearCachedProfile(QSharedPointer<ServerController> serverController = nullptr);
void clearCachedProfile();
QRegularExpression ipAddressPortRegExp();
QRegularExpression ipAddressRegExp();
void mountSftpDrive(const QString &port, const QString &password, const QString &username);
bool checkSshConnection(QSharedPointer<ServerController> serverController = nullptr);
bool checkSshConnection();
void setEncryptedPassphrase(QString passphrase);
@@ -79,15 +79,12 @@ signals:
private:
void installServer(const DockerContainer container, const QMap<DockerContainer, QJsonObject> &installedContainers,
const ServerCredentials &serverCredentials, const QSharedPointer<ServerController> &serverController,
QString &finishMessage);
const ServerCredentials &serverCredentials, QString &finishMessage);
void installContainer(const DockerContainer container, const QMap<DockerContainer, QJsonObject> &installedContainers,
const ServerCredentials &serverCredentials, const QSharedPointer<ServerController> &serverController,
QString &finishMessage);
const ServerCredentials &serverCredentials, QString &finishMessage);
bool isServerAlreadyExists();
ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController,
QMap<DockerContainer, QJsonObject> &installedContainers);
ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, QMap<DockerContainer, QJsonObject> &installedContainers);
bool isUpdateDockerContainerRequired(const DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig);
QSharedPointer<ServersModel> m_serversModel;

Some files were not shown because too many files have changed in this diff Show More