ssh client now reuses an existing session instead of opening a new one

This commit is contained in:
vladimir.kuznetsov 2024-04-12 20:00:21 +05:00
parent 624a84cbfb
commit ec650a65f7
32 changed files with 395 additions and 451 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -24,14 +24,14 @@
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/x509.h> #include <openssl/x509.h>
OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent) OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController,
: ConfiguratorBase(settings, parent) QObject *parent)
: ConfiguratorBase(settings, serverController, parent)
{ {
} }
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials, OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials,
DockerContainer container, DockerContainer container, ErrorCode errorCode)
ErrorCode errorCode)
{ {
OpenVpnConfigurator::ConnectionData connData = OpenVpnConfigurator::createCertRequest(); OpenVpnConfigurator::ConnectionData connData = OpenVpnConfigurator::createCertRequest();
connData.host = credentials.hostName; connData.host = credentials.hostName;
@ -43,8 +43,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
QString reqFileName = QString("%1/%2.req").arg(amnezia::protocols::openvpn::clientsDirPath).arg(connData.clientId); QString reqFileName = QString("%1/%2.req").arg(amnezia::protocols::openvpn::clientsDirPath).arg(connData.clientId);
ServerController serverController(m_settings); errorCode = m_serverController->uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
errorCode = serverController.uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return connData; return connData;
} }
@ -54,18 +53,16 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
return connData; return connData;
} }
connData.caCert = serverController.getTextFileFromContainer(container, credentials, connData.caCert =
amnezia::protocols::openvpn::caCertPath, errorCode); m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::caCertPath, errorCode);
connData.clientCert = serverController.getTextFileFromContainer( connData.clientCert = m_serverController->getTextFileFromContainer(
container, credentials, container, credentials, QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), errorCode);
QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), errorCode);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return connData; return connData;
} }
connData.taKey = serverController.getTextFileFromContainer(container, credentials, connData.taKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath, errorCode);
amnezia::protocols::openvpn::taKeyPath, errorCode);
if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) { if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) {
errorCode = ErrorCode::SshScpFailureError; errorCode = ErrorCode::SshScpFailureError;
@ -77,10 +74,8 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
QString OpenVpnConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, QString OpenVpnConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, ErrorCode errorCode) const QJsonObject &containerConfig, ErrorCode errorCode)
{ {
ServerController serverController(m_settings); QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
QString config = m_serverController->genVarsForScript(credentials, container, containerConfig));
serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
serverController.genVarsForScript(credentials, container, containerConfig));
ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode); ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
@ -194,12 +189,10 @@ ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, const ServerC
.arg(ContainerProps::containerToString(container)) .arg(ContainerProps::containerToString(container))
.arg(clientId); .arg(clientId);
ServerController serverController(m_settings);
QStringList scriptList { script_import, script_sign }; QStringList scriptList { script_import, script_sign };
QString script = serverController.replaceVars(scriptList.join("\n"), QString script = m_serverController->replaceVars(scriptList.join("\n"), m_serverController->genVarsForScript(credentials, container));
serverController.genVarsForScript(credentials, container));
return serverController.runScript(credentials, script); return m_serverController->runScript(credentials, script);
} }
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest() OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
@ -233,8 +226,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, "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, "O", MBSTRING_ASC, (unsigned char *)"", -1, -1, 0);
X509_NAME_add_entry_by_txt(x509_name, "CN", MBSTRING_ASC, X509_NAME_add_entry_by_txt(x509_name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char const *>(clientIdUtf8.data()),
reinterpret_cast<unsigned char const *>(clientIdUtf8.data()), clientIdUtf8.size(), -1, 0); clientIdUtf8.size(), -1, 0);
// 4. set public key of x509 req // 4. set public key of x509 req
ret = X509_REQ_set_pubkey(x509_req, pKey); ret = X509_REQ_set_pubkey(x509_req, pKey);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -23,6 +23,13 @@ namespace libssh {
ErrorCode Client::connectToHost(const ServerCredentials &credentials) 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) { if (m_session == nullptr) {
m_session = ssh_new(); m_session = ssh_new();

View file

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

View file

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

View file

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

View file

@ -10,11 +10,11 @@
#include "core/controllers/serverController.h" #include "core/controllers/serverController.h"
#include "core/controllers/vpnConfigurationController.h" #include "core/controllers/vpnConfigurationController.h"
#include "core/errorstrings.h" #include "core/errorstrings.h"
#include "logger.h"
#include "core/networkUtilities.h" #include "core/networkUtilities.h"
#include "utilities.h" #include "logger.h"
#include "ui/models/protocols/awgConfigModel.h" #include "ui/models/protocols/awgConfigModel.h"
#include "ui/models/protocols/wireguardConfigModel.h" #include "ui/models/protocols/wireguardConfigModel.h"
#include "utilities.h"
namespace namespace
{ {
@ -132,12 +132,12 @@ void InstallController::install(DockerContainer container, int port, TransportPr
serverCredentials = qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); serverCredentials = qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
} }
ServerController serverController(m_settings); QSharedPointer<ServerController> serverController(new ServerController(m_settings));
connect(&serverController, &ServerController::serverIsBusy, this, &InstallController::serverIsBusy); connect(serverController.get(), &ServerController::serverIsBusy, this, &InstallController::serverIsBusy);
connect(this, &InstallController::cancelInstallation, &serverController, &ServerController::cancelInstallation); connect(this, &InstallController::cancelInstallation, serverController.get(), &ServerController::cancelInstallation);
QMap<DockerContainer, QJsonObject> installedContainers; QMap<DockerContainer, QJsonObject> installedContainers;
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, installedContainers); ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, serverController, installedContainers);
if (errorCode) { if (errorCode) {
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
return; return;
@ -146,7 +146,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr
QString finishMessage = ""; QString finishMessage = "";
if (!installedContainers.contains(container)) { if (!installedContainers.contains(container)) {
errorCode = serverController.setupContainer(serverCredentials, container, config); errorCode = serverController->setupContainer(serverCredentials, container, config);
if (errorCode) { if (errorCode) {
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
return; return;
@ -164,14 +164,15 @@ void InstallController::install(DockerContainer container, int port, TransportPr
} }
if (m_shouldCreateServer) { if (m_shouldCreateServer) {
installServer(container, installedContainers, serverCredentials, finishMessage); installServer(container, installedContainers, serverCredentials, serverController, finishMessage);
} else { } else {
installContainer(container, installedContainers, serverCredentials, finishMessage); installContainer(container, installedContainers, serverCredentials, serverController, finishMessage);
} }
} }
void InstallController::installServer(const DockerContainer container, const QMap<DockerContainer, QJsonObject> &installedContainers, void InstallController::installServer(const DockerContainer container, const QMap<DockerContainer, QJsonObject> &installedContainers,
const ServerCredentials &serverCredentials, QString &finishMessage) const ServerCredentials &serverCredentials, const QSharedPointer<ServerController> &serverController,
QString &finishMessage)
{ {
if (installedContainers.size() > 1) { if (installedContainers.size() > 1) {
finishMessage += tr("\nAdded containers that were already installed on the server"); finishMessage += tr("\nAdded containers that were already installed on the server");
@ -185,13 +186,13 @@ void InstallController::installServer(const DockerContainer container, const QMa
server.insert(config_key::description, m_settings->nextAvailableServerName()); server.insert(config_key::description, m_settings->nextAvailableServerName());
QJsonArray containerConfigs; QJsonArray containerConfigs;
VpnConfigurationsController vpnConfigurationController(m_settings); VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
auto containerConfig = iterator.value(); auto containerConfig = iterator.value();
if (ContainerProps::isSupportedByCurrentPlatform(container)) { if (ContainerProps::isSupportedByCurrentPlatform(container)) {
auto errorCode = auto errorCode = vpnConfigurationController.createProtocolConfigForContainer(m_processedServerCredentials, iterator.key(),
vpnConfigurationController.createProtocolConfigForContainer(m_processedServerCredentials, iterator.key(), containerConfig); containerConfig);
if (errorCode) { if (errorCode) {
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
return; return;
@ -199,7 +200,7 @@ void InstallController::installServer(const DockerContainer container, const QMa
containerConfigs.append(containerConfig); containerConfigs.append(containerConfig);
errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig, errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName())); QString("Admin [%1]").arg(QSysInfo::prettyProductName()), serverController);
if (errorCode) { if (errorCode) {
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
return; return;
@ -218,18 +219,20 @@ void InstallController::installServer(const DockerContainer container, const QMa
} }
void InstallController::installContainer(const DockerContainer container, const QMap<DockerContainer, QJsonObject> &installedContainers, void InstallController::installContainer(const DockerContainer container, const QMap<DockerContainer, QJsonObject> &installedContainers,
const ServerCredentials &serverCredentials, QString &finishMessage) const ServerCredentials &serverCredentials,
const QSharedPointer<ServerController> &serverController, QString &finishMessage)
{ {
bool isInstalledContainerAddedToGui = false; bool isInstalledContainerAddedToGui = false;
VpnConfigurationsController vpnConfigurationController(m_settings); VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
QJsonObject containerConfig = m_containersModel->getContainerConfig(iterator.key()); QJsonObject containerConfig = m_containersModel->getContainerConfig(iterator.key());
if (containerConfig.isEmpty()) { if (containerConfig.isEmpty()) {
containerConfig = iterator.value(); containerConfig = iterator.value();
if (ContainerProps::isSupportedByCurrentPlatform(container)) { if (ContainerProps::isSupportedByCurrentPlatform(container)) {
auto errorCode = vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, iterator.key(), containerConfig); auto errorCode =
vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, iterator.key(), containerConfig);
if (errorCode) { if (errorCode) {
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
return; return;
@ -237,7 +240,7 @@ void InstallController::installContainer(const DockerContainer container, const
m_serversModel->addContainerConfig(iterator.key(), containerConfig); m_serversModel->addContainerConfig(iterator.key(), containerConfig);
errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig, errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName())); QString("Admin [%1]").arg(QSysInfo::prettyProductName()), serverController);
if (errorCode) { if (errorCode) {
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
return; return;
@ -279,14 +282,13 @@ void InstallController::scanServerForInstalledContainers()
ServerCredentials serverCredentials = ServerCredentials serverCredentials =
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
ServerController serverController(m_settings);
QMap<DockerContainer, QJsonObject> installedContainers; QMap<DockerContainer, QJsonObject> installedContainers;
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, installedContainers); QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, serverController, installedContainers);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
bool isInstalledContainerAddedToGui = false; bool isInstalledContainerAddedToGui = false;
VpnConfigurationsController vpnConfigurationController(m_settings); VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
auto container = iterator.key(); auto container = iterator.key();
@ -304,7 +306,8 @@ void InstallController::scanServerForInstalledContainers()
m_serversModel->addContainerConfig(container, containerConfig); m_serversModel->addContainerConfig(container, containerConfig);
errorCode = m_clientManagementModel->appendClient(container, serverCredentials, containerConfig, errorCode = m_clientManagementModel->appendClient(container, serverCredentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName())); QString("Admin [%1]").arg(QSysInfo::prettyProductName()),
serverController);
if (errorCode) { if (errorCode) {
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
return; return;
@ -325,6 +328,7 @@ void InstallController::scanServerForInstalledContainers()
} }
ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentials &credentials, ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController,
QMap<DockerContainer, QJsonObject> &installedContainers) QMap<DockerContainer, QJsonObject> &installedContainers)
{ {
QString stdOut; QString stdOut;
@ -337,10 +341,9 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
return ErrorCode::NoError; return ErrorCode::NoError;
}; };
ServerController serverController(m_settings);
QString script = QString("sudo docker ps --format '{{.Names}} {{.Ports}}'"); 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) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
@ -367,7 +370,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
containerConfig.insert(config_key::transport_proto, transportProto); containerConfig.insert(config_key::transport_proto, transportProto);
if (protocol == Proto::Awg) { if (protocol == Proto::Awg) {
QString serverConfig = serverController.getTextFileFromContainer(container, credentials, QString serverConfig = serverController->getTextFileFromContainer(container, credentials,
protocols::awg::serverConfigPath, errorCode); protocols::awg::serverConfigPath, errorCode);
QMap<QString, QString> serverConfigMap; QMap<QString, QString> serverConfigMap;
@ -399,7 +402,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
stdOut.clear(); stdOut.clear();
script = QString("sudo docker inspect --format '{{.Config.Cmd}}' %1").arg(name); 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) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
@ -443,7 +446,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
stdOut.clear(); stdOut.clear();
script = QString("sudo docker exec -i %1 sh -c 'cat /var/lib/tor/hidden_service/hostname'").arg(name); 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) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
@ -480,12 +483,12 @@ void InstallController::updateContainer(QJsonObject config)
ErrorCode errorCode = ErrorCode::NoError; ErrorCode errorCode = ErrorCode::NoError;
if (isUpdateDockerContainerRequired(container, oldContainerConfig, config)) { if (isUpdateDockerContainerRequired(container, oldContainerConfig, config)) {
ServerController serverController(m_settings); QSharedPointer<ServerController> serverController(new ServerController(m_settings));
connect(&serverController, &ServerController::serverIsBusy, this, &InstallController::serverIsBusy); connect(serverController.get(), &ServerController::serverIsBusy, this, &InstallController::serverIsBusy);
connect(this, &InstallController::cancelInstallation, &serverController, &ServerController::cancelInstallation); connect(this, &InstallController::cancelInstallation, serverController.get(), &ServerController::cancelInstallation);
errorCode = serverController.updateContainer(serverCredentials, container, oldContainerConfig, config); errorCode = serverController->updateContainer(serverCredentials, container, oldContainerConfig, config);
clearCachedProfile(); clearCachedProfile(serverController);
} }
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
@ -510,13 +513,11 @@ void InstallController::rebootProcessedServer()
int serverIndex = m_serversModel->getProcessedServerIndex(); int serverIndex = m_serversModel->getProcessedServerIndex();
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString(); QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
const auto errorCode = m_serversModel->rebootServer(); QSharedPointer<ServerController> serverController(new ServerController(m_settings));
if (errorCode == ErrorCode::NoError) const auto errorCode = m_serversModel->rebootServer(serverController);
{ if (errorCode == ErrorCode::NoError) {
emit rebootProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName)); emit rebootProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName));
} } else {
else
{
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
} }
} }
@ -535,7 +536,8 @@ void InstallController::removeAllContainers()
int serverIndex = m_serversModel->getProcessedServerIndex(); int serverIndex = m_serversModel->getProcessedServerIndex();
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString(); QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
ErrorCode errorCode = m_serversModel->removeAllContainers(); QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = m_serversModel->removeAllContainers(serverController);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
emit removeAllContainersFinished(tr("All containers from server '%1' have been removed").arg(serverName)); emit removeAllContainersFinished(tr("All containers from server '%1' have been removed").arg(serverName));
return; return;
@ -551,7 +553,8 @@ void InstallController::removeProcessedContainer()
int container = m_containersModel->getProcessedContainerIndex(); int container = m_containersModel->getProcessedContainerIndex();
QString containerName = m_containersModel->getProcessedContainerName(); QString containerName = m_containersModel->getProcessedContainerName();
ErrorCode errorCode = m_serversModel->removeContainer(container); QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = m_serversModel->removeContainer(serverController, container);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
emit removeProcessedContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName)); emit removeProcessedContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName));
@ -574,8 +577,12 @@ void InstallController::removeApiConfig()
m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex()); m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex());
} }
void InstallController::clearCachedProfile() void InstallController::clearCachedProfile(QSharedPointer<ServerController> serverController)
{ {
if (serverController.isNull()) {
serverController.reset(new ServerController(m_settings));
}
int serverIndex = m_serversModel->getProcessedServerIndex(); int serverIndex = m_serversModel->getProcessedServerIndex();
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getProcessedContainerIndex()); DockerContainer container = static_cast<DockerContainer>(m_containersModel->getProcessedContainerIndex());
QJsonObject containerConfig = m_containersModel->getContainerConfig(container); QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
@ -583,7 +590,7 @@ void InstallController::clearCachedProfile()
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
m_serversModel->clearCachedProfile(container); m_serversModel->clearCachedProfile(container);
m_clientManagementModel->revokeClient(containerConfig, container, serverCredentials, serverIndex); m_clientManagementModel->revokeClient(containerConfig, container, serverCredentials, serverIndex, serverController);
emit cachedProfileCleared(tr("%1 cached profile cleared").arg(ContainerProps::containerHumanNames().value(container))); emit cachedProfileCleared(tr("%1 cached profile cleared").arg(ContainerProps::containerHumanNames().value(container)));
} }
@ -685,13 +692,15 @@ void InstallController::mountSftpDrive(const QString &port, const QString &passw
process->write((password + "\n").toUtf8()); process->write((password + "\n").toUtf8());
} }
#endif #endif
} }
bool InstallController::checkSshConnection() bool InstallController::checkSshConnection(QSharedPointer<ServerController> serverController)
{ {
ServerController serverController(m_settings); if (serverController.isNull()) {
serverController.reset(new ServerController(m_settings));
}
ErrorCode errorCode = ErrorCode::NoError; ErrorCode errorCode = ErrorCode::NoError;
m_privateKeyPassphrase = ""; m_privateKeyPassphrase = "";
@ -706,7 +715,7 @@ bool InstallController::checkSshConnection()
}; };
QString decryptedPrivateKey; QString decryptedPrivateKey;
errorCode = serverController.getDecryptedPrivateKey(m_processedServerCredentials, decryptedPrivateKey, passphraseCallback); errorCode = serverController->getDecryptedPrivateKey(m_processedServerCredentials, decryptedPrivateKey, passphraseCallback);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
m_processedServerCredentials.secretData = decryptedPrivateKey; m_processedServerCredentials.secretData = decryptedPrivateKey;
} else { } else {
@ -716,7 +725,7 @@ bool InstallController::checkSshConnection()
} }
QString output; QString output;
output = serverController.checkSshConnection(m_processedServerCredentials, errorCode); output = serverController->checkSshConnection(m_processedServerCredentials, errorCode);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit installationErrorOccurred(errorString(errorCode)); emit installationErrorOccurred(errorString(errorCode));
@ -753,7 +762,8 @@ void InstallController::addEmptyServer()
emit installServerFinished(tr("Server added successfully")); 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); Proto mainProto = ContainerProps::defaultProtocol(container);

