diff --git a/client/configurators/awg_configurator.cpp b/client/configurators/awg_configurator.cpp index f83acb195..07ebfd8fc 100644 --- a/client/configurators/awg_configurator.cpp +++ b/client/configurators/awg_configurator.cpp @@ -9,16 +9,24 @@ AwgConfigurator::AwgConfigurator(std::shared_ptr settings, const QShar { } -QString AwgConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, - ErrorCode &errorCode) +QSharedPointer AwgConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) { - QString config = WireguardConfigurator::createConfig(credentials, container, containerConfig, errorCode); - - QJsonObject jsonConfig = QJsonDocument::fromJson(config.toUtf8()).object(); - QString awgConfig = jsonConfig.value(config_key::config).toString(); + auto result = WireguardConfigurator::createConfig(credentials, container, protocolConfig, errorCode); + if (!result) { + return nullptr; + } + + auto awgConfig = qSharedPointerCast(result); + if (!awgConfig) { + errorCode = ErrorCode::InternalError; + return nullptr; + } + + QString config = awgConfig->clientProtocolConfig.nativeConfig; QMap configMap; - auto configLines = awgConfig.split("\n"); + auto configLines = config.split("\n"); for (auto &line : configLines) { auto trimmedLine = line.trimmed(); if (trimmedLine.startsWith("[") && trimmedLine.endsWith("]")) { @@ -31,31 +39,17 @@ QString AwgConfigurator::createConfig(const ServerCredentials &credentials, Dock } } - jsonConfig[config_key::junkPacketCount] = configMap.value(config_key::junkPacketCount); - jsonConfig[config_key::junkPacketMinSize] = configMap.value(config_key::junkPacketMinSize); - jsonConfig[config_key::junkPacketMaxSize] = configMap.value(config_key::junkPacketMaxSize); - jsonConfig[config_key::initPacketJunkSize] = configMap.value(config_key::initPacketJunkSize); - jsonConfig[config_key::responsePacketJunkSize] = configMap.value(config_key::responsePacketJunkSize); - jsonConfig[config_key::initPacketMagicHeader] = configMap.value(config_key::initPacketMagicHeader); - jsonConfig[config_key::responsePacketMagicHeader] = configMap.value(config_key::responsePacketMagicHeader); - jsonConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader); - jsonConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader); + awgConfig->clientProtocolConfig.awgData.junkPacketCount = configMap.value(config_key::junkPacketCount); + awgConfig->clientProtocolConfig.awgData.junkPacketMinSize = configMap.value(config_key::junkPacketMinSize); + awgConfig->clientProtocolConfig.awgData.junkPacketMaxSize = configMap.value(config_key::junkPacketMaxSize); + awgConfig->clientProtocolConfig.awgData.initPacketJunkSize = configMap.value(config_key::initPacketJunkSize); + awgConfig->clientProtocolConfig.awgData.responsePacketJunkSize = configMap.value(config_key::responsePacketJunkSize); + awgConfig->clientProtocolConfig.awgData.initPacketMagicHeader = configMap.value(config_key::initPacketMagicHeader); + awgConfig->clientProtocolConfig.awgData.responsePacketMagicHeader = configMap.value(config_key::responsePacketMagicHeader); + awgConfig->clientProtocolConfig.awgData.underloadPacketMagicHeader = configMap.value(config_key::underloadPacketMagicHeader); + awgConfig->clientProtocolConfig.awgData.transportPacketMagicHeader = configMap.value(config_key::transportPacketMagicHeader); - // jsonConfig[config_key::cookieReplyPacketJunkSize] = configMap.value(config_key::cookieReplyPacketJunkSize); - // jsonConfig[config_key::transportPacketJunkSize] = configMap.value(config_key::transportPacketJunkSize); + awgConfig->clientProtocolConfig.wireGuardData.mtu = awgConfig->serverProtocolConfig.mtu; - // jsonConfig[config_key::specialJunk1] = configMap.value(amnezia::config_key::specialJunk1); - // jsonConfig[config_key::specialJunk2] = configMap.value(amnezia::config_key::specialJunk2); - // jsonConfig[config_key::specialJunk3] = configMap.value(amnezia::config_key::specialJunk3); - // jsonConfig[config_key::specialJunk4] = configMap.value(amnezia::config_key::specialJunk4); - // jsonConfig[config_key::specialJunk5] = configMap.value(amnezia::config_key::specialJunk5); - // jsonConfig[config_key::controlledJunk1] = configMap.value(amnezia::config_key::controlledJunk1); - // jsonConfig[config_key::controlledJunk2] = configMap.value(amnezia::config_key::controlledJunk2); - // jsonConfig[config_key::controlledJunk3] = configMap.value(amnezia::config_key::controlledJunk3); - // jsonConfig[config_key::specialHandshakeTimeout] = configMap.value(amnezia::config_key::specialHandshakeTimeout); - - jsonConfig[config_key::mtu] = - containerConfig.value(ProtocolProps::protoToString(Proto::Awg)).toObject().value(config_key::mtu).toString(protocols::awg::defaultMtu); - - return QJsonDocument(jsonConfig).toJson(); + return awgConfig; } diff --git a/client/configurators/awg_configurator.h b/client/configurators/awg_configurator.h index 301b927c7..ebab85b24 100644 --- a/client/configurators/awg_configurator.h +++ b/client/configurators/awg_configurator.h @@ -11,8 +11,8 @@ class AwgConfigurator : public WireguardConfigurator public: AwgConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent = nullptr); - QString createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode); + QSharedPointer createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) override; }; #endif // AWGCONFIGURATOR_H diff --git a/client/configurators/cloak_configurator.cpp b/client/configurators/cloak_configurator.cpp index 9ebf8b349..f78eeed23 100644 --- a/client/configurators/cloak_configurator.cpp +++ b/client/configurators/cloak_configurator.cpp @@ -6,21 +6,45 @@ #include "core/models/containers/containers_defs.h" #include "core/controllers/selfhosted/serverController.h" +#include "core/models/protocols/cloakProtocolConfig.h" +#include "protocols/protocols_defs.h" CloakConfigurator::CloakConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent) : ConfiguratorBase(settings, serverController, parent) { } -QString CloakConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, - ErrorCode &errorCode) +ConfiguratorBase::Vars CloakConfigurator::generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const { + Vars vars = generateCommonVars(credentials, container); + + auto cloakConfig = qSharedPointerCast(protocolConfig); + if (!cloakConfig) { + return vars; + } + + vars.append({{"$CLOAK_SERVER_PORT", cloakConfig->serverProtocolConfig.port}}); + vars.append({{"$FAKE_WEB_SITE_ADDRESS", cloakConfig->serverProtocolConfig.site}}); + + return vars; +} + +QSharedPointer CloakConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) +{ + auto cloakConfig = qSharedPointerCast(protocolConfig); + if (!cloakConfig) { + errorCode = ErrorCode::InternalError; + return nullptr; + } + QString cloakPublicKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::cloak::ckPublicKeyPath, errorCode); cloakPublicKey.replace("\n", ""); if (errorCode != ErrorCode::NoError) { - return ""; + return nullptr; } QString cloakBypassUid = @@ -28,24 +52,38 @@ QString CloakConfigurator::createConfig(const ServerCredentials &credentials, Do cloakBypassUid.replace("\n", ""); if (errorCode != ErrorCode::NoError) { - return ""; + return nullptr; } + cloakConfig->clientProtocolConfig.transport = "direct"; + cloakConfig->clientProtocolConfig.proxyMethod = "openvpn"; + cloakConfig->clientProtocolConfig.encryptionMethod = "aes-gcm"; + cloakConfig->clientProtocolConfig.uid = cloakBypassUid; + cloakConfig->clientProtocolConfig.publicKey = cloakPublicKey; + cloakConfig->clientProtocolConfig.serverName = cloakConfig->serverProtocolConfig.site; + cloakConfig->clientProtocolConfig.numConn = 1; + cloakConfig->clientProtocolConfig.browserSig = "chrome"; + cloakConfig->clientProtocolConfig.streamTimeout = 300; + cloakConfig->clientProtocolConfig.remoteHost = credentials.hostName; + cloakConfig->clientProtocolConfig.remotePort = cloakConfig->serverProtocolConfig.port; + QJsonObject config; - config.insert("Transport", "direct"); - config.insert("ProxyMethod", "openvpn"); - config.insert("EncryptionMethod", "aes-gcm"); - config.insert("UID", cloakBypassUid); - config.insert("PublicKey", cloakPublicKey); - config.insert("ServerName", "$FAKE_WEB_SITE_ADDRESS"); - config.insert("NumConn", 1); - config.insert("BrowserSig", "chrome"); - config.insert("StreamTimeout", 300); - config.insert("RemoteHost", credentials.hostName); - config.insert("RemotePort", "$CLOAK_SERVER_PORT"); + config.insert("Transport", cloakConfig->clientProtocolConfig.transport); + config.insert("ProxyMethod", cloakConfig->clientProtocolConfig.proxyMethod); + config.insert("EncryptionMethod", cloakConfig->clientProtocolConfig.encryptionMethod); + config.insert("UID", cloakConfig->clientProtocolConfig.uid); + config.insert("PublicKey", cloakConfig->clientProtocolConfig.publicKey); + config.insert("ServerName", cloakConfig->clientProtocolConfig.serverName); + config.insert("NumConn", cloakConfig->clientProtocolConfig.numConn); + config.insert("BrowserSig", cloakConfig->clientProtocolConfig.browserSig); + config.insert("StreamTimeout", cloakConfig->clientProtocolConfig.streamTimeout); + config.insert("RemoteHost", cloakConfig->clientProtocolConfig.remoteHost); + config.insert("RemotePort", cloakConfig->clientProtocolConfig.remotePort); - QString textCfg = m_serverController->replaceVars(QJsonDocument(config).toJson(), - m_serverController->genVarsForScript(credentials, container, containerConfig)); + QString textCfg = QJsonDocument(config).toJson(); - return textCfg; + cloakConfig->clientProtocolConfig.isEmpty = false; + cloakConfig->clientProtocolConfig.nativeConfig = textCfg; + + return cloakConfig; } diff --git a/client/configurators/cloak_configurator.h b/client/configurators/cloak_configurator.h index d117a821b..b00ef8317 100644 --- a/client/configurators/cloak_configurator.h +++ b/client/configurators/cloak_configurator.h @@ -4,6 +4,7 @@ #include #include "configurator_base.h" +#include "core/models/protocols/cloakProtocolConfig.h" using namespace amnezia; @@ -13,8 +14,11 @@ class CloakConfigurator : public ConfiguratorBase public: CloakConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent = nullptr); - QString createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode); + QSharedPointer createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) override; + + Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const override; }; #endif // CLOAK_CONFIGURATOR_H diff --git a/client/configurators/configurator_base.cpp b/client/configurators/configurator_base.cpp index 3502538c0..c661e09b8 100644 --- a/client/configurators/configurator_base.cpp +++ b/client/configurators/configurator_base.cpp @@ -1,4 +1,5 @@ #include "configurator_base.h" +#include "core/networkUtilities.h" ConfiguratorBase::ConfiguratorBase(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent) : QObject { parent }, m_settings(settings), m_serverController(serverController) @@ -24,3 +25,31 @@ void ConfiguratorBase::processConfigWithDnsSettings(const QPair &protocolConfig) const +{ + return generateCommonVars(credentials, container); +} + +ConfiguratorBase::Vars ConfiguratorBase::generateCommonVars(const ServerCredentials &credentials, DockerContainer container) const +{ + Vars vars; + + vars.append({{"$REMOTE_HOST", credentials.hostName}}); + + QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::WireGuard && container != DockerContainer::Xray) + ? NetworkUtilities::getIPAddress(credentials.hostName) + : credentials.hostName; + if (!serverIp.isEmpty()) { + vars.append({{"$SERVER_IP_ADDRESS", serverIp}}); + } + + vars.append({{"$CONTAINER_NAME", ContainerProps::containerToString(container)}}); + vars.append({{"$DOCKERFILE_FOLDER", "/opt/amnezia/" + ContainerProps::containerToString(container)}}); + + vars.append({{"$PRIMARY_SERVER_DNS", m_settings->primaryDns()}}); + vars.append({{"$SECONDARY_SERVER_DNS", m_settings->secondaryDns()}}); + + return vars; +} diff --git a/client/configurators/configurator_base.h b/client/configurators/configurator_base.h index 14c1086dc..7397527c9 100644 --- a/client/configurators/configurator_base.h +++ b/client/configurators/configurator_base.h @@ -2,29 +2,40 @@ #define CONFIGURATORBASE_H #include +#include +#include +#include #include "core/models/containers/containers_defs.h" #include "core/defs.h" #include "core/controllers/selfhosted/serverController.h" +#include "core/models/protocols/protocolConfig.h" #include "settings.h" class ConfiguratorBase : public QObject { Q_OBJECT public: + using Vars = QList>; + explicit ConfiguratorBase(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent = nullptr); - virtual QString createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode) = 0; + virtual QSharedPointer createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) = 0; virtual QString processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, QString &protocolConfigString); virtual QString processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, QString &protocolConfigString); + virtual Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const; + protected: void processConfigWithDnsSettings(const QPair &dns, QString &protocolConfigString); + Vars generateCommonVars(const ServerCredentials &credentials, DockerContainer container) const; + std::shared_ptr m_settings; QSharedPointer m_serverController; diff --git a/client/configurators/ikev2_configurator.cpp b/client/configurators/ikev2_configurator.cpp index 09f972602..7f986d253 100644 --- a/client/configurators/ikev2_configurator.cpp +++ b/client/configurators/ikev2_configurator.cpp @@ -12,6 +12,7 @@ #include "core/controllers/selfhosted/serverController.h" #include "core/scripts_registry.h" #include "core/server_defs.h" +#include "protocols/protocols_defs.h" #include "utilities.h" Ikev2Configurator::Ikev2Configurator(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent) @@ -19,6 +20,28 @@ Ikev2Configurator::Ikev2Configurator(std::shared_ptr settings, const Q { } +ConfiguratorBase::Vars Ikev2Configurator::generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const +{ + Vars vars = generateCommonVars(credentials, container); + + vars.append({{"$IPSEC_VPN_L2TP_NET", "192.168.42.0/24"}}); + vars.append({{"$IPSEC_VPN_L2TP_POOL", "192.168.42.10-192.168.42.250"}}); + vars.append({{"$IPSEC_VPN_L2TP_LOCAL", "192.168.42.1"}}); + + vars.append({{"$IPSEC_VPN_XAUTH_NET", "192.168.43.0/24"}}); + vars.append({{"$IPSEC_VPN_XAUTH_POOL", "192.168.43.10-192.168.43.250"}}); + + vars.append({{"$IPSEC_VPN_SHA2_TRUNCBUG", "yes"}}); + vars.append({{"$IPSEC_VPN_VPN_ANDROID_MTU_FIX", "yes"}}); + vars.append({{"$IPSEC_VPN_DISABLE_IKEV2", "no"}}); + vars.append({{"$IPSEC_VPN_DISABLE_L2TP", "no"}}); + vars.append({{"$IPSEC_VPN_DISABLE_XAUTH", "no"}}); + vars.append({{"$IPSEC_VPN_C2C_TRAFFIC", "no"}}); + + return vars; +} + Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials, DockerContainer container, ErrorCode &errorCode) { @@ -54,21 +77,58 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se return connData; } -QString Ikev2Configurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, - ErrorCode &errorCode) +QSharedPointer Ikev2Configurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) { - Q_UNUSED(containerConfig) + Q_UNUSED(protocolConfig) + + // IKEv2 uses a generic ProtocolConfig - no specific subclass needed + if (!protocolConfig) { + errorCode = ErrorCode::InternalError; + return nullptr; + } ConnectionData connData = prepareIkev2Config(credentials, container, errorCode); if (errorCode != ErrorCode::NoError) { - return ""; + return nullptr; } - return genIkev2Config(connData); + auto ikev2Config = qSharedPointerCast(protocolConfig); + if (!ikev2Config) { + errorCode = ErrorCode::InternalError; + return nullptr; + } + + ikev2Config->clientProtocolConfig.isEmpty = false; + ikev2Config->clientProtocolConfig.hostName = connData.host; + ikev2Config->clientProtocolConfig.userName = connData.clientId; + ikev2Config->clientProtocolConfig.cert = QString(connData.clientCert.toBase64()); + ikev2Config->clientProtocolConfig.password = connData.password; + + // Generate the appropriate native config based on platform + QString nativeConfigStr; + switch (Utils::systemType()) { + case SystemType::iOS: + [[fallthrough]]; + case SystemType::macOS: + nativeConfigStr = genMobileConfig(connData); + break; + case SystemType::Android: + nativeConfigStr = genIkev2Config(connData); + break; + default: + nativeConfigStr = genStrongSwanConfig(connData); + break; + } + + ikev2Config->clientProtocolConfig.nativeConfig = nativeConfigStr; + + return ikev2Config; } QString Ikev2Configurator::genIkev2Config(const ConnectionData &connData) { + // Create temporary JSON for Android platform (will be eliminated when android protocols are updated) QJsonObject config; config[config_key::hostName] = connData.host; config[config_key::userName] = connData.clientId; diff --git a/client/configurators/ikev2_configurator.h b/client/configurators/ikev2_configurator.h index e3a852163..e1e032b54 100644 --- a/client/configurators/ikev2_configurator.h +++ b/client/configurators/ikev2_configurator.h @@ -5,6 +5,8 @@ #include #include "configurator_base.h" +#include "core/models/protocols/protocolConfig.h" +#include "core/models/protocols/ikev2ProtocolConfig.h" #include "core/defs.h" class Ikev2Configurator : public ConfiguratorBase @@ -21,13 +23,16 @@ public: QString host; // host ip }; - QString createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode); + QSharedPointer createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) override; QString genIkev2Config(const ConnectionData &connData); QString genMobileConfig(const ConnectionData &connData); QString genStrongSwanConfig(const ConnectionData &connData); + Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const override; + ConnectionData prepareIkev2Config(const ServerCredentials &credentials, DockerContainer container, ErrorCode &errorCode); }; diff --git a/client/configurators/openvpn_configurator.cpp b/client/configurators/openvpn_configurator.cpp index 1f83bf4d8..b415e2c4a 100644 --- a/client/configurators/openvpn_configurator.cpp +++ b/client/configurators/openvpn_configurator.cpp @@ -17,6 +17,8 @@ #include "core/models/containers/containers_defs.h" #include "core/controllers/selfhosted/serverController.h" #include "core/scripts_registry.h" +#include "core/models/protocols/openvpnProtocolConfig.h" +#include "protocols/protocols_defs.h" #include "settings.h" #include "utilities.h" @@ -31,6 +33,39 @@ OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr settings, con { } +ConfiguratorBase::Vars OpenVpnConfigurator::generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const +{ + Vars vars = generateCommonVars(credentials, container); + + auto openVpnConfig = qSharedPointerCast(protocolConfig); + if (!openVpnConfig) { + return vars; + } + + vars.append({{"$OPENVPN_SUBNET_IP", openVpnConfig->serverProtocolConfig.subnetAddress}}); + vars.append({{"$OPENVPN_SUBNET_CIDR", protocols::openvpn::defaultSubnetCidr}}); + vars.append({{"$OPENVPN_SUBNET_MASK", protocols::openvpn::defaultSubnetMask}}); + + vars.append({{"$OPENVPN_PORT", openVpnConfig->serverProtocolConfig.port}}); + vars.append({{"$OPENVPN_TRANSPORT_PROTO", openVpnConfig->serverProtocolConfig.transportProto}}); + + vars.append({{"$OPENVPN_NCP_DISABLE", openVpnConfig->serverProtocolConfig.ncpDisable ? protocols::openvpn::ncpDisableString : ""}}); + + vars.append({{"$OPENVPN_CIPHER", openVpnConfig->serverProtocolConfig.cipher}}); + vars.append({{"$OPENVPN_HASH", openVpnConfig->serverProtocolConfig.hash}}); + + vars.append({{"$OPENVPN_TLS_AUTH", openVpnConfig->serverProtocolConfig.tlsAuth ? protocols::openvpn::tlsAuthString : ""}}); + if (!openVpnConfig->serverProtocolConfig.tlsAuth) { + vars.append({{"$OPENVPN_TA_KEY", ""}}); + } + + vars.append({{"$OPENVPN_ADDITIONAL_CLIENT_CONFIG", openVpnConfig->serverProtocolConfig.additionalClientConfig}}); + vars.append({{"$OPENVPN_ADDITIONAL_SERVER_CONFIG", openVpnConfig->serverProtocolConfig.additionalServerConfig}}); + + return vars; +} + OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, ErrorCode &errorCode) { @@ -72,15 +107,21 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co return connData; } -QString OpenVpnConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode) +QSharedPointer OpenVpnConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) { + auto openVpnConfig = qSharedPointerCast(protocolConfig); + if (!openVpnConfig) { + errorCode = ErrorCode::InternalError; + return nullptr; + } + QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container), - m_serverController->genVarsForScript(credentials, container, containerConfig)); + generateProtocolVars(credentials, container, protocolConfig)); ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode); if (errorCode != ErrorCode::NoError) { - return ""; + return nullptr; } config.replace("$OPENVPN_CA_CERT", connData.caCert); @@ -98,12 +139,11 @@ QString OpenVpnConfigurator::createConfig(const ServerCredentials &credentials, config.replace("block-outside-dns", ""); #endif - QJsonObject jConfig; - jConfig[config_key::config] = config; + openVpnConfig->clientProtocolConfig.isEmpty = false; + openVpnConfig->clientProtocolConfig.clientId = connData.clientId; + openVpnConfig->clientProtocolConfig.nativeConfig = config; - jConfig[config_key::clientId] = connData.clientId; - - return QJsonDocument(jConfig).toJson(); + return openVpnConfig; } QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, @@ -199,7 +239,7 @@ ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, const ServerC .arg(clientId); QStringList scriptList { script_import, script_sign }; - QString script = m_serverController->replaceVars(scriptList.join("\n"), m_serverController->genVarsForScript(credentials, container)); + QString script = m_serverController->replaceVars(scriptList.join("\n"), generateProtocolVars(credentials, container)); return m_serverController->runScript(credentials, script); } diff --git a/client/configurators/openvpn_configurator.h b/client/configurators/openvpn_configurator.h index 48e3f4be7..4108ec8ce 100644 --- a/client/configurators/openvpn_configurator.h +++ b/client/configurators/openvpn_configurator.h @@ -6,6 +6,7 @@ #include "configurator_base.h" #include "core/defs.h" +#include "core/models/protocols/openvpnProtocolConfig.h" class OpenVpnConfigurator : public ConfiguratorBase { @@ -24,14 +25,17 @@ public: QString host; // host ip }; - QString createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode); + QSharedPointer createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) override; QString processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, QString &protocolConfigString); QString processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, QString &protocolConfigString); + Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const override; + static ConnectionData createCertRequest(); private: diff --git a/client/configurators/shadowsocks_configurator.cpp b/client/configurators/shadowsocks_configurator.cpp index d388e495f..259c982e3 100644 --- a/client/configurators/shadowsocks_configurator.cpp +++ b/client/configurators/shadowsocks_configurator.cpp @@ -6,6 +6,8 @@ #include "core/models/containers/containers_defs.h" #include "core/controllers/selfhosted/serverController.h" +#include "core/models/protocols/shadowsocksProtocolConfig.h" +#include "protocols/protocols_defs.h" ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent) @@ -13,28 +15,59 @@ ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr setti { } -QString ShadowSocksConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode) +ConfiguratorBase::Vars ShadowSocksConfigurator::generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const { + Vars vars = generateCommonVars(credentials, container); + + auto shadowsocksConfig = qSharedPointerCast(protocolConfig); + if (!shadowsocksConfig) { + return vars; + } + + vars.append({{"$SHADOWSOCKS_SERVER_PORT", shadowsocksConfig->serverProtocolConfig.port}}); + vars.append({{"$SHADOWSOCKS_LOCAL_PORT", protocols::shadowsocks::defaultLocalProxyPort}}); + vars.append({{"$SHADOWSOCKS_CIPHER", shadowsocksConfig->serverProtocolConfig.cipher}}); + + return vars; +} + +QSharedPointer ShadowSocksConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) +{ + auto shadowsocksConfig = qSharedPointerCast(protocolConfig); + if (!shadowsocksConfig) { + errorCode = ErrorCode::InternalError; + return nullptr; + } + QString ssKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::shadowsocks::ssKeyPath, errorCode); ssKey.replace("\n", ""); if (errorCode != ErrorCode::NoError) { - return ""; + return nullptr; } + shadowsocksConfig->clientProtocolConfig.server = credentials.hostName; + shadowsocksConfig->clientProtocolConfig.serverPort = shadowsocksConfig->serverProtocolConfig.port; + shadowsocksConfig->clientProtocolConfig.localPort = protocols::shadowsocks::defaultLocalProxyPort; + shadowsocksConfig->clientProtocolConfig.password = ssKey; + shadowsocksConfig->clientProtocolConfig.timeout = 60; + shadowsocksConfig->clientProtocolConfig.method = shadowsocksConfig->serverProtocolConfig.cipher; + QJsonObject config; - config.insert("server", credentials.hostName); - config.insert("server_port", "$SHADOWSOCKS_SERVER_PORT"); - config.insert("local_port", "$SHADOWSOCKS_LOCAL_PORT"); - config.insert("password", ssKey); - config.insert("timeout", 60); - config.insert("method", "$SHADOWSOCKS_CIPHER"); + config.insert("server", shadowsocksConfig->clientProtocolConfig.server); + config.insert("server_port", shadowsocksConfig->clientProtocolConfig.serverPort); + config.insert("local_port", shadowsocksConfig->clientProtocolConfig.localPort); + config.insert("password", shadowsocksConfig->clientProtocolConfig.password); + config.insert("timeout", shadowsocksConfig->clientProtocolConfig.timeout); + config.insert("method", shadowsocksConfig->clientProtocolConfig.method); - QString textCfg = m_serverController->replaceVars(QJsonDocument(config).toJson(), - m_serverController->genVarsForScript(credentials, container, containerConfig)); + QString textCfg = QJsonDocument(config).toJson(); - // qDebug().noquote() << textCfg; - return textCfg; + shadowsocksConfig->clientProtocolConfig.isEmpty = false; + shadowsocksConfig->clientProtocolConfig.nativeConfig = textCfg; + + return shadowsocksConfig; } diff --git a/client/configurators/shadowsocks_configurator.h b/client/configurators/shadowsocks_configurator.h index b21b3be31..7d8176b96 100644 --- a/client/configurators/shadowsocks_configurator.h +++ b/client/configurators/shadowsocks_configurator.h @@ -4,6 +4,7 @@ #include #include "configurator_base.h" +#include "core/models/protocols/shadowsocksProtocolConfig.h" #include "core/defs.h" class ShadowSocksConfigurator : public ConfiguratorBase @@ -12,8 +13,11 @@ class ShadowSocksConfigurator : public ConfiguratorBase public: ShadowSocksConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent = nullptr); - QString createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode); + QSharedPointer createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) override; + + Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const override; }; #endif // SHADOWSOCKS_CONFIGURATOR_H diff --git a/client/configurators/wireguard_configurator.cpp b/client/configurators/wireguard_configurator.cpp index 2408f6480..ce2e3ad2c 100644 --- a/client/configurators/wireguard_configurator.cpp +++ b/client/configurators/wireguard_configurator.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -17,6 +19,9 @@ #include "core/controllers/selfhosted/serverController.h" #include "core/scripts_registry.h" #include "core/server_defs.h" +#include "core/models/protocols/wireguardProtocolConfig.h" +#include "core/models/protocols/awgProtocolConfig.h" +#include "protocols/protocols_defs.h" #include "settings.h" #include "utilities.h" @@ -37,6 +42,47 @@ WireguardConfigurator::WireguardConfigurator(std::shared_ptr settings, m_defaultPort = m_isAwg ? protocols::wireguard::defaultPort : protocols::awg::defaultPort; } +ConfiguratorBase::Vars WireguardConfigurator::generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const +{ + Vars vars = generateCommonVars(credentials, container); + + if (m_isAwg) { + auto awgConfig = qSharedPointerCast(protocolConfig); + if (!awgConfig) { + return vars; + } + + vars.append({{"$AWG_SUBNET_IP", awgConfig->serverProtocolConfig.subnetAddress}}); + vars.append({{"$AWG_SERVER_PORT", awgConfig->serverProtocolConfig.port}}); + + const auto &awgData = awgConfig->serverProtocolConfig.awgData; + vars.append({{"$JUNK_PACKET_COUNT", awgData.junkPacketCount}}); + vars.append({{"$JUNK_PACKET_MIN_SIZE", awgData.junkPacketMinSize}}); + vars.append({{"$JUNK_PACKET_MAX_SIZE", awgData.junkPacketMaxSize}}); + vars.append({{"$INIT_PACKET_JUNK_SIZE", awgData.initPacketJunkSize}}); + vars.append({{"$RESPONSE_PACKET_JUNK_SIZE", awgData.responsePacketJunkSize}}); + vars.append({{"$INIT_PACKET_MAGIC_HEADER", awgData.initPacketMagicHeader}}); + vars.append({{"$RESPONSE_PACKET_MAGIC_HEADER", awgData.responsePacketMagicHeader}}); + vars.append({{"$UNDERLOAD_PACKET_MAGIC_HEADER", awgData.underloadPacketMagicHeader}}); + vars.append({{"$TRANSPORT_PACKET_MAGIC_HEADER", awgData.transportPacketMagicHeader}}); + vars.append({{"$COOKIE_REPLY_PACKET_JUNK_SIZE", awgData.cookieReplyPacketJunkSize}}); + vars.append({{"$TRANSPORT_PACKET_JUNK_SIZE", awgData.transportPacketJunkSize}}); + } else { + auto wgConfig = qSharedPointerCast(protocolConfig); + if (!wgConfig) { + return vars; + } + + vars.append({{"$WIREGUARD_SUBNET_IP", wgConfig->serverProtocolConfig.subnetAddress}}); + vars.append({{"$WIREGUARD_SUBNET_CIDR", protocols::wireguard::defaultSubnetCidr}}); + vars.append({{"$WIREGUARD_SUBNET_MASK", protocols::wireguard::defaultSubnetMask}}); + vars.append({{"$WIREGUARD_SERVER_PORT", wgConfig->serverProtocolConfig.port}}); + } + + return vars; +} + WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys() { // TODO review @@ -91,12 +137,20 @@ QList WireguardConfigurator::getIpsFromConf(const QString &input) WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) { WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys(); connData.host = credentials.hostName; - connData.port = containerConfig.value(m_protocolName).toObject().value(config_key::port).toString(m_defaultPort); + + // Extract port from appropriate protocol config + if (m_isAwg) { + auto awgConfig = qSharedPointerCast(protocolConfig); + connData.port = awgConfig ? awgConfig->serverProtocolConfig.port : m_defaultPort; + } else { + auto wgConfig = qSharedPointerCast(protocolConfig); + connData.port = wgConfig ? wgConfig->serverProtocolConfig.port : m_defaultPort; + } if (connData.clientPrivKey.isEmpty() || connData.clientPubKey.isEmpty()) { errorCode = ErrorCode::InternalError; @@ -120,10 +174,16 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon QHostAddress result; QHostAddress lastIp; if (ips.empty()) { - lastIp.setAddress(containerConfig.value(m_protocolName) - .toObject() - .value(config_key::subnet_address) - .toString(protocols::wireguard::defaultSubnetAddress)); + // Get subnet from protocol config + QString subnetAddress; + if (m_isAwg) { + auto awgConfig = qSharedPointerCast(protocolConfig); + subnetAddress = awgConfig ? awgConfig->serverProtocolConfig.subnetAddress : protocols::wireguard::defaultSubnetAddress; + } else { + auto wgConfig = qSharedPointerCast(protocolConfig); + subnetAddress = wgConfig ? wgConfig->serverProtocolConfig.subnetAddress : protocols::wireguard::defaultSubnetAddress; + } + lastIp.setAddress(subnetAddress); } else { lastIp = ips.last(); } @@ -173,21 +233,39 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon errorCode = m_serverController->runScript( credentials, - m_serverController->replaceVars(script, m_serverController->genVarsForScript(credentials, container))); + m_serverController->replaceVars(script, generateProtocolVars(credentials, container))); return connData; } -QString WireguardConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode) +QSharedPointer WireguardConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) { + QSharedPointer result; + + if (m_isAwg) { + auto awgConfig = qSharedPointerCast(protocolConfig); + if (!awgConfig) { + errorCode = ErrorCode::InternalError; + return nullptr; + } + result = awgConfig; + } else { + auto wgConfig = qSharedPointerCast(protocolConfig); + if (!wgConfig) { + errorCode = ErrorCode::InternalError; + return nullptr; + } + result = wgConfig; + } + QString scriptData = amnezia::scriptData(m_configTemplate, container); QString config = m_serverController->replaceVars( - scriptData, m_serverController->genVarsForScript(credentials, container, containerConfig)); + scriptData, generateProtocolVars(credentials, container, protocolConfig)); - ConnectionData connData = prepareWireguardConfig(credentials, container, containerConfig, errorCode); + ConnectionData connData = prepareWireguardConfig(credentials, container, protocolConfig, errorCode); if (errorCode != ErrorCode::NoError) { - return ""; + return nullptr; } config.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", connData.clientPrivKey); @@ -195,26 +273,27 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials config.replace("$WIREGUARD_SERVER_PUBLIC_KEY", connData.serverPubKey); config.replace("$WIREGUARD_PSK", connData.pskKey); - const QJsonObject &wireguarConfig = containerConfig.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject(); - QJsonObject jConfig; - jConfig[config_key::config] = config; + ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(result); + std::visit([&connData, &config](const auto &protocolConfig) -> void { + using ConfigType = std::decay_t; + if constexpr (std::is_same_v || std::is_same_v) { + protocolConfig->clientProtocolConfig.isEmpty = false; + protocolConfig->clientProtocolConfig.clientId = connData.clientPubKey; + protocolConfig->clientProtocolConfig.hostname = connData.host; + protocolConfig->clientProtocolConfig.port = connData.port.toInt(); + protocolConfig->clientProtocolConfig.wireGuardData.clientPrivateKey = connData.clientPrivKey; + protocolConfig->clientProtocolConfig.wireGuardData.clientIp = connData.clientIP; + protocolConfig->clientProtocolConfig.wireGuardData.clientPublicKey = connData.clientPubKey; + protocolConfig->clientProtocolConfig.wireGuardData.pskKey = connData.pskKey; + protocolConfig->clientProtocolConfig.wireGuardData.serverPubKey = connData.serverPubKey; + protocolConfig->clientProtocolConfig.wireGuardData.mtu = protocolConfig->serverProtocolConfig.mtu; + protocolConfig->clientProtocolConfig.wireGuardData.persistentKeepAlive = "25"; + protocolConfig->clientProtocolConfig.wireGuardData.allowedIps = QStringList{"0.0.0.0/0", "::/0"}; + protocolConfig->clientProtocolConfig.nativeConfig = config; + } + }, variant); - jConfig[config_key::hostName] = connData.host; - jConfig[config_key::port] = connData.port.toInt(); - jConfig[config_key::client_priv_key] = connData.clientPrivKey; - jConfig[config_key::client_ip] = connData.clientIP; - jConfig[config_key::client_pub_key] = connData.clientPubKey; - jConfig[config_key::psk_key] = connData.pskKey; - jConfig[config_key::server_pub_key] = connData.serverPubKey; - jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu); - - jConfig[config_key::persistent_keep_alive] = "25"; - QJsonArray allowedIps { "0.0.0.0/0", "::/0" }; - jConfig[config_key::allowed_ips] = allowedIps; - - jConfig[config_key::clientId] = connData.clientPubKey; - - return QJsonDocument(jConfig).toJson(); + return result; } QString WireguardConfigurator::processConfigWithLocalSettings(const QPair &dns, diff --git a/client/configurators/wireguard_configurator.h b/client/configurators/wireguard_configurator.h index a4302e3ed..2021157ba 100644 --- a/client/configurators/wireguard_configurator.h +++ b/client/configurators/wireguard_configurator.h @@ -6,6 +6,8 @@ #include #include "configurator_base.h" +#include "core/models/protocols/wireguardProtocolConfig.h" +#include "core/models/protocols/awgProtocolConfig.h" #include "core/defs.h" #include "core/scripts_registry.h" @@ -27,20 +29,23 @@ public: QString port; }; - QString createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode); + QSharedPointer createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) override; QString processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, QString &protocolConfigString); QString processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, QString &protocolConfigString); + Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const override; + static ConnectionData genClientKeys(); private: QList getIpsFromConf(const QString &input); ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode); + const QSharedPointer &protocolConfig, ErrorCode &errorCode); bool m_isAwg; QString m_serverConfigPath; diff --git a/client/configurators/xray_configurator.cpp b/client/configurators/xray_configurator.cpp index 6a7cb5be1..cebb6c08a 100644 --- a/client/configurators/xray_configurator.cpp +++ b/client/configurators/xray_configurator.cpp @@ -9,6 +9,8 @@ #include "core/models/containers/containers_defs.h" #include "core/controllers/selfhosted/serverController.h" #include "core/scripts_registry.h" +#include "core/models/protocols/xrayProtocolConfig.h" +#include "protocols/protocols_defs.h" namespace { Logger logger("XrayConfigurator"); @@ -19,8 +21,24 @@ XrayConfigurator::XrayConfigurator(std::shared_ptr settings, const QSh { } +ConfiguratorBase::Vars XrayConfigurator::generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const +{ + Vars vars = generateCommonVars(credentials, container); + + auto xrayConfig = qSharedPointerCast(protocolConfig); + if (!xrayConfig) { + return vars; + } + + vars.append({{"$XRAY_SITE_NAME", xrayConfig->serverProtocolConfig.site}}); + vars.append({{"$XRAY_SERVER_PORT", xrayConfig->serverProtocolConfig.port}}); + + return vars; +} + QString XrayConfigurator::prepareServerConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode) + const QSharedPointer &protocolConfig, ErrorCode &errorCode) { // Generate new UUID for client QString clientId = QUuid::createUuid().toString(QUuid::WithoutBraces); @@ -44,7 +62,6 @@ QString XrayConfigurator::prepareServerConfig(const ServerCredentials &credentia QJsonObject serverConfig = doc.object(); - // Validate server config structure if (!serverConfig.contains("inbounds")) { logger.error() << "Server config missing 'inbounds' field"; errorCode = ErrorCode::InternalError; @@ -106,7 +123,7 @@ QString XrayConfigurator::prepareServerConfig(const ServerCredentials &credentia QString restartScript = QString("sudo docker restart $CONTAINER_NAME"); errorCode = m_serverController->runScript( credentials, - m_serverController->replaceVars(restartScript, m_serverController->genVarsForScript(credentials, container)) + m_serverController->replaceVars(restartScript, generateProtocolVars(credentials, container)) ); if (errorCode != ErrorCode::NoError) { @@ -117,24 +134,30 @@ QString XrayConfigurator::prepareServerConfig(const ServerCredentials &credentia return clientId; } -QString XrayConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode) +QSharedPointer XrayConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) { + auto xrayConfig = qSharedPointerCast(protocolConfig); + if (!xrayConfig) { + errorCode = ErrorCode::InternalError; + return nullptr; + } + // Get client ID from prepareServerConfig - QString xrayClientId = prepareServerConfig(credentials, container, containerConfig, errorCode); + QString xrayClientId = prepareServerConfig(credentials, container, protocolConfig, errorCode); if (errorCode != ErrorCode::NoError || xrayClientId.isEmpty()) { logger.error() << "Failed to prepare server config"; errorCode = ErrorCode::InternalError; - return ""; + return nullptr; } QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::xray_template, container), - m_serverController->genVarsForScript(credentials, container, containerConfig)); + generateProtocolVars(credentials, container, protocolConfig)); if (config.isEmpty()) { logger.error() << "Failed to get config template"; errorCode = ErrorCode::InternalError; - return ""; + return nullptr; } QString xrayPublicKey = @@ -142,7 +165,7 @@ QString XrayConfigurator::createConfig(const ServerCredentials &credentials, Doc if (errorCode != ErrorCode::NoError || xrayPublicKey.isEmpty()) { logger.error() << "Failed to get public key"; errorCode = ErrorCode::InternalError; - return ""; + return nullptr; } xrayPublicKey.replace("\n", ""); @@ -151,7 +174,7 @@ QString XrayConfigurator::createConfig(const ServerCredentials &credentials, Doc if (errorCode != ErrorCode::NoError || xrayShortId.isEmpty()) { logger.error() << "Failed to get short ID"; errorCode = ErrorCode::InternalError; - return ""; + return nullptr; } xrayShortId.replace("\n", ""); @@ -162,12 +185,16 @@ QString XrayConfigurator::createConfig(const ServerCredentials &credentials, Doc << "XRAY_PUBLIC_KEY:" << !config.contains("$XRAY_PUBLIC_KEY") << "XRAY_SHORT_ID:" << !config.contains("$XRAY_SHORT_ID"); errorCode = ErrorCode::InternalError; - return ""; + return nullptr; } config.replace("$XRAY_CLIENT_ID", xrayClientId); config.replace("$XRAY_PUBLIC_KEY", xrayPublicKey); config.replace("$XRAY_SHORT_ID", xrayShortId); - return config; + xrayConfig->clientProtocolConfig.isEmpty = false; + xrayConfig->clientProtocolConfig.clientId = xrayClientId; + xrayConfig->clientProtocolConfig.nativeConfig = config; + + return xrayConfig; } diff --git a/client/configurators/xray_configurator.h b/client/configurators/xray_configurator.h index 8ed4e7752..b350f0818 100644 --- a/client/configurators/xray_configurator.h +++ b/client/configurators/xray_configurator.h @@ -4,6 +4,7 @@ #include #include "configurator_base.h" +#include "core/models/protocols/xrayProtocolConfig.h" #include "core/defs.h" class XrayConfigurator : public ConfiguratorBase @@ -12,12 +13,15 @@ class XrayConfigurator : public ConfiguratorBase public: XrayConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, QObject *parent = nullptr); - QString createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, - ErrorCode &errorCode); + QSharedPointer createConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode) override; + + Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig) const override; private: - QString prepareServerConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, - ErrorCode &errorCode); + QString prepareServerConfig(const ServerCredentials &credentials, DockerContainer container, + const QSharedPointer &protocolConfig, ErrorCode &errorCode); }; #endif // XRAY_CONFIGURATOR_H diff --git a/client/core/controllers/selfhosted/clientManagementController.cpp b/client/core/controllers/selfhosted/clientManagementController.cpp index 5b9a468f7..bb2b5ac7e 100644 --- a/client/core/controllers/selfhosted/clientManagementController.cpp +++ b/client/core/controllers/selfhosted/clientManagementController.cpp @@ -440,7 +440,7 @@ ErrorCode ClientManagementController::wgShow(const DockerContainer container, co const QString command = QString("sudo docker exec -i $CONTAINER_NAME bash -c '%1'").arg("wg show all"); - QString script = serverController->replaceVars(command, serverController->genVarsForScript(credentials, container)); + QString script = serverController->replaceVars(command, serverController->generateVarsForContainer(credentials, container)); error = serverController->runScript(credentials, script, cbReadStdOut); if (error != ErrorCode::NoError) { logger.error() << "Failed to execute wg show command"; @@ -668,7 +668,7 @@ ErrorCode ClientManagementController::revokeOpenVpn(const int row, const DockerC const QString revokeClientScript = "sudo docker exec -i $CONTAINER_NAME bash -c './easyrsa --batch revoke %1'"; QString script = serverController->replaceVars(revokeClientScript.arg(clientId), - serverController->genVarsForScript(credentials, container)); + serverController->generateVarsForContainer(credentials, container)); error = serverController->runScript(credentials, script, cbReadStdOut); if (error != ErrorCode::NoError) { return error; diff --git a/client/core/controllers/selfhosted/installationController.cpp b/client/core/controllers/selfhosted/installationController.cpp deleted file mode 100644 index 6fe155721..000000000 --- a/client/core/controllers/selfhosted/installationController.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "installationController.h" - -#include - -#include "core/controllers/vpnConfigurationController.h" -#include "core/networkUtilities.h" -#include "settings.h" -#include "logger.h" - -namespace -{ - Logger logger("InstallationController"); -} - -InstallationController::InstallationController(std::shared_ptr settings, QObject *parent) - : QObject(parent), m_settings(settings) -{ -} - -QFuture InstallationController::installContainer(const QSharedPointer &serverConfig, - DockerContainer container, - const QJsonObject &containerConfig) -{ - return QtConcurrent::run([this, serverConfig, container, containerConfig]() -> ErrorCode { - // TODO: Implement container installation logic - // This will be moved from UI InstallController - logger.info() << "Installing container" << ContainerProps::containerToString(container); - return ErrorCode::NoError; - }); -} - -QFuture InstallationController::scanServerForInstalledContainers(const QSharedPointer &serverConfig) -{ - return QtConcurrent::run([this, serverConfig]() -> ErrorCode { - // TODO: Implement server scanning logic - // This will be moved from UI InstallController - logger.info() << "Scanning server for installed containers"; - return ErrorCode::NoError; - }); -} - -QFuture InstallationController::removeContainer(const QSharedPointer &serverConfig, - DockerContainer container) -{ - return QtConcurrent::run([this, serverConfig, container]() -> ErrorCode { - // TODO: Implement container removal logic - logger.info() << "Removing container" << ContainerProps::containerToString(container); - return ErrorCode::NoError; - }); -} - -QFuture InstallationController::updateContainer(const QSharedPointer &serverConfig, - DockerContainer container, - const QJsonObject &containerConfig) -{ - return QtConcurrent::run([this, serverConfig, container, containerConfig]() -> ErrorCode { - // TODO: Implement container update logic - logger.info() << "Updating container" << ContainerProps::containerToString(container); - return ErrorCode::NoError; - }); -} - -QFuture InstallationController::rebootServer(const QSharedPointer &serverConfig) -{ - return QtConcurrent::run([this, serverConfig]() -> ErrorCode { - // TODO: Implement server reboot logic - logger.info() << "Rebooting server"; - return ErrorCode::NoError; - }); -} - -QFuture InstallationController::removeAllContainers(const QSharedPointer &serverConfig) -{ - return QtConcurrent::run([this, serverConfig]() -> ErrorCode { - // TODO: Implement all containers removal logic - logger.info() << "Removing all containers"; - return ErrorCode::NoError; - }); -} - -QFuture InstallationController::checkSshConnection(const QSharedPointer &serverConfig) -{ - return QtConcurrent::run([this, serverConfig]() -> bool { - // TODO: Implement SSH connection check logic - logger.info() << "Checking SSH connection"; - return true; - }); -} - -QFuture InstallationController::mountSftpDrive(const QSharedPointer &serverConfig, - const QString &port, - const QString &password, - const QString &username) -{ - return QtConcurrent::run([this, serverConfig, port, password, username]() -> ErrorCode { - // TODO: Implement SFTP mounting logic - logger.info() << "Mounting SFTP drive"; - return ErrorCode::NoError; - }); -} - -ErrorCode InstallationController::getAlreadyInstalledContainers(const ServerCredentials &serverCredentials, - const QSharedPointer &serverController, - QMap &installedContainers) -{ - // TODO: Implement logic to get already installed containers - // This will be moved from UI InstallController - return ErrorCode::NoError; -} diff --git a/client/core/controllers/selfhosted/installationController.h b/client/core/controllers/selfhosted/installationController.h deleted file mode 100644 index d4c072ad9..000000000 --- a/client/core/controllers/selfhosted/installationController.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef INSTALLATIONCONTROLLER_H -#define INSTALLATIONCONTROLLER_H - -#include -#include -#include - -#include "core/defs.h" -#include "core/models/containers/containers_defs.h" -#include "core/models/servers/serverConfig.h" -#include "serverController.h" - -class Settings; - -using namespace amnezia; - -class InstallationController : public QObject -{ - Q_OBJECT - -public: - explicit InstallationController(std::shared_ptr settings, QObject *parent = nullptr); - - QFuture installContainer(const QSharedPointer &serverConfig, - DockerContainer container, - const QJsonObject &containerConfig); - - QFuture scanServerForInstalledContainers(const QSharedPointer &serverConfig); - - QFuture removeContainer(const QSharedPointer &serverConfig, - DockerContainer container); - - QFuture updateContainer(const QSharedPointer &serverConfig, - DockerContainer container, - const QJsonObject &containerConfig); - - QFuture rebootServer(const QSharedPointer &serverConfig); - - QFuture removeAllContainers(const QSharedPointer &serverConfig); - - QFuture checkSshConnection(const QSharedPointer &serverConfig); - - QFuture mountSftpDrive(const QSharedPointer &serverConfig, - const QString &port, - const QString &password, - const QString &username); - -signals: - void installationFinished(const QString &finishMessage, bool isServiceInstall); - void installationProgress(const QString &message); - void installationError(ErrorCode errorCode); - -private: - ErrorCode getAlreadyInstalledContainers(const ServerCredentials &serverCredentials, - const QSharedPointer &serverController, - QMap &installedContainers); - - std::shared_ptr m_settings; -}; - -#endif // INSTALLATIONCONTROLLER_H diff --git a/client/core/controllers/selfhosted/serverController.cpp b/client/core/controllers/selfhosted/serverController.cpp index 0fd1da7d6..197174e62 100644 --- a/client/core/controllers/selfhosted/serverController.cpp +++ b/client/core/controllers/selfhosted/serverController.cpp @@ -29,7 +29,15 @@ #include "logger.h" #include "settings.h" #include "utilities.h" -#include "vpnConfigurationController.h" +#include "configurators/awg_configurator.h" +#include "configurators/cloak_configurator.h" +#include "configurators/ikev2_configurator.h" +#include "configurators/openvpn_configurator.h" +#include "configurators/shadowsocks_configurator.h" +#include "configurators/wireguard_configurator.h" +#include "configurators/xray_configurator.h" +#include "core/models/protocols/sftpProtocolConfig.h" +#include "core/models/protocols/socks5ProtocolConfig.h" namespace { @@ -106,10 +114,10 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti QString runner = QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash")); - e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); + e = runScript(credentials, replaceVars(runner, generateVarsForContainer(credentials, container)), cbReadStdOut, cbReadStdErr); QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName); - runScript(credentials, replaceVars(remover, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); + runScript(credentials, replaceVars(remover, generateVarsForContainer(credentials, container)), cbReadStdOut, cbReadStdErr); return e; } @@ -132,14 +140,14 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, // mkdir QString mkdir = QString("sudo docker exec -i $CONTAINER_NAME mkdir -p \"$(dirname %1)\"").arg(path); - e = runScript(credentials, replaceVars(mkdir, genVarsForScript(credentials, container))); + e = runScript(credentials, replaceVars(mkdir, generateVarsForContainer(credentials, container))); if (e) return e; if (overwriteMode == libssh::ScpOverwriteMode::ScpOverwriteExisting) { e = runScript(credentials, replaceVars(QStringLiteral("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName, path), - genVarsForScript(credentials, container)), + generateVarsForContainer(credentials, container)), cbReadStd, cbReadStd); if (e) @@ -147,7 +155,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, } else if (overwriteMode == libssh::ScpOverwriteMode::ScpAppendToExisting) { e = runScript(credentials, replaceVars(QStringLiteral("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName, tmpFileName), - genVarsForScript(credentials, container)), + generateVarsForContainer(credentials, container)), cbReadStd, cbReadStd); if (e) @@ -155,7 +163,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, e = runScript(credentials, replaceVars(QStringLiteral("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName, path), - genVarsForScript(credentials, container)), + generateVarsForContainer(credentials, container)), cbReadStd, cbReadStd); if (e) @@ -167,7 +175,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, return ErrorCode::ServerContainerMissingError; } - runScript(credentials, replaceVars(QString("sudo shred -u %1").arg(tmpFileName), genVarsForScript(credentials, container))); + runScript(credentials, replaceVars(QString("sudo shred -u %1").arg(tmpFileName), generateVarsForContainer(credentials, container))); return e; } @@ -236,7 +244,7 @@ ErrorCode ServerController::removeAllContainers(const ServerCredentials &credent ErrorCode ServerController::removeContainer(const ServerCredentials &credentials, DockerContainer container) { return runScript(credentials, - replaceVars(amnezia::scriptData(SharedScriptType::remove_container), genVarsForScript(credentials, container))); + replaceVars(amnezia::scriptData(SharedScriptType::remove_container), generateVarsForContainer(credentials, container))); } ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config, bool isUpdate) @@ -415,7 +423,7 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent }; ErrorCode error = - runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::install_docker), genVarsForScript(credentials)), + runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::install_docker), generateVarsForContainer(credentials, DockerContainer::None)), cbReadStdOut, cbReadStdErr); qDebug().noquote() << "ServerController::installDockerWorker" << stdOut; @@ -430,14 +438,14 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config) { // create folder on host - return runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::prepare_host), genVarsForScript(credentials, container))); + return runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::prepare_host), generateVarsForContainer(credentials, container))); } ErrorCode ServerController::buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config) { QString dockerFilePath = amnezia::server::getDockerfileFolder(container) + "/Dockerfile"; QString scriptString = QString("sudo rm %1").arg(dockerFilePath); - ErrorCode errorCode = runScript(credentials, replaceVars(scriptString, genVarsForScript(credentials, container))); + ErrorCode errorCode = runScript(credentials, replaceVars(scriptString, generateVarsForContainer(credentials, container))); if (errorCode) return errorCode; @@ -458,7 +466,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden ErrorCode error = runScript(credentials, - replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)), + replaceVars(amnezia::scriptData(SharedScriptType::build_container), generateVarsForContainer(credentials, container, config)), cbReadStdOut, cbReadStdErr); if (stdOut.contains("doesn't work on cgroups v2")) @@ -481,7 +489,7 @@ ErrorCode ServerController::runContainerWorker(const ServerCredentials &credenti ErrorCode e = runScript(credentials, replaceVars(amnezia::scriptData(ProtocolScriptType::run_container, container), - genVarsForScript(credentials, container, config)), + generateVarsForContainer(credentials, container, config)), cbReadStdOut); if (stdOut.contains("address already in use")) @@ -508,7 +516,7 @@ ErrorCode ServerController::configureContainerWorker(const ServerCredentials &cr ErrorCode e = runContainerScript(credentials, container, replaceVars(amnezia::scriptData(ProtocolScriptType::configure_container, container), - genVarsForScript(credentials, container, config)), + generateVarsForContainer(credentials, container, config)), cbReadStdOut, cbReadStdErr); VpnConfigurationsController::updateContainerConfigAfterInstallation(container, config, stdOut); @@ -524,7 +532,7 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred return ErrorCode::NoError; } - ErrorCode e = uploadTextFileToContainer(container, credentials, replaceVars(script, genVarsForScript(credentials, container, config)), + ErrorCode e = uploadTextFileToContainer(container, credentials, replaceVars(script, generateVarsForContainer(credentials, container, config)), "/opt/amnezia/start.sh"); if (e) return e; @@ -532,138 +540,99 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred return runScript(credentials, replaceVars("sudo docker exec -d $CONTAINER_NAME sh -c \"chmod a+x /opt/amnezia/start.sh && " "/opt/amnezia/start.sh\"", - genVarsForScript(credentials, container, config))); + generateVarsForContainer(credentials, container, config))); } -ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &config) + + +ServerController::Vars ServerController::generateVarsForContainer(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &config) { - const QJsonObject &openvpnConfig = config.value(ProtocolProps::protoToString(Proto::OpenVpn)).toObject(); - const QJsonObject &cloakConfig = config.value(ProtocolProps::protoToString(Proto::Cloak)).toObject(); - const QJsonObject &ssConfig = config.value(ProtocolProps::protoToString(Proto::ShadowSocks)).toObject(); - const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject(); - const QJsonObject &amneziaWireguarConfig = config.value(ProtocolProps::protoToString(Proto::Awg)).toObject(); - const QJsonObject &xrayConfig = config.value(ProtocolProps::protoToString(Proto::Xray)).toObject(); - const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject(); - const QJsonObject &socks5ProxyConfig = config.value(ProtocolProps::protoToString(Proto::Socks5Proxy)).toObject(); - - Vars vars; - - vars.append({ { "$REMOTE_HOST", credentials.hostName } }); - - // OpenVPN vars - vars.append({ { "$OPENVPN_SUBNET_IP", - openvpnConfig.value(config_key::subnet_address).toString(protocols::openvpn::defaultSubnetAddress) } }); - vars.append({ { "$OPENVPN_SUBNET_CIDR", openvpnConfig.value(config_key::subnet_cidr).toString(protocols::openvpn::defaultSubnetCidr) } }); - vars.append({ { "$OPENVPN_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(protocols::openvpn::defaultSubnetMask) } }); - - vars.append({ { "$OPENVPN_PORT", openvpnConfig.value(config_key::port).toString(protocols::openvpn::defaultPort) } }); - vars.append({ { "$OPENVPN_TRANSPORT_PROTO", - openvpnConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) } }); - - bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable); - vars.append({ { "$OPENVPN_NCP_DISABLE", isNcpDisabled ? protocols::openvpn::ncpDisableString : "" } }); - - vars.append({ { "$OPENVPN_CIPHER", openvpnConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher) } }); - vars.append({ { "$OPENVPN_HASH", openvpnConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash) } }); - - bool isTlsAuth = openvpnConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth); - vars.append({ { "$OPENVPN_TLS_AUTH", isTlsAuth ? protocols::openvpn::tlsAuthString : "" } }); - if (!isTlsAuth) { - // erase $OPENVPN_TA_KEY, so it will not set in OpenVpnConfigurator::genOpenVpnConfig - vars.append({ { "$OPENVPN_TA_KEY", "" } }); + // For VPN containers, use configurator pattern + if (ContainerProps::containerService(container) != ServiceType::Other) { + for (Proto protocol : ContainerProps::protocolsForContainer(container)) { + QScopedPointer configurator; + + // Create the appropriate configurator for this protocol + switch (protocol) { + case Proto::OpenVpn: + configurator.reset(new OpenVpnConfigurator(m_settings, QSharedPointer(this, [](ServerController*){}))); + break; + case Proto::ShadowSocks: + configurator.reset(new ShadowSocksConfigurator(m_settings, QSharedPointer(this, [](ServerController*){}))); + break; + case Proto::Cloak: + configurator.reset(new CloakConfigurator(m_settings, QSharedPointer(this, [](ServerController*){}))); + break; + case Proto::WireGuard: + configurator.reset(new WireguardConfigurator(m_settings, QSharedPointer(this, [](ServerController*){}), false)); + break; + case Proto::Awg: + configurator.reset(new AwgConfigurator(m_settings, QSharedPointer(this, [](ServerController*){}))); + break; + case Proto::Ikev2: + configurator.reset(new Ikev2Configurator(m_settings, QSharedPointer(this, [](ServerController*){}))); + break; + case Proto::Xray: + case Proto::SSXray: + configurator.reset(new XrayConfigurator(m_settings, QSharedPointer(this, [](ServerController*){}))); + break; + default: + continue; + } + + if (configurator) { + return configurator->generateProtocolVars(credentials, container, config); + } + } } - vars.append({ { "$OPENVPN_ADDITIONAL_CLIENT_CONFIG", - openvpnConfig.value(config_key::additional_client_config).toString(protocols::openvpn::defaultAdditionalClientConfig) } }); - vars.append({ { "$OPENVPN_ADDITIONAL_SERVER_CONFIG", - openvpnConfig.value(config_key::additional_server_config).toString(protocols::openvpn::defaultAdditionalServerConfig) } }); - - // ShadowSocks vars - vars.append({ { "$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) } }); - vars.append({ { "$SHADOWSOCKS_LOCAL_PORT", - ssConfig.value(config_key::local_port).toString(protocols::shadowsocks::defaultLocalProxyPort) } }); - vars.append({ { "$SHADOWSOCKS_CIPHER", ssConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher) } }); - - vars.append({ { "$CONTAINER_NAME", ContainerProps::containerToString(container) } }); - vars.append({ { "$DOCKERFILE_FOLDER", "/opt/amnezia/" + ContainerProps::containerToString(container) } }); - - // Cloak vars - vars.append({ { "$CLOAK_SERVER_PORT", cloakConfig.value(config_key::port).toString(protocols::cloak::defaultPort) } }); - vars.append({ { "$FAKE_WEB_SITE_ADDRESS", cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) } }); - - // Xray vars - vars.append({ { "$XRAY_SITE_NAME", xrayConfig.value(config_key::site).toString(protocols::xray::defaultSite) } }); - vars.append({ { "$XRAY_SERVER_PORT", xrayConfig.value(config_key::port).toString(protocols::xray::defaultPort) } }); - - // Wireguard vars - vars.append({ { "$WIREGUARD_SUBNET_IP", - wireguarConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) } }); - vars.append({ { "$WIREGUARD_SUBNET_CIDR", - wireguarConfig.value(config_key::subnet_cidr).toString(protocols::wireguard::defaultSubnetCidr) } }); - vars.append({ { "$WIREGUARD_SUBNET_MASK", - wireguarConfig.value(config_key::subnet_mask).toString(protocols::wireguard::defaultSubnetMask) } }); - - vars.append({ { "$WIREGUARD_SERVER_PORT", wireguarConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) } }); - - // IPsec vars - vars.append({ { "$IPSEC_VPN_L2TP_NET", "192.168.42.0/24" } }); - vars.append({ { "$IPSEC_VPN_L2TP_POOL", "192.168.42.10-192.168.42.250" } }); - vars.append({ { "$IPSEC_VPN_L2TP_LOCAL", "192.168.42.1" } }); - - vars.append({ { "$IPSEC_VPN_XAUTH_NET", "192.168.43.0/24" } }); - vars.append({ { "$IPSEC_VPN_XAUTH_POOL", "192.168.43.10-192.168.43.250" } }); - - vars.append({ { "$IPSEC_VPN_SHA2_TRUNCBUG", "yes" } }); - - vars.append({ { "$IPSEC_VPN_VPN_ANDROID_MTU_FIX", "yes" } }); - vars.append({ { "$IPSEC_VPN_DISABLE_IKEV2", "no" } }); - vars.append({ { "$IPSEC_VPN_DISABLE_L2TP", "no" } }); - vars.append({ { "$IPSEC_VPN_DISABLE_XAUTH", "no" } }); - - vars.append({ { "$IPSEC_VPN_C2C_TRAFFIC", "no" } }); - - vars.append({ { "$PRIMARY_SERVER_DNS", m_settings->primaryDns() } }); - vars.append({ { "$SECONDARY_SERVER_DNS", m_settings->secondaryDns() } }); - - // Sftp vars - vars.append({ { "$SFTP_PORT", sftpConfig.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Proto::Sftp))) } }); - vars.append({ { "$SFTP_USER", sftpConfig.value(config_key::userName).toString() } }); - vars.append({ { "$SFTP_PASSWORD", sftpConfig.value(config_key::password).toString() } }); - - // Amnezia wireguard vars - vars.append({ { "$AWG_SUBNET_IP", - amneziaWireguarConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) } }); - vars.append({ { "$AWG_SERVER_PORT", amneziaWireguarConfig.value(config_key::port).toString(protocols::awg::defaultPort) } }); - - vars.append({ { "$JUNK_PACKET_COUNT", amneziaWireguarConfig.value(config_key::junkPacketCount).toString() } }); - vars.append({ { "$JUNK_PACKET_MIN_SIZE", amneziaWireguarConfig.value(config_key::junkPacketMinSize).toString() } }); - vars.append({ { "$JUNK_PACKET_MAX_SIZE", amneziaWireguarConfig.value(config_key::junkPacketMaxSize).toString() } }); - vars.append({ { "$INIT_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::initPacketJunkSize).toString() } }); - vars.append({ { "$RESPONSE_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::responsePacketJunkSize).toString() } }); - vars.append({ { "$INIT_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::initPacketMagicHeader).toString() } }); - vars.append({ { "$RESPONSE_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::responsePacketMagicHeader).toString() } }); - vars.append({ { "$UNDERLOAD_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::underloadPacketMagicHeader).toString() } }); - vars.append({ { "$TRANSPORT_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::transportPacketMagicHeader).toString() } }); - - vars.append({ { "$COOKIE_REPLY_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::cookieReplyPacketJunkSize).toString() } }); - vars.append({ { "$TRANSPORT_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::transportPacketJunkSize).toString() } }); - - // Socks5 proxy vars - vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } }); - auto username = socks5ProxyConfig.value(config_key::userName).toString(); - auto password = socks5ProxyConfig.value(config_key::password).toString(); - QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : ""; - vars.append({ { "$SOCKS5_USER", socks5user } }); - vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } }); + // Handle non-VPN services (SFTP, Socks5) with direct variable generation + Vars vars; + + // Common variables that apply to all containers + vars.append({{"$REMOTE_HOST", credentials.hostName}}); + vars.append({{"$CONTAINER_NAME", ContainerProps::containerToString(container)}}); + vars.append({{"$DOCKERFILE_FOLDER", "/opt/amnezia/" + ContainerProps::containerToString(container)}}); + vars.append({{"$PRIMARY_SERVER_DNS", m_settings->primaryDns()}}); + vars.append({{"$SECONDARY_SERVER_DNS", m_settings->secondaryDns()}}); QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::WireGuard && container != DockerContainer::Xray) ? NetworkUtilities::getIPAddress(credentials.hostName) : credentials.hostName; if (!serverIp.isEmpty()) { - vars.append({ { "$SERVER_IP_ADDRESS", serverIp } }); - } else { - qWarning() << "ServerController::genVarsForScript unable to resolve address for credentials.hostName"; + vars.append({{"$SERVER_IP_ADDRESS", serverIp}}); + } + + // Handle container-specific variables for non-VPN services + if (container == DockerContainer::Sftp) { + SftpProtocolConfig protocolConfig(config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject(), + ProtocolProps::protoToString(Proto::Sftp)); + + QString port = protocolConfig.serverProtocolConfig.port; + if (port.isEmpty()) { + port = QString::number(ProtocolProps::defaultPort(Proto::Sftp)); + } + + vars.append({{"$SFTP_PORT", port}}); + vars.append({{"$SFTP_USER", protocolConfig.serverProtocolConfig.userName}}); + vars.append({{"$SFTP_PASSWORD", protocolConfig.serverProtocolConfig.password}}); + } else if (container == DockerContainer::Socks5Proxy) { + Socks5ProtocolConfig protocolConfig(config.value(ProtocolProps::protoToString(Proto::Socks5Proxy)).toObject(), + ProtocolProps::protoToString(Proto::Socks5Proxy)); + + QString port = protocolConfig.serverProtocolConfig.port; + if (port.isEmpty()) { + port = protocols::socks5Proxy::defaultPort; + } + + vars.append({{"$SOCKS5_PROXY_PORT", port}}); + + const QString &username = protocolConfig.serverProtocolConfig.userName; + const QString &password = protocolConfig.serverProtocolConfig.password; + QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : ""; + vars.append({{"$SOCKS5_USER", socks5user}}); + vars.append({{"$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong"}}); } return vars; @@ -693,7 +662,7 @@ void ServerController::cancelInstallation() ErrorCode ServerController::setupServerFirewall(const ServerCredentials &credentials) { - return runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::setup_host_firewall), genVarsForScript(credentials))); + return runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::setup_host_firewall), generateVarsForContainer(credentials, DockerContainer::None))); } QString ServerController::replaceVars(const QString &script, const Vars &vars) @@ -746,12 +715,12 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential tcpProtoScript.append(" | grep LISTEN"); ErrorCode errorCode = - runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); + runScript(credentials, replaceVars(tcpProtoScript, generateVarsForContainer(credentials, container)), cbReadStdOut, cbReadStdErr); if (errorCode != ErrorCode::NoError) { return errorCode; } - errorCode = runScript(credentials, replaceVars(udpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); + errorCode = runScript(credentials, replaceVars(udpProtoScript, generateVarsForContainer(credentials, container)), cbReadStdOut, cbReadStdErr); if (errorCode != ErrorCode::NoError) { return errorCode; } @@ -768,7 +737,7 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential script = script.append(" | grep LISTEN"); } - ErrorCode errorCode = runScript(credentials, replaceVars(script, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); + ErrorCode errorCode = runScript(credentials, replaceVars(script, generateVarsForContainer(credentials, container)), cbReadStdOut, cbReadStdErr); if (errorCode != ErrorCode::NoError) { return errorCode; } @@ -792,7 +761,7 @@ ErrorCode ServerController::isUserInSudo(const ServerCredentials &credentials, D }; const QString scriptData = amnezia::scriptData(SharedScriptType::check_user_in_sudo); - ErrorCode error = runScript(credentials, replaceVars(scriptData, genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); + ErrorCode error = runScript(credentials, replaceVars(scriptData, generateVarsForContainer(credentials, DockerContainer::None)), cbReadStdOut, cbReadStdErr); if (credentials.userName != "root" && stdOut.contains("sudo:") && !stdOut.contains("uname:") && stdOut.contains("not found")) return ErrorCode::ServerSudoPackageIsNotPreinstalled; @@ -830,7 +799,7 @@ ErrorCode ServerController::isServerDpkgBusy(const ServerCredentials &credential return ErrorCode::ServerCancelInstallation; } stdOut.clear(); - runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), genVarsForScript(credentials)), + runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), generateVarsForContainer(credentials, DockerContainer::None)), cbReadStdOut, cbReadStdErr); if (stdOut.contains("Packet manager not found")) diff --git a/client/core/controllers/selfhosted/serverController.h b/client/core/controllers/selfhosted/serverController.h index b5df24886..c6e37c3e2 100644 --- a/client/core/controllers/selfhosted/serverController.h +++ b/client/core/controllers/selfhosted/serverController.h @@ -39,8 +39,8 @@ public: ErrorCode &errorCode); QString replaceVars(const QString &script, const Vars &vars); - Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, - const QJsonObject &config = QJsonObject()); + Vars generateVarsForContainer(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &config = QJsonObject()); ErrorCode runScript(const ServerCredentials &credentials, QString script, const std::function &cbReadStdOut = nullptr, diff --git a/client/core/controllers/vpnConfigurationController.cpp b/client/core/controllers/vpnConfigurationController.cpp index 612879728..1b2c4f60a 100644 --- a/client/core/controllers/vpnConfigurationController.cpp +++ b/client/core/controllers/vpnConfigurationController.cpp @@ -7,6 +7,13 @@ #include "configurators/shadowsocks_configurator.h" #include "configurators/wireguard_configurator.h" #include "configurators/xray_configurator.h" +#include "core/models/protocols/awgProtocolConfig.h" +#include "core/models/protocols/cloakProtocolConfig.h" +#include "core/models/protocols/ikev2ProtocolConfig.h" +#include "core/models/protocols/openvpnProtocolConfig.h" +#include "core/models/protocols/shadowsocksProtocolConfig.h" +#include "core/models/protocols/wireguardProtocolConfig.h" +#include "core/models/protocols/xrayProtocolConfig.h" VpnConfigurationsController::VpnConfigurationsController(const std::shared_ptr &settings, QSharedPointer serverController, QObject *parent) @@ -29,6 +36,29 @@ QScopedPointer VpnConfigurationsController::createConfigurator } } +QSharedPointer VpnConfigurationsController::createProtocolConfig(const Proto protocol, const QJsonObject &protocolConfigJson) +{ + switch (protocol) { + case Proto::OpenVpn: + return QSharedPointer::create(protocolConfigJson, ProtocolProps::protoToString(protocol)); + case Proto::ShadowSocks: + return QSharedPointer::create(protocolConfigJson, ProtocolProps::protoToString(protocol)); + case Proto::Cloak: + return QSharedPointer::create(protocolConfigJson, ProtocolProps::protoToString(protocol)); + case Proto::WireGuard: + return QSharedPointer::create(protocolConfigJson, ProtocolProps::protoToString(protocol)); + case Proto::Awg: + return QSharedPointer::create(protocolConfigJson, ProtocolProps::protoToString(protocol)); + case Proto::Xray: + case Proto::SSXray: + return QSharedPointer::create(protocolConfigJson, ProtocolProps::protoToString(protocol)); + case Proto::Ikev2: + return QSharedPointer::create(ProtocolProps::protoToString(protocol)); + default: + return nullptr; + } +} + ErrorCode VpnConfigurationsController::createProtocolConfigForContainer(const ServerCredentials &credentials, const DockerContainer container, QJsonObject &containerConfig) { @@ -39,16 +69,41 @@ ErrorCode VpnConfigurationsController::createProtocolConfigForContainer(const Se } for (Proto protocol : ContainerProps::protocolsForContainer(container)) { - QJsonObject protocolConfig = containerConfig.value(ProtocolProps::protoToString(protocol)).toObject(); + QJsonObject protocolConfigJson = containerConfig.value(ProtocolProps::protoToString(protocol)).toObject(); - auto configurator = createConfigurator(protocol); - QString protocolConfigString = configurator->createConfig(credentials, container, containerConfig, errorCode); - if (errorCode != ErrorCode::NoError) { + // Create ProtocolConfig from JSON + auto protocolConfig = createProtocolConfig(protocol, protocolConfigJson); + if (!protocolConfig) { + errorCode = ErrorCode::InternalError; return errorCode; } - protocolConfig.insert(config_key::last_config, protocolConfigString); - containerConfig.insert(ProtocolProps::protoToString(protocol), protocolConfig); + auto configurator = createConfigurator(protocol); + auto result = configurator->createConfig(credentials, container, protocolConfig, errorCode); + if (errorCode != ErrorCode::NoError || !result) { + return errorCode; + } + + // Extract nativeConfig and store back in JSON for backward compatibility + QString nativeConfig; + if (auto openVpnConfig = qSharedPointerCast(result)) { + nativeConfig = openVpnConfig->clientProtocolConfig.nativeConfig; + } else if (auto wgConfig = qSharedPointerCast(result)) { + nativeConfig = wgConfig->clientProtocolConfig.nativeConfig; + } else if (auto awgConfig = qSharedPointerCast(result)) { + nativeConfig = awgConfig->clientProtocolConfig.nativeConfig; + } else if (auto cloakConfig = qSharedPointerCast(result)) { + nativeConfig = cloakConfig->clientProtocolConfig.nativeConfig; + } else if (auto xrayConfig = qSharedPointerCast(result)) { + nativeConfig = xrayConfig->clientProtocolConfig.nativeConfig; + } else if (auto shadowsocksConfig = qSharedPointerCast(result)) { + nativeConfig = shadowsocksConfig->clientProtocolConfig.nativeConfig; + } else if (auto ikev2Config = qSharedPointerCast(result)) { + nativeConfig = ikev2Config->clientProtocolConfig.nativeConfig; + } + + protocolConfigJson.insert(config_key::last_config, nativeConfig); + containerConfig.insert(ProtocolProps::protoToString(protocol), protocolConfigJson); } return errorCode; @@ -65,13 +120,39 @@ ErrorCode VpnConfigurationsController::createProtocolConfigString(const bool isA return errorCode; } - auto configurator = createConfigurator(protocol); - - protocolConfigString = configurator->createConfig(credentials, container, containerConfig, errorCode); - if (errorCode != ErrorCode::NoError) { + // Create ProtocolConfig from JSON + QJsonObject protocolConfigJson = containerConfig.value(ProtocolProps::protoToString(protocol)).toObject(); + auto protocolConfig = createProtocolConfig(protocol, protocolConfigJson); + if (!protocolConfig) { + errorCode = ErrorCode::InternalError; return errorCode; } - protocolConfigString = configurator->processConfigWithExportSettings(dns, isApiConfig, protocolConfigString); + + auto configurator = createConfigurator(protocol); + auto result = configurator->createConfig(credentials, container, protocolConfig, errorCode); + if (errorCode != ErrorCode::NoError || !result) { + return errorCode; + } + + // Extract nativeConfig + QString nativeConfig; + if (auto openVpnConfig = qSharedPointerCast(result)) { + nativeConfig = openVpnConfig->clientProtocolConfig.nativeConfig; + } else if (auto wgConfig = qSharedPointerCast(result)) { + nativeConfig = wgConfig->clientProtocolConfig.nativeConfig; + } else if (auto awgConfig = qSharedPointerCast(result)) { + nativeConfig = awgConfig->clientProtocolConfig.nativeConfig; + } else if (auto cloakConfig = qSharedPointerCast(result)) { + nativeConfig = cloakConfig->clientProtocolConfig.nativeConfig; + } else if (auto xrayConfig = qSharedPointerCast(result)) { + nativeConfig = xrayConfig->clientProtocolConfig.nativeConfig; + } else if (auto shadowsocksConfig = qSharedPointerCast(result)) { + nativeConfig = shadowsocksConfig->clientProtocolConfig.nativeConfig; + } else if (auto ikev2Config = qSharedPointerCast(result)) { + nativeConfig = ikev2Config->clientProtocolConfig.nativeConfig; + } + + protocolConfigString = configurator->processConfigWithExportSettings(dns, isApiConfig, nativeConfig); return errorCode; } @@ -143,3 +224,4 @@ void VpnConfigurationsController::updateContainerConfigAfterInstallation(const D containerConfig.insert(ProtocolProps::protoToString(mainProto), protocol); } } + diff --git a/client/core/controllers/vpnConfigurationController.h b/client/core/controllers/vpnConfigurationController.h index 34fd1c48e..2730db47a 100644 --- a/client/core/controllers/vpnConfigurationController.h +++ b/client/core/controllers/vpnConfigurationController.h @@ -6,6 +6,7 @@ #include "configurators/configurator_base.h" #include "core/models/containers/containers_defs.h" #include "core/defs.h" +#include "core/models/protocols/protocolConfig.h" #include "settings.h" class VpnConfigurationsController : public QObject @@ -29,6 +30,7 @@ signals: private: QScopedPointer createConfigurator(const Proto protocol); + QSharedPointer createProtocolConfig(const Proto protocol, const QJsonObject &protocolConfigJson); std::shared_ptr m_settings; QSharedPointer m_serverController; diff --git a/client/core/models/protocols/awgProtocolConfig.cpp b/client/core/models/protocols/awgProtocolConfig.cpp index 9e82cedea..939f49c5c 100644 --- a/client/core/models/protocols/awgProtocolConfig.cpp +++ b/client/core/models/protocols/awgProtocolConfig.cpp @@ -13,19 +13,22 @@ AwgProtocolConfig::AwgProtocolConfig(const QString &protocolName) : ProtocolConf AwgProtocolConfig::AwgProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) { - serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); - serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); - serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(protocols::awg::defaultPort); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString("udp"); + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); + serverProtocolConfig.mtu = protocolConfigObject.value(config_key::mtu).toString(protocols::awg::defaultMtu); - serverProtocolConfig.awgData.junkPacketCount = protocolConfigObject.value(config_key::junkPacketCount).toString(); - serverProtocolConfig.awgData.junkPacketMinSize = protocolConfigObject.value(config_key::junkPacketMinSize).toString(); - serverProtocolConfig.awgData.junkPacketMaxSize = protocolConfigObject.value(config_key::junkPacketMaxSize).toString(); - serverProtocolConfig.awgData.initPacketJunkSize = protocolConfigObject.value(config_key::initPacketJunkSize).toString(); - serverProtocolConfig.awgData.responsePacketJunkSize = protocolConfigObject.value(config_key::responsePacketJunkSize).toString(); - serverProtocolConfig.awgData.initPacketMagicHeader = protocolConfigObject.value(config_key::initPacketMagicHeader).toString(); - serverProtocolConfig.awgData.responsePacketMagicHeader = protocolConfigObject.value(config_key::responsePacketMagicHeader).toString(); - serverProtocolConfig.awgData.underloadPacketMagicHeader = protocolConfigObject.value(config_key::underloadPacketMagicHeader).toString(); - serverProtocolConfig.awgData.transportPacketMagicHeader = protocolConfigObject.value(config_key::transportPacketMagicHeader).toString(); + serverProtocolConfig.awgData.junkPacketCount = protocolConfigObject.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); + serverProtocolConfig.awgData.junkPacketMinSize = protocolConfigObject.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); + serverProtocolConfig.awgData.junkPacketMaxSize = protocolConfigObject.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); + serverProtocolConfig.awgData.initPacketJunkSize = protocolConfigObject.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); + serverProtocolConfig.awgData.responsePacketJunkSize = protocolConfigObject.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); + serverProtocolConfig.awgData.cookieReplyPacketJunkSize = protocolConfigObject.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize); + serverProtocolConfig.awgData.transportPacketJunkSize = protocolConfigObject.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize); + serverProtocolConfig.awgData.initPacketMagicHeader = protocolConfigObject.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); + serverProtocolConfig.awgData.responsePacketMagicHeader = protocolConfigObject.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader); + serverProtocolConfig.awgData.underloadPacketMagicHeader = protocolConfigObject.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader); + serverProtocolConfig.awgData.transportPacketMagicHeader = protocolConfigObject.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); if (!clientProtocolString.isEmpty()) { @@ -38,6 +41,8 @@ AwgProtocolConfig::AwgProtocolConfig(const QJsonObject &protocolConfigObject, co clientProtocolConfig.awgData.junkPacketMaxSize = clientProtocolConfigObject.value(config_key::junkPacketMaxSize).toString(); clientProtocolConfig.awgData.initPacketJunkSize = clientProtocolConfigObject.value(config_key::initPacketJunkSize).toString(); clientProtocolConfig.awgData.responsePacketJunkSize = clientProtocolConfigObject.value(config_key::responsePacketJunkSize).toString(); + clientProtocolConfig.awgData.cookieReplyPacketJunkSize = clientProtocolConfigObject.value(config_key::cookieReplyPacketJunkSize).toString(); + clientProtocolConfig.awgData.transportPacketJunkSize = clientProtocolConfigObject.value(config_key::transportPacketJunkSize).toString(); clientProtocolConfig.awgData.initPacketMagicHeader = clientProtocolConfigObject.value(config_key::initPacketMagicHeader).toString(); clientProtocolConfig.awgData.responsePacketMagicHeader = clientProtocolConfigObject.value(config_key::responsePacketMagicHeader).toString(); @@ -91,6 +96,9 @@ QJsonObject AwgProtocolConfig::toJson() const if (!serverProtocolConfig.subnetAddress.isEmpty()) { json[config_key::subnet_address] = serverProtocolConfig.subnetAddress; } + if (!serverProtocolConfig.mtu.isEmpty()) { + json[config_key::mtu] = serverProtocolConfig.mtu; + } if (!serverProtocolConfig.awgData.junkPacketCount.isEmpty()) { json[config_key::junkPacketCount] = serverProtocolConfig.awgData.junkPacketCount; @@ -107,6 +115,12 @@ QJsonObject AwgProtocolConfig::toJson() const if (!serverProtocolConfig.awgData.responsePacketJunkSize.isEmpty()) { json[config_key::responsePacketJunkSize] = serverProtocolConfig.awgData.responsePacketJunkSize; } + if (!serverProtocolConfig.awgData.cookieReplyPacketJunkSize.isEmpty()) { + json[config_key::cookieReplyPacketJunkSize] = serverProtocolConfig.awgData.cookieReplyPacketJunkSize; + } + if (!serverProtocolConfig.awgData.transportPacketJunkSize.isEmpty()) { + json[config_key::transportPacketJunkSize] = serverProtocolConfig.awgData.transportPacketJunkSize; + } if (!serverProtocolConfig.awgData.initPacketMagicHeader.isEmpty()) { json[config_key::initPacketMagicHeader] = serverProtocolConfig.awgData.initPacketMagicHeader; } diff --git a/client/core/models/protocols/awgProtocolConfig.h b/client/core/models/protocols/awgProtocolConfig.h index 90ef9ba49..26e958219 100644 --- a/client/core/models/protocols/awgProtocolConfig.h +++ b/client/core/models/protocols/awgProtocolConfig.h @@ -17,6 +17,8 @@ namespace awg QString initPacketJunkSize; QString responsePacketJunkSize; + QString cookieReplyPacketJunkSize; + QString transportPacketJunkSize; QString initPacketMagicHeader; QString responsePacketMagicHeader; @@ -30,6 +32,7 @@ namespace awg QString transportProto; QString subnetAddress; + QString mtu; AwgData awgData; }; diff --git a/client/core/models/protocols/cloakProtocolConfig.cpp b/client/core/models/protocols/cloakProtocolConfig.cpp index c5dd916a0..e6fa50c18 100644 --- a/client/core/models/protocols/cloakProtocolConfig.cpp +++ b/client/core/models/protocols/cloakProtocolConfig.cpp @@ -8,9 +8,9 @@ using namespace amnezia; CloakProtocolConfig::CloakProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) { - serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); - serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); - serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString(); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(protocols::cloak::defaultPort); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(protocols::cloak::defaultCipher); + serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString(protocols::cloak::defaultRedirSite); auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); if (!clientProtocolString.isEmpty()) { diff --git a/client/core/models/protocols/cloakProtocolConfig.h b/client/core/models/protocols/cloakProtocolConfig.h index f82dc34e3..46733f9b9 100644 --- a/client/core/models/protocols/cloakProtocolConfig.h +++ b/client/core/models/protocols/cloakProtocolConfig.h @@ -18,6 +18,20 @@ namespace cloak struct ClientProtocolConfig { bool isEmpty = true; + + QString transport = "direct"; + QString proxyMethod = "openvpn"; + QString encryptionMethod = "aes-gcm"; + QString uid; + QString publicKey; + QString serverName; + int numConn = 1; + QString browserSig = "chrome"; + int streamTimeout = 300; + QString remoteHost; + QString remotePort; + + QString nativeConfig; }; } diff --git a/client/core/models/protocols/ikev2ProtocolConfig.cpp b/client/core/models/protocols/ikev2ProtocolConfig.cpp new file mode 100644 index 000000000..b98be2258 --- /dev/null +++ b/client/core/models/protocols/ikev2ProtocolConfig.cpp @@ -0,0 +1,32 @@ +#include "ikev2ProtocolConfig.h" + +#include "config_key.h" + +Ikev2ProtocolConfig::Ikev2ProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) + : ProtocolConfig(protocolName) +{ + Q_UNUSED(protocolConfigObject) +} + +Ikev2ProtocolConfig::Ikev2ProtocolConfig(const QString &protocolName) + : ProtocolConfig(protocolName) +{ +} + +QJsonObject Ikev2ProtocolConfig::toJson() const +{ + QJsonObject protocolConfigObject; + + return protocolConfigObject; +} + +bool Ikev2ProtocolConfig::hasEqualServerSettings(const Ikev2ProtocolConfig &other) const +{ + Q_UNUSED(other) + return true; +} + +void Ikev2ProtocolConfig::clearClientSettings() +{ + clientProtocolConfig = ikev2::ClientProtocolConfig(); +} diff --git a/client/core/models/protocols/ikev2ProtocolConfig.h b/client/core/models/protocols/ikev2ProtocolConfig.h new file mode 100644 index 000000000..c537af02e --- /dev/null +++ b/client/core/models/protocols/ikev2ProtocolConfig.h @@ -0,0 +1,45 @@ +#ifndef IKEV2PROTOCOLCONFIG_H +#define IKEV2PROTOCOLCONFIG_H + +#include +#include +#include + +#include "protocolConfig.h" + +namespace ikev2 +{ + struct ServerProtocolConfig + { + bool isEmpty = true; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + + QString hostName; + QString userName; + QString cert; + QString password; + + QString nativeConfig; + }; +} + +class Ikev2ProtocolConfig : public ProtocolConfig +{ +public: + Ikev2ProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + explicit Ikev2ProtocolConfig(const QString &protocolName); + + QJsonObject toJson() const override; + + bool hasEqualServerSettings(const Ikev2ProtocolConfig &other) const; + void clearClientSettings(); + + ikev2::ServerProtocolConfig serverProtocolConfig; + ikev2::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // IKEV2PROTOCOLCONFIG_H diff --git a/client/core/models/protocols/openvpnProtocolConfig.cpp b/client/core/models/protocols/openvpnProtocolConfig.cpp index 4b4c8e854..480217c87 100644 --- a/client/core/models/protocols/openvpnProtocolConfig.cpp +++ b/client/core/models/protocols/openvpnProtocolConfig.cpp @@ -8,17 +8,16 @@ using namespace amnezia; OpenVpnProtocolConfig::OpenVpnProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) { - serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); - serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); - serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(protocols::openvpn::defaultSubnetAddress); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(protocols::openvpn::defaultPort); serverProtocolConfig.ncpDisable = protocolConfigObject.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable); - serverProtocolConfig.hash = protocolConfigObject.value(config_key::hash).toString(); - serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); + serverProtocolConfig.hash = protocolConfigObject.value(config_key::hash).toString(protocols::openvpn::defaultHash); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(protocols::openvpn::defaultCipher); serverProtocolConfig.tlsAuth = protocolConfigObject.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth); - serverProtocolConfig.blockOutsideDns = - protocolConfigObject.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns); - serverProtocolConfig.additionalClientConfig = protocolConfigObject.value(config_key::additional_client_config).toString(); - serverProtocolConfig.additionalServerConfig = protocolConfigObject.value(config_key::additional_server_config).toString(); + serverProtocolConfig.blockOutsideDns = protocolConfigObject.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns); + serverProtocolConfig.additionalClientConfig = protocolConfigObject.value(config_key::additional_client_config).toString(protocols::openvpn::defaultAdditionalClientConfig); + serverProtocolConfig.additionalServerConfig = protocolConfigObject.value(config_key::additional_server_config).toString(protocols::openvpn::defaultAdditionalServerConfig); auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); if (!clientProtocolString.isEmpty()) { diff --git a/client/core/models/protocols/protocolConfig.h b/client/core/models/protocols/protocolConfig.h index 899e6ec00..a29c6935a 100644 --- a/client/core/models/protocols/protocolConfig.h +++ b/client/core/models/protocols/protocolConfig.h @@ -11,10 +11,14 @@ class ShadowsocksProtocolConfig; class CloakProtocolConfig; class XrayProtocolConfig; class AwgProtocolConfig; +class SftpProtocolConfig; +class Socks5ProtocolConfig; +class Ikev2ProtocolConfig; using ProtocolConfigVariant = std::variant, QSharedPointer, QSharedPointer, - QSharedPointer, QSharedPointer, QSharedPointer >; + QSharedPointer, QSharedPointer, QSharedPointer, + QSharedPointer, QSharedPointer, QSharedPointer >; class ProtocolConfig { diff --git a/client/core/models/protocols/sftpProtocolConfig.cpp b/client/core/models/protocols/sftpProtocolConfig.cpp new file mode 100644 index 000000000..04e7b8858 --- /dev/null +++ b/client/core/models/protocols/sftpProtocolConfig.cpp @@ -0,0 +1,48 @@ +#include "sftpProtocolConfig.h" + +#include +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +SftpProtocolConfig::SftpProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Proto::Sftp))); + serverProtocolConfig.userName = protocolConfigObject.value(config_key::userName).toString(protocols::sftp::defaultUserName); + serverProtocolConfig.password = protocolConfigObject.value(config_key::password).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + } +} + +QJsonObject SftpProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.userName.isEmpty()) { + json[config_key::userName] = serverProtocolConfig.userName; + } + if (!serverProtocolConfig.password.isEmpty()) { + json[config_key::password] = serverProtocolConfig.password; + } + + return json; +} + +bool SftpProtocolConfig::hasEqualServerSettings(const SftpProtocolConfig &other) const +{ + return serverProtocolConfig.port == other.serverProtocolConfig.port && + serverProtocolConfig.userName == other.serverProtocolConfig.userName && + serverProtocolConfig.password == other.serverProtocolConfig.password; +} + +void SftpProtocolConfig::clearClientSettings() +{ + clientProtocolConfig.isEmpty = true; +} diff --git a/client/core/models/protocols/sftpProtocolConfig.h b/client/core/models/protocols/sftpProtocolConfig.h new file mode 100644 index 000000000..113fc33cd --- /dev/null +++ b/client/core/models/protocols/sftpProtocolConfig.h @@ -0,0 +1,38 @@ +#ifndef SFTPPROTOCOLCONFIG_H +#define SFTPPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace sftp +{ + struct ServerProtocolConfig + { + QString port; + QString userName; + QString password; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + }; +} + +class SftpProtocolConfig : public ProtocolConfig +{ +public: + SftpProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + bool hasEqualServerSettings(const SftpProtocolConfig &other) const; + void clearClientSettings(); + + sftp::ServerProtocolConfig serverProtocolConfig; + sftp::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // SFTPPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/shadowsocksProtocolConfig.cpp b/client/core/models/protocols/shadowsocksProtocolConfig.cpp index 30539a9b7..1f49ee90d 100644 --- a/client/core/models/protocols/shadowsocksProtocolConfig.cpp +++ b/client/core/models/protocols/shadowsocksProtocolConfig.cpp @@ -8,8 +8,8 @@ using namespace amnezia; ShadowsocksProtocolConfig::ShadowsocksProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) { - serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); - serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(protocols::shadowsocks::defaultPort); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher); auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); if (!clientProtocolString.isEmpty()) { diff --git a/client/core/models/protocols/shadowsocksProtocolConfig.h b/client/core/models/protocols/shadowsocksProtocolConfig.h index 1b7480f87..15db5fd84 100644 --- a/client/core/models/protocols/shadowsocksProtocolConfig.h +++ b/client/core/models/protocols/shadowsocksProtocolConfig.h @@ -17,6 +17,15 @@ namespace shadowsocks struct ClientProtocolConfig { bool isEmpty = true; + + QString server; + QString serverPort; + QString localPort; + QString password; + int timeout = 60; + QString method; + + QString nativeConfig; }; } diff --git a/client/core/models/protocols/socks5ProtocolConfig.cpp b/client/core/models/protocols/socks5ProtocolConfig.cpp new file mode 100644 index 000000000..0ae385188 --- /dev/null +++ b/client/core/models/protocols/socks5ProtocolConfig.cpp @@ -0,0 +1,48 @@ +#include "socks5ProtocolConfig.h" + +#include +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +Socks5ProtocolConfig::Socks5ProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(protocols::socks5Proxy::defaultPort); + serverProtocolConfig.userName = protocolConfigObject.value(config_key::userName).toString(protocols::socks5Proxy::defaultUserName); + serverProtocolConfig.password = protocolConfigObject.value(config_key::password).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + } +} + +QJsonObject Socks5ProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.userName.isEmpty()) { + json[config_key::userName] = serverProtocolConfig.userName; + } + if (!serverProtocolConfig.password.isEmpty()) { + json[config_key::password] = serverProtocolConfig.password; + } + + return json; +} + +bool Socks5ProtocolConfig::hasEqualServerSettings(const Socks5ProtocolConfig &other) const +{ + return serverProtocolConfig.port == other.serverProtocolConfig.port && + serverProtocolConfig.userName == other.serverProtocolConfig.userName && + serverProtocolConfig.password == other.serverProtocolConfig.password; +} + +void Socks5ProtocolConfig::clearClientSettings() +{ + clientProtocolConfig.isEmpty = true; +} diff --git a/client/core/models/protocols/socks5ProtocolConfig.h b/client/core/models/protocols/socks5ProtocolConfig.h new file mode 100644 index 000000000..d45af4bec --- /dev/null +++ b/client/core/models/protocols/socks5ProtocolConfig.h @@ -0,0 +1,38 @@ +#ifndef SOCKS5PROTOCOLCONFIG_H +#define SOCKS5PROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace socks5 +{ + struct ServerProtocolConfig + { + QString port; + QString userName; + QString password; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + }; +} + +class Socks5ProtocolConfig : public ProtocolConfig +{ +public: + Socks5ProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + bool hasEqualServerSettings(const Socks5ProtocolConfig &other) const; + void clearClientSettings(); + + socks5::ServerProtocolConfig serverProtocolConfig; + socks5::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // SOCKS5PROTOCOLCONFIG_H diff --git a/client/core/models/protocols/wireguardProtocolConfig.cpp b/client/core/models/protocols/wireguardProtocolConfig.cpp index c44173d22..6c1c566c3 100644 --- a/client/core/models/protocols/wireguardProtocolConfig.cpp +++ b/client/core/models/protocols/wireguardProtocolConfig.cpp @@ -10,9 +10,10 @@ using namespace amnezia; WireGuardProtocolConfig::WireGuardProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) { - serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); - serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); - serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(protocols::wireguard::defaultPort); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString("udp"); + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); + serverProtocolConfig.mtu = protocolConfigObject.value(config_key::mtu).toString(protocols::wireguard::defaultMtu); auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); if (!clientProtocolString.isEmpty()) { @@ -59,6 +60,9 @@ QJsonObject WireGuardProtocolConfig::toJson() const if (!serverProtocolConfig.subnetAddress.isEmpty()) { json[config_key::subnet_address] = serverProtocolConfig.subnetAddress; } + if (!serverProtocolConfig.mtu.isEmpty()) { + json[config_key::mtu] = serverProtocolConfig.mtu; + } if (!clientProtocolConfig.isEmpty) { QJsonObject clientConfigJson; diff --git a/client/core/models/protocols/wireguardProtocolConfig.h b/client/core/models/protocols/wireguardProtocolConfig.h index 7d3f6620a..a0aac14c6 100644 --- a/client/core/models/protocols/wireguardProtocolConfig.h +++ b/client/core/models/protocols/wireguardProtocolConfig.h @@ -27,6 +27,7 @@ namespace wireguard QString transportProto; QString subnetAddress; + QString mtu; }; struct ClientProtocolConfig diff --git a/client/core/models/protocols/xrayProtocolConfig.cpp b/client/core/models/protocols/xrayProtocolConfig.cpp index 001270317..4e5194d09 100644 --- a/client/core/models/protocols/xrayProtocolConfig.cpp +++ b/client/core/models/protocols/xrayProtocolConfig.cpp @@ -8,9 +8,9 @@ using namespace amnezia; XrayProtocolConfig::XrayProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) { - serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString(); - serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); - serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString(protocols::xray::defaultSite); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(protocols::xray::defaultPort); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString("tcp"); auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); if (!clientProtocolString.isEmpty()) { diff --git a/client/core/models/protocols/xrayProtocolConfig.h b/client/core/models/protocols/xrayProtocolConfig.h index 941816fe0..005da6ecf 100644 --- a/client/core/models/protocols/xrayProtocolConfig.h +++ b/client/core/models/protocols/xrayProtocolConfig.h @@ -18,6 +18,9 @@ namespace xray struct ClientProtocolConfig { bool isEmpty = true; + + QString clientId; + QString nativeConfig; }; }