View file

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

View file

@ -64,13 +64,12 @@ void ClientManagementModel::migration(const QByteArray &clientsTableString)
} }
} }
ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCredentials credentials) ErrorCode ClientManagementModel::updateModel(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController)
{ {
beginResetModel(); beginResetModel();
m_clientsTable = QJsonArray(); m_clientsTable = QJsonArray();
ServerController serverController(m_settings);
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
@ -80,7 +79,7 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container)); clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
} }
const QByteArray clientsTableString = serverController.getTextFileFromContainer(container, credentials, clientsTableFile, error); const QByteArray clientsTableString = serverController->getTextFileFromContainer(container, credentials, clientsTableFile, error);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the clientsTable file from the server"; logger.error() << "Failed to get the clientsTable file from the server";
endResetModel(); endResetModel();
@ -95,9 +94,9 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
int count = 0; int count = 0;
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
error = getOpenVpnClients(serverController, container, credentials, count); error = getOpenVpnClients(container, credentials, serverController, count);
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) { } else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
error = getWireGuardClients(serverController, container, credentials, count); error = getWireGuardClients(container, credentials, serverController, count);
} }
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
endResetModel(); endResetModel();
@ -106,7 +105,7 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
const QByteArray newClientsTableString = QJsonDocument(m_clientsTable).toJson(); const QByteArray newClientsTableString = QJsonDocument(m_clientsTable).toJson();
if (clientsTableString != newClientsTableString) { if (clientsTableString != newClientsTableString) {
error = serverController.uploadTextFileToContainer(container, credentials, newClientsTableString, clientsTableFile); error = serverController->uploadTextFileToContainer(container, credentials, newClientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server"; logger.error() << "Failed to upload the clientsTable file to the server";
} }
@ -117,8 +116,8 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
return error; return error;
} }
ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverController, DockerContainer container, ErrorCode ClientManagementModel::getOpenVpnClients(const DockerContainer container, const ServerCredentials &credentials,
ServerCredentials credentials, int &count) const QSharedPointer<ServerController> &serverController, int &count)
{ {
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
QString stdOut; QString stdOut;
@ -128,8 +127,8 @@ ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverContr
}; };
const QString getOpenVpnClientsList = "sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'"; const QString getOpenVpnClientsList = "sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'";
QString script = serverController.replaceVars(getOpenVpnClientsList, serverController.genVarsForScript(credentials, container)); QString script = serverController->replaceVars(getOpenVpnClientsList, serverController->genVarsForScript(credentials, container));
error = serverController.runScript(credentials, script, cbReadStdOut); error = serverController->runScript(credentials, script, cbReadStdOut);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to retrieve the list of issued certificates on the server"; logger.error() << "Failed to retrieve the list of issued certificates on the server";
return error; return error;
@ -158,13 +157,13 @@ ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverContr
return error; return error;
} }
ErrorCode ClientManagementModel::getWireGuardClients(ServerController &serverController, DockerContainer container, ErrorCode ClientManagementModel::getWireGuardClients(const DockerContainer container, const ServerCredentials &credentials,
ServerCredentials credentials, int &count) const QSharedPointer<ServerController> &serverController, int &count)
{ {
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
const QString wireGuardConfigFile = QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg"); const QString wireGuardConfigFile = QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
const QString wireguardConfigString = serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, error); const QString wireguardConfigString = serverController->getTextFileFromContainer(container, credentials, wireGuardConfigFile, error);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the wg conf file from the server"; logger.error() << "Failed to get the wg conf file from the server";
return error; return error;
@ -198,7 +197,7 @@ ErrorCode ClientManagementModel::getWireGuardClients(ServerController &serverCon
bool ClientManagementModel::isClientExists(const QString &clientId) bool ClientManagementModel::isClientExists(const QString &clientId)
{ {
for (const QJsonValue &value : qAsConst(m_clientsTable)) { for (const QJsonValue &value : std::as_const(m_clientsTable)) {
if (value.isObject()) { if (value.isObject()) {
QJsonObject obj = value.toObject(); QJsonObject obj = value.toObject();
if (obj.contains(configKey::clientId) && obj[configKey::clientId].toString() == clientId) { if (obj.contains(configKey::clientId) && obj[configKey::clientId].toString() == clientId) {
@ -210,7 +209,8 @@ bool ClientManagementModel::isClientExists(const QString &clientId)
} }
ErrorCode ClientManagementModel::appendClient(const DockerContainer container, const ServerCredentials &credentials, ErrorCode ClientManagementModel::appendClient(const DockerContainer container, const ServerCredentials &credentials,
const QJsonObject &containerConfig, const QString &clientName) const QJsonObject &containerConfig, const QString &clientName,
const QSharedPointer<ServerController> &serverController)
{ {
Proto protocol; Proto protocol;
if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
@ -223,22 +223,22 @@ ErrorCode ClientManagementModel::appendClient(const DockerContainer container, c
auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig); auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig);
return appendClient(protocolConfig.value(config_key::clientId).toString(), clientName, container, credentials); return appendClient(protocolConfig.value(config_key::clientId).toString(), clientName, container, credentials, serverController);
} }
ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QString &clientName, const DockerContainer container, ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
ServerCredentials credentials) const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController)
{ {
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
error = updateModel(container, credentials); error = updateModel(container, credentials, serverController);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
return error; return error;
} }
for (int i = 0; i < m_clientsTable.size(); i++) { for (int i = 0; i < m_clientsTable.size(); i++) {
if (m_clientsTable.at(i).toObject().value(configKey::clientId) == clientId) { if (m_clientsTable.at(i).toObject().value(configKey::clientId) == clientId) {
return renameClient(i, clientName, container, credentials, true); return renameClient(i, clientName, container, credentials, serverController, true);
} }
} }
@ -255,7 +255,6 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson(); const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
ServerController serverController(m_settings);
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)); clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
@ -263,7 +262,7 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container)); clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
} }
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server"; logger.error() << "Failed to upload the clientsTable file to the server";
} }
@ -272,7 +271,8 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
} }
ErrorCode ClientManagementModel::renameClient(const int row, const QString &clientName, const DockerContainer container, ErrorCode ClientManagementModel::renameClient(const int row, const QString &clientName, const DockerContainer container,
ServerCredentials credentials, bool addTimeStamp) const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, bool addTimeStamp)
{ {
auto client = m_clientsTable.at(row).toObject(); auto client = m_clientsTable.at(row).toObject();
auto userData = client[configKey::userData].toObject(); auto userData = client[configKey::userData].toObject();
@ -287,7 +287,6 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson(); const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
ServerController serverController(m_settings);
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)); clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
@ -295,7 +294,7 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container)); clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
} }
ErrorCode error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); ErrorCode error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server"; logger.error() << "Failed to upload the clientsTable file to the server";
} }
@ -303,17 +302,17 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
return error; return error;
} }
ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContainer container, ServerCredentials credentials, ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContainer container, const ServerCredentials &credentials,
const int serverIndex) const int serverIndex, const QSharedPointer<ServerController> &serverController)
{ {
ErrorCode errorCode = ErrorCode::NoError; ErrorCode errorCode = ErrorCode::NoError;
auto client = m_clientsTable.at(row).toObject(); auto client = m_clientsTable.at(row).toObject();
QString clientId = client.value(configKey::clientId).toString(); QString clientId = client.value(configKey::clientId).toString();
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
errorCode = revokeOpenVpn(row, container, credentials, serverIndex); errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) { } else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
errorCode = revokeWireGuard(row, container, credentials); errorCode = revokeWireGuard(row, container, credentials, serverController);
} }
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
@ -340,11 +339,12 @@ ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContain
return errorCode; return errorCode;
} }
ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig, const DockerContainer container, ServerCredentials credentials, ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig, const DockerContainer container,
const int serverIndex) const ServerCredentials &credentials, const int serverIndex,
const QSharedPointer<ServerController> &serverController)
{ {
ErrorCode errorCode = ErrorCode::NoError; ErrorCode errorCode = ErrorCode::NoError;
errorCode = updateModel(container, credentials); errorCode = updateModel(container, credentials, serverController);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
@ -375,15 +375,15 @@ ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig
} }
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
errorCode = revokeOpenVpn(row, container, credentials, serverIndex); errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) { } else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
errorCode = revokeWireGuard(row, container, credentials); errorCode = revokeWireGuard(row, container, credentials, serverController);
} }
return errorCode; return errorCode;
} }
ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContainer container, ServerCredentials credentials, ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials,
const int serverIndex) const int serverIndex, const QSharedPointer<ServerController> &serverController)
{ {
auto client = m_clientsTable.at(row).toObject(); auto client = m_clientsTable.at(row).toObject();
QString clientId = client.value(configKey::clientId).toString(); QString clientId = client.value(configKey::clientId).toString();
@ -396,9 +396,8 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
"cp pki/crl.pem .'") "cp pki/crl.pem .'")
.arg(clientId); .arg(clientId);
ServerController serverController(m_settings); const QString script = serverController->replaceVars(getOpenVpnCertData, serverController->genVarsForScript(credentials, container));
const QString script = serverController.replaceVars(getOpenVpnCertData, serverController.genVarsForScript(credentials, container)); ErrorCode error = serverController->runScript(credentials, script);
ErrorCode error = serverController.runScript(credentials, script);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to revoke the certificate"; logger.error() << "Failed to revoke the certificate";
return error; return error;
@ -412,7 +411,7 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)); clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server"; logger.error() << "Failed to upload the clientsTable file to the server";
return error; return error;
@ -421,14 +420,14 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerContainer container, ServerCredentials credentials) ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController)
{ {
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
ServerController serverController(m_settings);
const QString wireGuardConfigFile = const QString wireGuardConfigFile =
QString("/opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg"); QString("/opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
const QString wireguardConfigString = serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, error); const QString wireguardConfigString = serverController->getTextFileFromContainer(container, credentials, wireGuardConfigFile, error);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the wg conf file from the server"; logger.error() << "Failed to get the wg conf file from the server";
return error; return error;
@ -446,7 +445,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
} }
QString newWireGuardConfig = configSections.join("["); QString newWireGuardConfig = configSections.join("[");
newWireGuardConfig.insert(0, "["); newWireGuardConfig.insert(0, "[");
error = serverController.uploadTextFileToContainer(container, credentials, newWireGuardConfig, wireGuardConfigFile); error = serverController->uploadTextFileToContainer(container, credentials, newWireGuardConfig, wireGuardConfigFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the wg conf file to the server"; logger.error() << "Failed to upload the wg conf file to the server";
return error; return error;
@ -464,16 +463,16 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
} else { } else {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container)); clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
} }
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server"; logger.error() << "Failed to upload the clientsTable file to the server";
return error; return error;
} }
const QString script = "sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'"; const QString script = "sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'";
error = serverController.runScript( error = serverController->runScript(
credentials, credentials,
serverController.replaceVars(script.arg(wireGuardConfigFile), serverController.genVarsForScript(credentials, container))); serverController->replaceVars(script.arg(wireGuardConfigFile), serverController->genVarsForScript(credentials, container)));
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to execute the command 'wg syncconf' on the server"; logger.error() << "Failed to execute the command 'wg syncconf' on the server";
return error; return error;

View file

@ -23,15 +23,18 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots: public slots:
ErrorCode updateModel(DockerContainer container, ServerCredentials credentials); ErrorCode updateModel(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController);
ErrorCode appendClient(const DockerContainer container, const ServerCredentials &credentials, const QJsonObject &containerConfig, ErrorCode appendClient(const DockerContainer container, const ServerCredentials &credentials, const QJsonObject &containerConfig,
const QString &clientName); const QString &clientName, const QSharedPointer<ServerController> &serverController);
ErrorCode appendClient(const QString &clientId, const QString &clientName, const DockerContainer container, ErrorCode appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
ServerCredentials credentials); const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController);
ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container, ServerCredentials credentials, ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container, const ServerCredentials &credentials,
bool addTimeStamp = false); const QSharedPointer<ServerController> &serverController, bool addTimeStamp = false);
ErrorCode revokeClient(const int index, const DockerContainer container, ServerCredentials credentials, const int serverIndex); ErrorCode revokeClient(const int index, const DockerContainer container, const ServerCredentials &credentials, const int serverIndex,
ErrorCode revokeClient(const QJsonObject &containerConfig, const DockerContainer container, ServerCredentials credentials, const int serverIndex); const QSharedPointer<ServerController> &serverController);
ErrorCode revokeClient(const QJsonObject &containerConfig, const DockerContainer container, const ServerCredentials &credentials,
const int serverIndex, const QSharedPointer<ServerController> &serverController);
protected: protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
@ -44,11 +47,15 @@ private:
void migration(const QByteArray &clientsTableString); void migration(const QByteArray &clientsTableString);
ErrorCode revokeOpenVpn(const int row, const DockerContainer container, ServerCredentials credentials, const int serverIndex); ErrorCode revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials, const int serverIndex,
ErrorCode revokeWireGuard(const int row, const DockerContainer container, ServerCredentials credentials); const QSharedPointer<ServerController> &serverController);
ErrorCode revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController);
ErrorCode getOpenVpnClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count); ErrorCode getOpenVpnClients(const DockerContainer container, const ServerCredentials &credentials,
ErrorCode getWireGuardClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count); const QSharedPointer<ServerController> &serverController, int &count);
ErrorCode getWireGuardClients(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, int &count);
QJsonArray m_clientsTable; QJsonArray m_clientsTable;

View file

@ -428,10 +428,10 @@ const QString ServersModel::getDefaultServerDefaultContainerName()
return ContainerProps::containerHumanNames().value(defaultContainer); return ContainerProps::containerHumanNames().value(defaultContainer);
} }
ErrorCode ServersModel::removeAllContainers() ErrorCode ServersModel::removeAllContainers(const QSharedPointer<ServerController> &serverController)
{ {
ServerController serverController(m_settings);
ErrorCode errorCode = serverController.removeAllContainers(m_settings->serverCredentials(m_processedServerIndex)); ErrorCode errorCode = serverController->removeAllContainers(m_settings->serverCredentials(m_processedServerIndex));
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
QJsonObject s = m_servers.at(m_processedServerIndex).toObject(); QJsonObject s = m_servers.at(m_processedServerIndex).toObject();
@ -443,22 +443,22 @@ ErrorCode ServersModel::removeAllContainers()
return errorCode; return errorCode;
} }
ErrorCode ServersModel::rebootServer() ErrorCode ServersModel::rebootServer(const QSharedPointer<ServerController> &serverController)
{ {
ServerController serverController(m_settings);
auto credentials = m_settings->serverCredentials(m_processedServerIndex); auto credentials = m_settings->serverCredentials(m_processedServerIndex);
ErrorCode errorCode = serverController.rebootServer(credentials); ErrorCode errorCode = serverController->rebootServer(credentials);
return errorCode; return errorCode;
} }
ErrorCode ServersModel::removeContainer(const int containerIndex) ErrorCode ServersModel::removeContainer(const QSharedPointer<ServerController> &serverController, const int containerIndex)
{ {
ServerController serverController(m_settings);
auto credentials = m_settings->serverCredentials(m_processedServerIndex); auto credentials = m_settings->serverCredentials(m_processedServerIndex);
auto dockerContainer = static_cast<DockerContainer>(containerIndex); auto dockerContainer = static_cast<DockerContainer>(containerIndex);
ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer); ErrorCode errorCode = serverController->removeContainer(credentials, dockerContainer);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
QJsonObject server = m_servers.at(m_processedServerIndex).toObject(); QJsonObject server = m_servers.at(m_processedServerIndex).toObject();

View file

@ -4,6 +4,7 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include "settings.h" #include "settings.h"
#include "core/controllers/serverController.h"
class ServersModel : public QAbstractListModel class ServersModel : public QAbstractListModel
{ {
@ -88,9 +89,9 @@ public slots:
void clearCachedProfile(const DockerContainer container); void clearCachedProfile(const DockerContainer container);
ErrorCode removeContainer(const int containerIndex); ErrorCode removeContainer(const QSharedPointer<ServerController> &serverController, const int containerIndex);
ErrorCode removeAllContainers(); ErrorCode removeAllContainers(const QSharedPointer<ServerController> &serverController);
ErrorCode rebootServer(); ErrorCode rebootServer(const QSharedPointer<ServerController> &serverController);
void setDefaultContainer(const int serverIndex, const int containerIndex); void setDefaultContainer(const int serverIndex, const int containerIndex);