From e3fb239de962769396e3536bd7965ee813efdcb4 Mon Sep 17 00:00:00 2001 From: pokamest Date: Mon, 10 May 2021 02:33:31 +0300 Subject: [PATCH] Config export --- client/client.pro | 4 + client/configurators/openvpn_configurator.cpp | 25 +- client/configurators/openvpn_configurator.h | 2 + client/configurators/vpn_configurator.cpp | 33 + client/configurators/vpn_configurator.h | 18 + client/core/defs.h | 13 - client/core/errorstrings.cpp | 58 ++ client/core/errorstrings.h | 51 +- client/core/scripts_registry.h | 2 +- client/core/server_defs.h | 2 +- client/core/servercontroller.cpp | 39 +- client/core/servercontroller.h | 2 +- client/protocols/protocols_defs.cpp | 80 +++ client/protocols/protocols_defs.h | 44 +- client/protocols/shadowsocksvpnprotocol.h | 2 +- client/server_scripts/openvpn/template.ovpn | 2 +- .../openvpn_cloak/run_container.sh | 2 +- .../openvpn_shadowsocks/template.ovpn | 2 +- client/server_scripts/setup_host_firewall.sh | 12 +- client/settings.cpp | 43 +- client/ui/mainwindow.cpp | 438 ++++++++++-- client/ui/mainwindow.h | 13 +- client/ui/mainwindow.ui | 657 +++++++++++++++--- client/ui/server_widget.cpp | 30 + client/ui/server_widget.h | 8 + client/ui/server_widget.ui | 4 +- client/utils.h | 2 + client/vpnconnection.cpp | 8 +- 28 files changed, 1247 insertions(+), 349 deletions(-) create mode 100644 client/configurators/vpn_configurator.cpp create mode 100644 client/configurators/vpn_configurator.h create mode 100644 client/core/errorstrings.cpp create mode 100644 client/protocols/protocols_defs.cpp diff --git a/client/client.pro b/client/client.pro index b4b87af4..7ecf401b 100644 --- a/client/client.pro +++ b/client/client.pro @@ -15,6 +15,7 @@ HEADERS += \ ../ipc/ipc.h \ configurators/cloak_configurator.h \ configurators/shadowsocks_configurator.h \ + configurators/vpn_configurator.h \ core/defs.h \ core/errorstrings.h \ core/ipcclient.h \ @@ -41,6 +42,8 @@ HEADERS += \ SOURCES += \ configurators/cloak_configurator.cpp \ configurators/shadowsocks_configurator.cpp \ + configurators/vpn_configurator.cpp \ + core/errorstrings.cpp \ core/ipcclient.cpp \ configurators/openvpn_configurator.cpp \ core/scripts_registry.cpp \ @@ -50,6 +53,7 @@ SOURCES += \ main.cpp \ managementserver.cpp \ protocols/openvpnovercloakprotocol.cpp \ + protocols/protocols_defs.cpp \ protocols/shadowsocksvpnprotocol.cpp \ settings.cpp \ ui/Controls/SlidingStackedWidget.cpp \ diff --git a/client/configurators/openvpn_configurator.cpp b/client/configurators/openvpn_configurator.cpp index 4d29c5eb..c98fbc6a 100644 --- a/client/configurators/openvpn_configurator.cpp +++ b/client/configurators/openvpn_configurator.cpp @@ -180,8 +180,6 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co if (errorCode) *errorCode = ErrorCode::RemoteProcessCrashError; } - ServerController::setupServerFirewall(credentials); - return connData; } @@ -202,15 +200,6 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia return ""; } - config.replace("$PRIMARY_DNS", m_settings().primaryDns()); - config.replace("$SECONDARY_DNS", m_settings().secondaryDns()); - - if (m_settings().customRouting()) { - config.replace("redirect-gateway def1 bypass-dhcp", ""); - } - - config.replace("$REMOTE_HOST", connData.host); - config.replace("$REMOTE_PORT", amnezia::protocols::openvpn::defaultPort); config.replace("$OPENVPN_CA_CERT", connData.caCert); config.replace("$OPENVPN_CLIENT_CERT", connData.clientCert); config.replace("$OPENVPN_PRIV_KEY", connData.privKey); @@ -219,7 +208,21 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia #ifdef Q_OS_MAC config.replace("block-outside-dns", ""); #endif + //qDebug().noquote() << config; + return processConfigWithLocalSettings(config); +} + +QString OpenVpnConfigurator::processConfigWithLocalSettings(QString config) +{ + // TODO replace DNS if it already set + config.replace("$PRIMARY_DNS", m_settings().primaryDns()); + config.replace("$SECONDARY_DNS", m_settings().secondaryDns()); + + if (m_settings().customRouting()) { + config.replace("redirect-gateway def1 bypass-dhcp", ""); + } + return config; } diff --git a/client/configurators/openvpn_configurator.h b/client/configurators/openvpn_configurator.h index a40effef..6002dde0 100644 --- a/client/configurators/openvpn_configurator.h +++ b/client/configurators/openvpn_configurator.h @@ -25,6 +25,8 @@ public: static QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); + static QString processConfigWithLocalSettings(QString config); + static QString convertOpenSShKey(const QString &key); static ErrorCode signCert(DockerContainer container, diff --git a/client/configurators/vpn_configurator.cpp b/client/configurators/vpn_configurator.cpp new file mode 100644 index 00000000..b4ee7976 --- /dev/null +++ b/client/configurators/vpn_configurator.cpp @@ -0,0 +1,33 @@ +#include "vpn_configurator.h" +#include "openvpn_configurator.h" +#include "cloak_configurator.h" +#include "shadowsocks_configurator.h" +//#include "wireguard_configurator.h" + +#include +#include +#include + +#include "protocols/protocols_defs.h" + + +QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, + DockerContainer container, const QJsonObject &containerConfig, Protocol proto, ErrorCode *errorCode) +{ + switch (proto) { + case Protocol::OpenVpn: + return OpenVpnConfigurator::genOpenVpnConfig(credentials, container, containerConfig, errorCode); + + case Protocol::ShadowSocks: + return ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, errorCode); + + case Protocol::Cloak: + return CloakConfigurator::genCloakConfig(credentials, container, containerConfig, errorCode); + +// case Protocol::WireGuard: +// return WireGuardConfigurator::genWireGuardConfig(credentials, container, containerConfig, errorCode); + + default: + return ""; + } +} diff --git a/client/configurators/vpn_configurator.h b/client/configurators/vpn_configurator.h new file mode 100644 index 00000000..02f410a2 --- /dev/null +++ b/client/configurators/vpn_configurator.h @@ -0,0 +1,18 @@ +#ifndef VPN_CONFIGURATOR_H +#define VPN_CONFIGURATOR_H + +#include + +#include "core/defs.h" +#include "settings.h" +#include "core/servercontroller.h" + +class VpnConfigurator +{ +public: + + static QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, Protocol proto, ErrorCode *errorCode = nullptr); +}; + +#endif // VPN_CONFIGURATOR_H diff --git a/client/core/defs.h b/client/core/defs.h index cce2f5a5..c0db0eed 100644 --- a/client/core/defs.h +++ b/client/core/defs.h @@ -6,19 +6,6 @@ namespace amnezia { -//static DockerContainer containerForProto(Protocol proto) -//{ -// Q_ASSERT(proto != Protocol::Any); - -// switch (proto) { -// case Protocol::OpenVpn: return DockerContainer::OpenVpn; -// case Protocol::OpenVpnOverCloak: return DockerContainer::OpenVpnOverCloak; -// case Protocol::ShadowSocksOverOpenVpn: return DockerContainer::ShadowSocksOverOpenVpn; -// case Protocol::WireGuard: return DockerContainer::WireGuard; -// case Protocol::Any: return DockerContainer::None; -// } -//} - struct ServerCredentials { QString hostName; diff --git a/client/core/errorstrings.cpp b/client/core/errorstrings.cpp new file mode 100644 index 00000000..fda1aea8 --- /dev/null +++ b/client/core/errorstrings.cpp @@ -0,0 +1,58 @@ +#include "errorstrings.h" + +using namespace amnezia; + +QString errorString(ErrorCode code){ + switch (code) { + + // General error codes + case(NoError): return QObject::tr("No error"); + case(UnknownError): return QObject::tr("Unknown Error"); + case(NotImplementedError): return QObject::tr("Function not implemented"); + + // Server errors + case(ServerCheckFailed): return QObject::tr("Server check failed"); + case(ServerPortAlreadyAllocatedError): return QObject::tr("Server port already used. Check for another software"); + + // Ssh connection errors + case(SshSocketError): return QObject::tr("Ssh connection error"); + case(SshTimeoutError): return QObject::tr("Ssh connection timeout"); + case(SshProtocolError): return QObject::tr("Ssh protocol error"); + case(SshHostKeyError): return QObject::tr("Ssh server ket check failed"); + case(SshKeyFileError): return QObject::tr("Ssh key file error"); + case(SshAuthenticationError): return QObject::tr("Ssh authentication error"); + case(SshClosedByServerError): return QObject::tr("Ssh session closed"); + case(SshInternalError): return QObject::tr("Ssh internal error"); + + // Ssh remote process errors + case(SshRemoteProcessCreationError): return QObject::tr("Failed to create remote process on server"); + case(FailedToStartRemoteProcessError): return QObject::tr("Failed to start remote process on server"); + case(RemoteProcessCrashError): return QObject::tr("Remote process on server crashed"); + + // Local errors + case (FailedToSaveConfigData): return QObject::tr("Failed to save config to disk"); + case (OpenVpnConfigMissing): return QObject::tr("OpenVPN config missing"); + case (OpenVpnManagementServerError): return QObject::tr("OpenVPN management server error"); + case (EasyRsaError): return QObject::tr("EasyRSA runtime error"); + + // Distro errors + case (OpenVpnExecutableMissing): return QObject::tr("OpenVPN executable missing"); + case (EasyRsaExecutableMissing): return QObject::tr("EasyRsa executable missing"); + case (AmneziaServiceConnectionFailed): return QObject::tr("Amnezia helper service error"); + + // VPN errors + case (OpenVpnAdaptersInUseError): return QObject::tr("Can't connect: another VPN connection is active"); + + case(InternalError): + default: + return QObject::tr("Internal error"); + } +} + +QDebug operator<<(QDebug debug, const ErrorCode &e) +{ + QDebugStateSaver saver(debug); + debug.nospace() << "ErrorCode::" << int(e) << "(" << errorString(e) << ")"; + + return debug; +} diff --git a/client/core/errorstrings.h b/client/core/errorstrings.h index da9bf01d..a3f817cb 100644 --- a/client/core/errorstrings.h +++ b/client/core/errorstrings.h @@ -1,55 +1,14 @@ #ifndef ERRORSTRINGS_H #define ERRORSTRINGS_H +#include + #include "defs.h" + using namespace amnezia; -static QString errorString(ErrorCode code){ - switch (code) { - - // General error codes - case(NoError): return QObject::tr("No error"); - case(UnknownError): return QObject::tr("Unknown Error"); - case(NotImplementedError): return QObject::tr("Function not implemented"); - - // Server errors - case(ServerCheckFailed): return QObject::tr("Server check failed"); - case(ServerPortAlreadyAllocatedError): return QObject::tr("Server port already used. Check for another software"); - - // Ssh connection errors - case(SshSocketError): return QObject::tr("Ssh connection error"); - case(SshTimeoutError): return QObject::tr("Ssh connection timeout"); - case(SshProtocolError): return QObject::tr("Ssh protocol error"); - case(SshHostKeyError): return QObject::tr("Ssh server ket check failed"); - case(SshKeyFileError): return QObject::tr("Ssh key file error"); - case(SshAuthenticationError): return QObject::tr("Ssh authentication error"); - case(SshClosedByServerError): return QObject::tr("Ssh session closed"); - case(SshInternalError): return QObject::tr("Ssh internal error"); - - // Ssh remote process errors - case(SshRemoteProcessCreationError): return QObject::tr("Failed to create remote process on server"); - case(FailedToStartRemoteProcessError): return QObject::tr("Failed to start remote process on server"); - case(RemoteProcessCrashError): return QObject::tr("Remote process on server crashed"); - - // Local errors - case (FailedToSaveConfigData): return QObject::tr("Failed to save config to disk"); - case (OpenVpnConfigMissing): return QObject::tr("OpenVPN config missing"); - case (OpenVpnManagementServerError): return QObject::tr("OpenVPN management server error"); - case (EasyRsaError): return QObject::tr("EasyRSA runtime error"); - - // Distro errors - case (OpenVpnExecutableMissing): return QObject::tr("OpenVPN executable missing"); - case (EasyRsaExecutableMissing): return QObject::tr("EasyRsa executable missing"); - case (AmneziaServiceConnectionFailed): return QObject::tr("Amnezia helper service error"); - - // VPN errors - case (OpenVpnAdaptersInUseError): return QObject::tr("Can't connect: another VPN connection is active"); - - case(InternalError): - default: - return QObject::tr("Internal error"); - } -} +QString errorString(ErrorCode code); +QDebug operator<<(QDebug debug, const ErrorCode &e); #endif // ERRORSTRINGS_H diff --git a/client/core/scripts_registry.h b/client/core/scripts_registry.h index 88db5068..d7522c02 100644 --- a/client/core/scripts_registry.h +++ b/client/core/scripts_registry.h @@ -3,7 +3,7 @@ #include #include "core/defs.h" -#include "protocols/protocols_defs.h"" +#include "protocols/protocols_defs.h" namespace amnezia { diff --git a/client/core/server_defs.h b/client/core/server_defs.h index f70d5ebb..2b33ee91 100644 --- a/client/core/server_defs.h +++ b/client/core/server_defs.h @@ -2,7 +2,7 @@ #define SERVER_DEFS_H #include -#include "protocols/protocols_defs.h"" +#include "protocols/protocols_defs.h" namespace amnezia { namespace server { diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index 16492d24..052cd157 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -122,7 +122,7 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams, ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials, const QString &file, const QString &path) { - ErrorCode e; + ErrorCode e = ErrorCode::NoError; QString tmpFileName = QString("/tmp/%1.tmp").arg(Utils::getRandomString(16)); e = uploadFileToHost(credentials, file.toUtf8(), tmpFileName); if (e) return e; @@ -388,7 +388,10 @@ ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig) { - if (isReinstallContainerRequred(container, oldConfig, newConfig)) { + bool reinstallRequred = isReinstallContainerRequred(container, oldConfig, newConfig); + qDebug() << "ServerController::updateContainer for container" << container << "reinstall required is" << reinstallRequred; + + if (reinstallRequred) { return setupContainer(credentials, container, newConfig); } else { @@ -423,6 +426,15 @@ bool ServerController::isReinstallContainerRequred(DockerContainer container, co return true; } + if (container == DockerContainer::OpenVpnOverShadowSocks) { + const QJsonObject &oldProtoConfig = oldConfig[config_key::shadowsocks].toObject(); + const QJsonObject &newProtoConfig = newConfig[config_key::shadowsocks].toObject(); + + if (oldProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) != + newProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort)) + return true; + } + return false; } @@ -433,7 +445,7 @@ bool ServerController::isReinstallContainerRequred(DockerContainer container, co //ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials &credentials, const QJsonObject &config) //{ -// ErrorCode e; +// ErrorCode e = ErrorCode::NoError; // DockerContainer container = DockerContainer::OpenVpnOverCloak; // e = prepareHostWorker(credentials, container, config); @@ -588,6 +600,8 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential Vars vars; + vars.append({{"$REMOTE_HOST", credentials.hostName}}); + // OpenVPN vars vars.append({{"$VPN_SUBNET_IP", openvpnConfig.value(config_key::subnet_address).toString(amnezia::protocols::vpnDefaultSubnetAddress) }}); vars.append({{"$VPN_SUBNET_MASK_VAL", openvpnConfig.value(config_key::subnet_mask_val).toString(amnezia::protocols::vpnDefaultSubnetMaskVal) }}); @@ -609,6 +623,10 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential vars.append({{"$CONTAINER_NAME", amnezia::containerToString(container)}}); vars.append({{"$DOCKERFILE_FOLDER", "/opt/amnezia/" + amnezia::containerToString(container)}}); + // Cloak vars + vars.append({{"$CLOAK_SERVER_PORT", config.value(config_key::port).toString(protocols::cloak::defaultPort) }}); + vars.append({{"$FAKE_WEB_SITE_ADDRESS", cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) }}); + QString serverIp = Utils::getIPAddress(credentials.hostName); if (!serverIp.isEmpty()) { vars.append({{"$SERVER_IP_ADDRESS", serverIp}}); @@ -617,21 +635,6 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential qWarning() << "ServerController::genVarsForScript unable to resolve address for credentials.hostName"; } - // - - - if (container == DockerContainer::OpenVpn) { - vars.append({{"$DOCKER_PORT", config.value(config_key::port).toString(protocols::openvpn::defaultPort) }}); - } - else if (container == DockerContainer::OpenVpnOverCloak) { - vars.append({{"$DOCKER_PORT", config.value(config_key::port).toString(protocols::cloak::defaultPort) }}); - - vars.append({{"$FAKE_WEB_SITE_ADDRESS", cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) }}); - } - else if (container == DockerContainer::OpenVpnOverShadowSocks) { - vars.append({{"$DOCKER_PORT", config.value(config_key::port).toString(protocols::shadowsocks::defaultPort) }}); - } - return vars; } diff --git a/client/core/servercontroller.h b/client/core/servercontroller.h index 126e423a..9247f035 100644 --- a/client/core/servercontroller.h +++ b/client/core/servercontroller.h @@ -6,7 +6,7 @@ #include "sshconnection.h" #include "sshremoteprocess.h" #include "defs.h" -#include "protocols/protocols_defs.h"" +#include "protocols/protocols_defs.h" using namespace amnezia; diff --git a/client/protocols/protocols_defs.cpp b/client/protocols/protocols_defs.cpp new file mode 100644 index 00000000..b6485ec1 --- /dev/null +++ b/client/protocols/protocols_defs.cpp @@ -0,0 +1,80 @@ +#include "protocols_defs.h" + +QDebug operator<<(QDebug debug, const amnezia::Protocol &p) +{ + QDebugStateSaver saver(debug); + debug.nospace() << protoToString(p); + + return debug; +} + +QDebug operator<<(QDebug debug, const amnezia::DockerContainer &c) +{ + QDebugStateSaver saver(debug); + debug.nospace() << containerToString(c); + + return debug; +} + +amnezia::Protocol amnezia::protoFromString(QString proto){ + if (proto == config_key::openvpn) return Protocol::OpenVpn; + if (proto == config_key::cloak) return Protocol::Cloak; + if (proto == config_key::shadowsocks) return Protocol::ShadowSocks; + if (proto == config_key::wireguard) return Protocol::WireGuard; + return Protocol::Any; +} + +QString amnezia::protoToString(amnezia::Protocol proto){ + switch (proto) { + case(Protocol::OpenVpn): return config_key::openvpn; + case(Protocol::Cloak): return config_key::cloak; + case(Protocol::ShadowSocks): return config_key::shadowsocks; + case(Protocol::WireGuard): return config_key::wireguard; + default: return ""; + } +} + +amnezia::DockerContainer amnezia::containerFromString(const QString &container){ + if (container == config_key::amnezia_openvpn) return DockerContainer::OpenVpn; + if (container == config_key::amnezia_openvpn_cloak) return DockerContainer::OpenVpnOverCloak; + if (container == config_key::amnezia_shadowsocks) return DockerContainer::OpenVpnOverShadowSocks; + if (container == config_key::amnezia_wireguard) return DockerContainer::WireGuard; + return DockerContainer::None; +} + +QString amnezia::containerToString(amnezia::DockerContainer container){ + switch (container) { + case(DockerContainer::OpenVpn): return config_key::amnezia_openvpn; + case(DockerContainer::OpenVpnOverCloak): return config_key::amnezia_openvpn_cloak; + case(DockerContainer::OpenVpnOverShadowSocks): return config_key::amnezia_shadowsocks; + case(DockerContainer::WireGuard): return config_key::amnezia_wireguard; + default: return ""; + } +} + +QVector amnezia::allProtocols() +{ + return QVector { + Protocol::OpenVpn, + Protocol::ShadowSocks, + Protocol::Cloak, + Protocol::WireGuard + }; +} + +QVector amnezia::protocolsForContainer(amnezia::DockerContainer container) +{ + switch (container) { + case DockerContainer::OpenVpn: + return { Protocol::OpenVpn }; + + case DockerContainer::OpenVpnOverShadowSocks: + return { Protocol::OpenVpn, Protocol::ShadowSocks }; + + case DockerContainer::OpenVpnOverCloak: + return { Protocol::OpenVpn, Protocol::ShadowSocks, Protocol::Cloak }; + + default: + return {}; + } +} diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 87644859..f3266116 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -2,6 +2,7 @@ #define PROTOCOLS_DEFS_H #include +#include namespace amnezia { namespace config_key { @@ -88,6 +89,8 @@ constexpr char ckBypassUidKeyPath[] = "/opt/amnezia/cloak/cloak_bypass_uid.key"; constexpr char ckAdminKeyPath[] = "/opt/amnezia/cloak/cloak_admin_uid.key"; constexpr char defaultPort[] = "443"; constexpr char defaultRedirSite[] = "mail.ru"; +constexpr char defaultCipher[] = "chacha20-ietf-poly1305"; + } @@ -101,24 +104,11 @@ enum class Protocol { Cloak, WireGuard }; +QVector allProtocols(); -inline Protocol protoFromString(QString proto){ - if (proto == config_key::openvpn) return Protocol::OpenVpn; - if (proto == config_key::cloak) return Protocol::Cloak; - if (proto == config_key::shadowsocks) return Protocol::ShadowSocks; - if (proto == config_key::wireguard) return Protocol::WireGuard; - return Protocol::Any; -} +Protocol protoFromString(QString proto); +QString protoToString(Protocol proto); -inline QString protoToString(Protocol proto){ - switch (proto) { - case(Protocol::OpenVpn): return config_key::openvpn; - case(Protocol::Cloak): return config_key::cloak; - case(Protocol::ShadowSocks): return config_key::shadowsocks; - case(Protocol::WireGuard): return config_key::wireguard; - default: return ""; - } -} enum class DockerContainer { None, @@ -128,24 +118,14 @@ enum class DockerContainer { WireGuard }; -inline DockerContainer containerFromString(const QString &container){ - if (container == config_key::amnezia_openvpn) return DockerContainer::OpenVpn; - if (container == config_key::amnezia_openvpn_cloak) return DockerContainer::OpenVpnOverCloak; - if (container == config_key::amnezia_shadowsocks) return DockerContainer::OpenVpnOverShadowSocks; - if (container == config_key::amnezia_wireguard) return DockerContainer::WireGuard; - return DockerContainer::None; -} +DockerContainer containerFromString(const QString &container); +QString containerToString(DockerContainer container); -inline QString containerToString(DockerContainer container){ - switch (container) { - case(DockerContainer::OpenVpn): return config_key::amnezia_openvpn; - case(DockerContainer::OpenVpnOverCloak): return config_key::amnezia_openvpn_cloak; - case(DockerContainer::OpenVpnOverShadowSocks): return config_key::amnezia_shadowsocks; - case(DockerContainer::WireGuard): return config_key::amnezia_wireguard; - default: return ""; - } -} +QVector protocolsForContainer(DockerContainer container); } // namespace amnezia +QDebug operator<<(QDebug debug, const amnezia::Protocol &p); +QDebug operator<<(QDebug debug, const amnezia::DockerContainer &c); + #endif // PROTOCOLS_DEFS_H diff --git a/client/protocols/shadowsocksvpnprotocol.h b/client/protocols/shadowsocksvpnprotocol.h index 8a2ae4b1..52ff2186 100644 --- a/client/protocols/shadowsocksvpnprotocol.h +++ b/client/protocols/shadowsocksvpnprotocol.h @@ -3,7 +3,7 @@ #include "openvpnprotocol.h" #include "QProcess" -#include "protocols/protocols_defs.h"" +#include "protocols/protocols_defs.h" class ShadowSocksVpnProtocol : public OpenVpnProtocol { diff --git a/client/server_scripts/openvpn/template.ovpn b/client/server_scripts/openvpn/template.ovpn index 1d1d9d5d..6ce736c2 100644 --- a/client/server_scripts/openvpn/template.ovpn +++ b/client/server_scripts/openvpn/template.ovpn @@ -19,7 +19,7 @@ dhcp-option DNS $PRIMARY_DNS dhcp-option DNS $SECONDARY_DNS block-outside-dns -remote $REMOTE_HOST $REMOTE_PORT +remote $REMOTE_HOST $OPENVPN_PORT $OPENVPN_CA_CERT diff --git a/client/server_scripts/openvpn_cloak/run_container.sh b/client/server_scripts/openvpn_cloak/run_container.sh index be3dbad5..09486887 100644 --- a/client/server_scripts/openvpn_cloak/run_container.sh +++ b/client/server_scripts/openvpn_cloak/run_container.sh @@ -1,5 +1,5 @@ # Run container -sudo docker run -d --restart always --cap-add=NET_ADMIN -p $DOCKER_PORT:443/tcp --name $CONTAINER_NAME $CONTAINER_NAME +sudo docker run -d --restart always --cap-add=NET_ADMIN -p $CLOAK_SERVER_PORT:443/tcp --name $CONTAINER_NAME $CONTAINER_NAME # Create tun device if not exist sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi' diff --git a/client/server_scripts/openvpn_shadowsocks/template.ovpn b/client/server_scripts/openvpn_shadowsocks/template.ovpn index 5164c22d..76b755f6 100644 --- a/client/server_scripts/openvpn_shadowsocks/template.ovpn +++ b/client/server_scripts/openvpn_shadowsocks/template.ovpn @@ -21,7 +21,7 @@ block-outside-dns socks-proxy 127.0.0.1 $SHADOWSOCKS_LOCAL_PORT route $REMOTE_HOST 255.255.255.255 net_gateway -remote $REMOTE_HOST $REMOTE_PORT +remote $REMOTE_HOST $OPENVPN_PORT $OPENVPN_CA_CERT diff --git a/client/server_scripts/setup_host_firewall.sh b/client/server_scripts/setup_host_firewall.sh index 13c93324..605de511 100644 --- a/client/server_scripts/setup_host_firewall.sh +++ b/client/server_scripts/setup_host_firewall.sh @@ -2,12 +2,12 @@ sudo sysctl -w net.ipv4.ip_forward=1 sudo iptables -C INPUT -p icmp --icmp-type echo-request -j DROP || sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP #sudo iptables -P FORWARD ACCEPT -sudo iptables -A FORWARD -j DOCKER-USER -sudo iptables -A FORWARD -j DOCKER-ISOLATION-STAGE-1 -sudo iptables -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -sudo iptables -A FORWARD -o docker0 -j DOCKER -sudo iptables -A FORWARD -i docker0 ! -o docker0 -j ACCEPT -sudo iptables -A FORWARD -i docker0 -o docker0 -j ACCEPT +sudo iptables -C FORWARD -j DOCKER-USER || sudo iptables -A FORWARD -j DOCKER-USER +sudo iptables -C FORWARD -j DOCKER-ISOLATION-STAGE-1 || sudo iptables -A FORWARD -j DOCKER-ISOLATION-STAGE-1; \ +sudo iptables -C FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT || sudo iptables -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT; \ +sudo iptables -C FORWARD -o docker0 -j DOCKER || sudo iptables -A FORWARD -o docker0 -j DOCKER; \ +sudo iptables -C FORWARD -i docker0 ! -o docker0 -j ACCEPT || sudo iptables -A FORWARD -i docker0 ! -o docker0 -j ACCEPT; \ +sudo iptables -C FORWARD -i docker0 -o docker0 -j ACCEPT || sudo iptables -A FORWARD -i docker0 -o docker0 -j ACCEPT # Tuning network sudo sysctl fs.file-max=51200; \ diff --git a/client/settings.cpp b/client/settings.cpp index c38ee5e2..6b97ed9e 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -118,23 +118,12 @@ QJsonObject Settings::containerConfig(int serverIndex, DockerContainer container return containers(serverIndex).value(container); } -//QJsonObject Settings::containerConfig(int serverIndex, DockerContainer container) -//{ -// if (container == DockerContainer::None) return QJsonObject(); - -// const QJsonArray &containers = server(serverIndex).value(config_key::containers).toArray(); -// for (const QJsonValue &val : containers) { -// if (val.toObject().value(config_key::container).toString() == containerToString(container)) { -// return val.toObject(); -// } -// } -// return QJsonObject(); -//} - void Settings::setContainerConfig(int serverIndex, DockerContainer container, const QJsonObject &config) { - if (container == DockerContainer::None) return; - + if (container == DockerContainer::None) { + qCritical() << "Settings::setContainerConfig trying to set config for container == DockerContainer::None"; + return; + } auto c = containers(serverIndex); c[container] = config; c[container][config_key::container] = containerToString(container); @@ -143,30 +132,16 @@ void Settings::setContainerConfig(int serverIndex, DockerContainer container, co void Settings::removeContainerConfig(int serverIndex, DockerContainer container) { - if (container == DockerContainer::None) return; + if (container == DockerContainer::None) { + qCritical() << "Settings::removeContainerConfig trying to remove config for container == DockerContainer::None"; + return; + } auto c = containers(serverIndex); c.remove(container); setContainers(serverIndex, c); } -//void Settings::setContainerConfig(int serverIndex, DockerContainer container, const QJsonObject &config) -//{ -// if (container == DockerContainer::None) return; - -// QJsonObject s = server(serverIndex); -// QJsonArray c = s.value(config_key::containers).toArray(); -// for (int i = c.size() - 1; i >= 0; i--) { -// if (c.at(i).toObject().value(config_key::container).toString() == containerToString(container)) { -// c.removeAt(i); -// } -// } - -// c.append(config); -// s.insert(config_key::containers, c); -// editServer(serverIndex, s); -//} - QJsonObject Settings::protocolConfig(int serverIndex, DockerContainer container, Protocol proto) { const QJsonObject &c = containerConfig(serverIndex, container); @@ -193,7 +168,7 @@ void Settings::clearLastConnectionConfig(int serverIndex, DockerContainer contai QJsonObject c = protocolConfig(serverIndex, container, proto); c.remove(config_key::last_config); setProtocolConfig(serverIndex, container, proto, c); - qDebug() << "Settings::clearLastConnectionConfig for" << protoToString(proto); + qDebug() << "Settings::clearLastConnectionConfig for" << serverIndex << container << proto; } bool Settings::haveAuthData() const diff --git a/client/ui/mainwindow.cpp b/client/ui/mainwindow.cpp index 972feb0b..b21a6d58 100644 --- a/client/ui/mainwindow.cpp +++ b/client/ui/mainwindow.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -13,13 +14,19 @@ #include #include -#include -#include "core/errorstrings.h" +#include "configurators/vpn_configurator.h" #include "configurators/openvpn_configurator.h" +#include "configurators/shadowsocks_configurator.h" +#include "configurators/cloak_configurator.h" + #include "core/servercontroller.h" #include "core/server_defs.h" +#include "core/errorstrings.h" + #include "protocols/protocols_defs.h" +#include "protocols/shadowsocksvpnprotocol.h" + #include "ui/qautostart.h" #include "debug.h" @@ -52,6 +59,8 @@ MainWindow::MainWindow(QWidget *parent) : setupUiConnections(); setupProtocolsPageConnections(); setupNewServerPageConnections(); + setupSharePageConnections(); + setupServerSettingsPageConnections(); ui->label_error_text->clear(); installEventFilter(this); @@ -117,6 +126,7 @@ MainWindow::MainWindow(QWidget *parent) : m_ipAddressValidator.setRegExp(Utils::ipAddressRegExp()); m_ipAddressPortValidator.setRegExp(Utils::ipAddressPortRegExp()); m_ipNetwok24Validator.setRegExp(Utils::ipNetwork24RegExp()); + m_ipPortValidator.setRegExp(Utils::ipPortRegExp()); ui->lineEdit_new_server_ip->setValidator(&m_ipAddressPortValidator); ui->lineEdit_network_settings_dns1->setValidator(&m_ipAddressValidator); @@ -124,8 +134,12 @@ MainWindow::MainWindow(QWidget *parent) : ui->lineEdit_proto_openvpn_subnet->setValidator(&m_ipNetwok24Validator); - ui->toolBox_share_connection->removeItem(ui->toolBox_share_connection->indexOf(ui->page_share_shadowsocks)); - ui->page_share_shadowsocks->setVisible(false); + ui->lineEdit_proto_openvpn_port->setValidator(&m_ipPortValidator); + ui->lineEdit_proto_shadowsocks_port->setValidator(&m_ipPortValidator); + ui->lineEdit_proto_cloak_port->setValidator(&m_ipPortValidator); + + //ui->toolBox_share_connection->removeItem(ui->toolBox_share_connection->indexOf(ui->page_share_shadowsocks)); + //ui->page_share_shadowsocks->setVisible(false); } MainWindow::~MainWindow() @@ -155,22 +169,7 @@ void MainWindow::goToPage(Page page, bool reset, bool slide) updateServerPage(); } if (page == Page::ShareConnection) { -// QJsonObject ssConfig = ShadowSocksVpnProtocol::genShadowSocksConfig(m_settings.defaultServerCredentials()); -// QString ssString = QString("%1:%2@%3:%4") -// .arg(ssConfig.value("method").toString()) -// .arg(ssConfig.value("password").toString()) -// .arg(ssConfig.value("server").toString()) -// .arg(QString::number(ssConfig.value("server_port").toInt())); - -// ssString = "ss://" + ssString.toUtf8().toBase64(); -// ui->lineEdit_share_ss_string->setText(ssString); -// updateQRCodeImage(ssString, ui->label_share_ss_qr_code); - -// ui->label_share_ss_server->setText(ssConfig.value("server").toString()); -// ui->label_share_ss_port->setText(QString::number(ssConfig.value("server_port").toInt())); -// ui->label_share_ss_method->setText(ssConfig.value("method").toString()); -// ui->label_share_ss_password->setText(ssConfig.value("password").toString()); } if (page == Page::ServersList) { updateServersListPage(); @@ -281,14 +280,6 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) return false; } } - if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Escape && ! ui->stackedWidget_main->isAnimationRunning() ) { - if (currentPage() != Page::Vpn && currentPage() != Page::Start) { - closePage(); - } - } - } return QMainWindow::eventFilter(obj, event); } @@ -304,16 +295,30 @@ void MainWindow::keyPressEvent(QKeyEvent *event) #ifdef QT_DEBUG case Qt::Key_Q: qApp->quit(); + break; case Qt::Key_C: - qDebug().noquote() << QJsonDocument(m_settings.serversArray()).toJson(); + qDebug().noquote() << QJsonDocument(m_settings.containerConfig(m_settings.defaultServerIndex(), m_settings.defaultContainer(m_settings.defaultServerIndex()))).toJson(); + //qDebug().noquote() << QJsonDocument(m_settings.serversArray()).toJson(); break; #endif case Qt::Key_A: goToPage(Page::Start); break; case Qt::Key_S: + selectedServerIndex = m_settings.defaultServerIndex(); goToPage(Page::ServerSettings); break; + case Qt::Key_P: + selectedServerIndex = m_settings.defaultServerIndex(); + selectedDockerContainer = m_settings.defaultContainer(selectedServerIndex); + goToPage(Page::ServerVpnProtocols); + break; + case Qt::Key_Escape: + if (! ui->stackedWidget_main->isAnimationRunning() && ui->stackedWidget_main->currentWidget()->isEnabled()) { + if (currentPage() != Page::Vpn && currentPage() != Page::Start) { + closePage(); + } + } default: ; } @@ -654,16 +659,6 @@ ErrorCode MainWindow::doInstallAction(const std::function &action, return ErrorCode::NoError; } -void MainWindow::onPushButtonReinstallServer(bool) -{ -// onDisconnect(); -// installServer(m_settings.defaultServerCredentials(), -// ui->page_server_settings, -// ui->progressBar_server_settings_reinstall, -// ui->pushButton_server_settings_reinstall, -// ui->label_server_settings_wait_info); -} - void MainWindow::onPushButtonClearServer(bool) { ui->page_server_settings->setEnabled(false); @@ -697,8 +692,15 @@ void MainWindow::onPushButtonForgetServer(bool) onDisconnect(); } m_settings.removeServer(selectedServerIndex); - m_settings.setDefaultServer(0); + if (m_settings.defaultServerIndex() == selectedServerIndex) { + m_settings.setDefaultServer(0); + } + else if (m_settings.defaultServerIndex() > selectedServerIndex) { + m_settings.setDefaultServer(m_settings.defaultServerIndex() - 1); + } + + selectedServerIndex = -1; closePage(); updateServersListPage(); } @@ -849,9 +851,6 @@ void MainWindow::setupUiConnections() connect(ui->pushButton_new_server_connect_configure, SIGNAL(clicked(bool)), this, SLOT(onPushButtonNewServerConnectConfigure(bool))); connect(ui->pushButton_new_server_import, SIGNAL(clicked(bool)), this, SLOT(onPushButtonNewServerImport(bool))); - connect(ui->pushButton_server_settings_reinstall, SIGNAL(clicked(bool)), this, SLOT(onPushButtonReinstallServer(bool))); - connect(ui->pushButton_server_settings_clear, SIGNAL(clicked(bool)), this, SLOT(onPushButtonClearServer(bool))); - connect(ui->pushButton_server_settings_forget, SIGNAL(clicked(bool)), this, SLOT(onPushButtonForgetServer(bool))); connect(ui->pushButton_vpn_add_site, &QPushButton::clicked, this, [this](){ goToPage(Page::Sites); }); connect(ui->pushButton_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); }); @@ -861,21 +860,12 @@ void MainWindow::setupUiConnections() selectedServerIndex = m_settings.defaultServerIndex(); goToPage(Page::ServerSettings); }); - connect(ui->pushButton_server_settings_protocols, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerVpnProtocols); }); connect(ui->pushButton_servers_list, &QPushButton::clicked, this, [this](){ goToPage(Page::ServersList); }); connect(ui->pushButton_share_connection, &QPushButton::clicked, this, [this](){ goToPage(Page::ShareConnection); updateShareCodePage(); }); - connect(ui->pushButton_copy_sharing_code, &QPushButton::clicked, this, [this](){ - QGuiApplication::clipboard()->setText(ui->textEdit_sharing_code->toPlainText()); - ui->pushButton_copy_sharing_code->setText(tr("Copied")); - - QTimer::singleShot(3000, this, [this]() { - ui->pushButton_copy_sharing_code->setText(tr("Copy")); - }); - }); connect(ui->pushButton_back_from_sites, &QPushButton::clicked, this, [this](){ closePage(); }); connect(ui->pushButton_back_from_settings, &QPushButton::clicked, this, [this](){ closePage(); }); @@ -1014,43 +1004,64 @@ void MainWindow::setupProtocolsPageConnections() }); } + // share buttons + QList shareButtons { + ui->pushButton_proto_openvpn_cont_share, + ui->pushButton_proto_ss_openvpn_cont_share, + ui->pushButton_proto_cloak_openvpn_cont_share + }; + + for (int i = 0; i < containers.size(); ++i) { + QPushButton *button = shareButtons.at(i); + DockerContainer container = containers.at(i); + + connect(button, &QPushButton::clicked, this, [this, button, container](){ + updateSharingPage(selectedServerIndex, m_settings.serverCredentials(selectedServerIndex), container); + goToPage(Page::ShareConnection); + }); + } // settings buttons // settings openvpn container connect(ui->pushButton_proto_openvpn_cont_openvpn_config, &QPushButton::clicked, this, [this](){ - updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, DockerContainer::OpenVpn, Protocol::OpenVpn)); selectedDockerContainer = DockerContainer::OpenVpn; + updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::OpenVpn), + selectedDockerContainer); goToPage(Page::OpenVpnSettings); }); // settings shadowsocks container connect(ui->pushButton_proto_ss_openvpn_cont_openvpn_config, &QPushButton::clicked, this, [this](){ - updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, DockerContainer::OpenVpnOverShadowSocks, Protocol::OpenVpn), - DockerContainer::OpenVpnOverShadowSocks); selectedDockerContainer = DockerContainer::OpenVpnOverShadowSocks; + updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::OpenVpn), + selectedDockerContainer); goToPage(Page::OpenVpnSettings); }); connect(ui->pushButton_proto_ss_openvpn_cont_ss_config, &QPushButton::clicked, this, [this](){ - updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, DockerContainer::OpenVpnOverShadowSocks, Protocol::ShadowSocks)); selectedDockerContainer = DockerContainer::OpenVpnOverShadowSocks; + updateShadowSocksPage(m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::ShadowSocks), + selectedDockerContainer); goToPage(Page::ShadowSocksSettings); }); // settings cloak container connect(ui->pushButton_proto_cloak_openvpn_cont_openvpn_config, &QPushButton::clicked, this, [this](){ - updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, DockerContainer::OpenVpnOverCloak, Protocol::OpenVpn)); selectedDockerContainer = DockerContainer::OpenVpnOverCloak; + updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::OpenVpn), + selectedDockerContainer); goToPage(Page::OpenVpnSettings); }); connect(ui->pushButton_proto_cloak_openvpn_cont_ss_config, &QPushButton::clicked, this, [this](){ - updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, DockerContainer::OpenVpnOverCloak, Protocol::ShadowSocks)); selectedDockerContainer = DockerContainer::OpenVpnOverCloak; + updateShadowSocksPage(m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::ShadowSocks), + selectedDockerContainer); goToPage(Page::ShadowSocksSettings); }); connect(ui->pushButton_proto_cloak_openvpn_cont_cloak_config, &QPushButton::clicked, this, [this](){ - updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, DockerContainer::OpenVpnOverCloak, Protocol::Cloak)); selectedDockerContainer = DockerContainer::OpenVpnOverCloak; + updateCloakPage(m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::Cloak), + selectedDockerContainer); goToPage(Page::CloakSettings); }); @@ -1079,6 +1090,50 @@ void MainWindow::setupProtocolsPageConnections() m_settings.setContainerConfig(selectedServerIndex, selectedDockerContainer, newContainerConfig); m_settings.clearLastConnectionConfig(selectedServerIndex, selectedDockerContainer); } + qDebug() << "Protocol saved with code:" << e << "for" << selectedServerIndex << selectedDockerContainer; + }); + + connect(ui->pushButton_proto_shadowsocks_save, &QPushButton::clicked, this, [this](){ + QJsonObject protocolConfig = m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::ShadowSocks); + protocolConfig = getShadowSocksConfigFromPage(protocolConfig); + + QJsonObject containerConfig = m_settings.containerConfig(selectedServerIndex, selectedDockerContainer); + QJsonObject newContainerConfig = containerConfig; + newContainerConfig.insert(config_key::shadowsocks, protocolConfig); + + ErrorCode e = doInstallAction([this, containerConfig, newContainerConfig](){ + return ServerController::updateContainer(m_settings.serverCredentials(selectedServerIndex), selectedDockerContainer, containerConfig, newContainerConfig); + }, + ui->page_proto_shadowsocks, ui->progressBar_proto_shadowsocks_reset, + ui->pushButton_proto_shadowsocks_save, ui->label_proto_shadowsocks_info); + + if (!e) { + m_settings.setContainerConfig(selectedServerIndex, selectedDockerContainer, newContainerConfig); + m_settings.clearLastConnectionConfig(selectedServerIndex, selectedDockerContainer); + } + qDebug() << "Protocol saved with code:" << e << "for" << selectedServerIndex << selectedDockerContainer; + }); + + connect(ui->pushButton_proto_cloak_save, &QPushButton::clicked, this, [this](){ + QJsonObject protocolConfig = m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::Cloak); + protocolConfig = getCloakConfigFromPage(protocolConfig); + + QJsonObject containerConfig = m_settings.containerConfig(selectedServerIndex, selectedDockerContainer); + QJsonObject newContainerConfig = containerConfig; + newContainerConfig.insert(config_key::cloak, protocolConfig); + + ErrorCode e = doInstallAction([this, containerConfig, newContainerConfig](){ + return ServerController::updateContainer(m_settings.serverCredentials(selectedServerIndex), selectedDockerContainer, containerConfig, newContainerConfig); + }, + ui->page_proto_cloak, ui->progressBar_proto_cloak_reset, + ui->pushButton_proto_cloak_save, ui->label_proto_cloak_info); + + if (!e) { + m_settings.setContainerConfig(selectedServerIndex, selectedDockerContainer, newContainerConfig); + m_settings.clearLastConnectionConfig(selectedServerIndex, selectedDockerContainer); + } + + qDebug() << "Protocol saved with code:" << e << "for" << selectedServerIndex << selectedDockerContainer; }); } @@ -1127,6 +1182,137 @@ void MainWindow::setupNewServerPageConnections() }); } +void MainWindow::setupServerSettingsPageConnections() +{ + connect(ui->pushButton_server_settings_protocols, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerVpnProtocols); }); + + connect(ui->pushButton_server_settings_clear, SIGNAL(clicked(bool)), this, SLOT(onPushButtonClearServer(bool))); + connect(ui->pushButton_server_settings_forget, SIGNAL(clicked(bool)), this, SLOT(onPushButtonForgetServer(bool))); + + connect(ui->pushButton_server_settings_clear_client_cache, &QPushButton::clicked, this, [this](){ + ui->pushButton_server_settings_clear_client_cache->setText(tr("Cache cleared")); + + const auto &containers = m_settings.containers(selectedServerIndex); + for (DockerContainer container: containers.keys()) { + m_settings.clearLastConnectionConfig(selectedServerIndex, container); + } + + QTimer::singleShot(3000, this, [this]() { + ui->pushButton_server_settings_clear_client_cache->setText(tr("Clear client cached profile")); + }); + }); + +} + +void MainWindow::setupSharePageConnections() +{ + connect(ui->pushButton_share_full_copy, &QPushButton::clicked, this, [this](){ + QGuiApplication::clipboard()->setText(ui->textEdit_share_full_code->toPlainText()); + ui->pushButton_share_full_copy->setText(tr("Copied")); + + QTimer::singleShot(3000, this, [this]() { + ui->pushButton_share_full_copy->setText(tr("Copy")); + }); + }); + + connect(ui->pushButton_share_amnezia_copy, &QPushButton::clicked, this, [this](){ + QGuiApplication::clipboard()->setText(ui->textEdit_share_amnezia_code->toPlainText()); + ui->pushButton_share_amnezia_copy->setText(tr("Copied")); + + QTimer::singleShot(3000, this, [this]() { + ui->pushButton_share_amnezia_copy->setText(tr("Copy")); + }); + }); + + connect(ui->pushButton_share_openvpn_copy, &QPushButton::clicked, this, [this](){ + QGuiApplication::clipboard()->setText(ui->textEdit_share_openvpn_code->toPlainText()); + ui->pushButton_share_openvpn_copy->setText(tr("Copied")); + + QTimer::singleShot(3000, this, [this]() { + ui->pushButton_share_openvpn_copy->setText(tr("Copy")); + }); + }); + + connect(ui->pushButton_share_ss_copy, &QPushButton::clicked, this, [this](){ + QGuiApplication::clipboard()->setText(ui->lineEdit_share_ss_string->text()); + ui->pushButton_share_ss_copy->setText(tr("Copied")); + + QTimer::singleShot(3000, this, [this]() { + ui->pushButton_share_ss_copy->setText(tr("Copy")); + }); + }); + +// connect(ui->pushButton_share_cloak_copy, &QPushButton::clicked, this, [this](){ +// QGuiApplication::clipboard()->setText(ui->textEdit_share_openvpn_code->toPlainText()); +// ui->pushButton_share_cloak_copy->setText(tr("Copied")); + +// QTimer::singleShot(3000, this, [this]() { +// ui->pushButton_share_cloak_copy->setText(tr("Copy")); +// }); +// }); + + connect(ui->pushButton_share_amnezia_generate, &QPushButton::clicked, this, [this](){ + ui->pushButton_share_amnezia_generate->setEnabled(false); + ui->pushButton_share_amnezia_copy->setEnabled(false); + ui->pushButton_share_amnezia_generate->setText(tr("Generating...")); + qApp->processEvents(); + + ServerCredentials credentials = m_settings.serverCredentials(selectedServerIndex); + QJsonObject containerConfig; // = m_settings.containerConfig(selectedServerIndex, selectedDockerContainer); + containerConfig.insert(config_key::container, containerToString(selectedDockerContainer)); + + for (Protocol p: amnezia::protocolsForContainer(selectedDockerContainer)) { + QJsonObject protoConfig = m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, p); + + ErrorCode e = ErrorCode::NoError; + QString cfg = VpnConfigurator::genVpnProtocolConfig(credentials, selectedDockerContainer, containerConfig, p, &e); + if (e) { + cfg = "Error generating config"; + break; + } + protoConfig.insert(config_key::last_config, cfg); + + containerConfig.insert(protoToString(p), protoConfig); + } + + QJsonObject serverConfig = m_settings.server(selectedServerIndex); + serverConfig.remove(config_key::userName); + serverConfig.remove(config_key::password); + serverConfig.remove(config_key::port); + serverConfig.insert(config_key::containers, QJsonArray {containerConfig}); + serverConfig.insert(config_key::defaultContainer, containerToString(selectedDockerContainer)); + + + ui->textEdit_share_amnezia_code->setPlainText(QJsonDocument(serverConfig).toJson()); + + ui->pushButton_share_amnezia_generate->setEnabled(true); + ui->pushButton_share_amnezia_copy->setEnabled(true); + ui->pushButton_share_amnezia_generate->setText(tr("Generate config")); + }); + + connect(ui->pushButton_share_openvpn_generate, &QPushButton::clicked, this, [this](){ + ServerCredentials credentials = m_settings.serverCredentials(selectedServerIndex); + const QJsonObject &containerConfig = m_settings.containerConfig(selectedServerIndex, selectedDockerContainer); + ui->pushButton_share_openvpn_copy->setEnabled(false); + ui->pushButton_share_openvpn_save->setEnabled(false); + + ErrorCode e = ErrorCode::NoError; + QString cfg = OpenVpnConfigurator::genOpenVpnConfig(credentials, selectedDockerContainer, containerConfig, &e); + + ui->textEdit_share_openvpn_code->setPlainText(cfg); + ui->pushButton_share_openvpn_copy->setEnabled(true); + ui->pushButton_share_openvpn_save->setEnabled(true); + }); + + connect(ui->pushButton_share_openvpn_save, &QPushButton::clicked, this, [this](){ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save OpenVPN config"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.ovpn"); + QSaveFile save(fileName); + save.open(QIODevice::WriteOnly); + save.write(ui->textEdit_share_openvpn_code->toPlainText().toUtf8()); + save.commit(); + }); +} + void MainWindow::setTrayState(VpnProtocol::ConnectionState state) { QString resourcesPath = ":/images/tray/%1"; @@ -1224,7 +1410,6 @@ void MainWindow::onTrayActionConnect() } } - void MainWindow::onPushButtonAddCustomSitesClicked() { QString newSite = ui->lineEdit_sites_add_custom->text(); @@ -1428,6 +1613,115 @@ void MainWindow::updateOpenVpnPage(const QJsonObject &openvpnConfig, DockerConta ui->radioButton_proto_openvpn_tcp->setEnabled(false); ui->radioButton_proto_openvpn_tcp->setChecked(true); } + + ui->lineEdit_proto_openvpn_port->setText(openvpnConfig.value(config_key::port). + toString(protocols::openvpn::defaultPort)); + + ui->lineEdit_proto_openvpn_port->setEnabled(container == DockerContainer::OpenVpn); +} + +void MainWindow::updateShadowSocksPage(const QJsonObject &ssConfig, DockerContainer container) +{ + ui->comboBox_proto_shadowsocks_cipher->setCurrentText(ssConfig.value(config_key::cipher). + toString(protocols::shadowsocks::defaultCipher)); + + ui->lineEdit_proto_shadowsocks_port->setText(ssConfig.value(config_key::port). + toString(protocols::shadowsocks::defaultPort)); + + ui->lineEdit_proto_shadowsocks_port->setEnabled(container == DockerContainer::OpenVpnOverShadowSocks); +} + +void MainWindow::updateCloakPage(const QJsonObject &ckConfig, DockerContainer container) +{ + ui->comboBox_proto_cloak_cipher->setCurrentText(ckConfig.value(config_key::cipher). + toString(protocols::cloak::defaultCipher)); + + ui->lineEdit_proto_cloak_site->setText(ckConfig.value(config_key::site). + toString(protocols::cloak::defaultRedirSite)); + + ui->lineEdit_proto_cloak_port->setText(ckConfig.value(config_key::port). + toString(protocols::cloak::defaultPort)); + + ui->lineEdit_proto_cloak_port->setEnabled(container == DockerContainer::OpenVpnOverCloak); +} + +void MainWindow::updateSharingPage(int serverIndex, const ServerCredentials &credentials, + DockerContainer container) +{ + selectedDockerContainer = container; + selectedServerIndex = serverIndex; + + const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container); + + for (QWidget *page : { ui->page_share_openvpn, + ui->page_share_shadowsocks, + ui->page_share_cloak, + ui->page_share_full_access }) { + + ui->toolBox_share_connection->removeItem(ui->toolBox_share_connection->indexOf(page)); + page->hide(); + } + + if (container == DockerContainer::OpenVpn) { + ui->toolBox_share_connection->addItem(ui->page_share_openvpn, tr(" Share for OpenVPN client")); + + QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Protocol::OpenVpn); + QString cfg = protoConfig.value(config_key::last_config).toString(); + if (!cfg.isEmpty()) { + // TODO add redirect-gateway def1 bypass-dhcp here and on click Generate config + ui->textEdit_share_openvpn_code->setPlainText(cfg); + } + else { + cfg = tr("Press Generate config"); + ui->textEdit_share_openvpn_code->setPlainText(cfg); + ui->pushButton_share_openvpn_copy->setEnabled(false); + ui->pushButton_share_openvpn_save->setEnabled(false); + } + } + + if (container == DockerContainer::OpenVpnOverShadowSocks) { + ui->toolBox_share_connection->addItem(ui->page_share_shadowsocks, tr(" Share for ShadowSocks client")); + + QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Protocol::ShadowSocks); + QString cfg = protoConfig.value(config_key::last_config).toString(); + + if (cfg.isEmpty()) { + const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container); + + ErrorCode e = ErrorCode::NoError; + cfg = ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, &e); + + ui->pushButton_share_ss_copy->setEnabled(true); + } + + QJsonObject ssConfig = QJsonDocument::fromJson(cfg.toUtf8()).object(); + + QString ssString = QString("%1:%2@%3:%4") + .arg(ssConfig.value("method").toString()) + .arg(ssConfig.value("password").toString()) + .arg(ssConfig.value("server").toString()) + .arg(ssConfig.value("server_port").toString()); + + ssString = "ss://" + ssString.toUtf8().toBase64(); + ui->lineEdit_share_ss_string->setText(ssString); + updateQRCodeImage(ssString, ui->label_share_ss_qr_code); + + ui->label_share_ss_server->setText(ssConfig.value("server").toString()); + ui->label_share_ss_port->setText(ssConfig.value("server_port").toString()); + ui->label_share_ss_method->setText(ssConfig.value("method").toString()); + ui->label_share_ss_password->setText(ssConfig.value("password").toString()); + } + + // Amnezia sharing + QJsonObject exportContainer; + for (Protocol p: protocolsForContainer(container)) { + QJsonObject protocolConfig = containerConfig.value(protoToString(p)).toObject(); + protocolConfig.remove(config_key::last_config); + exportContainer.insert(protoToString(p), protocolConfig); + } + exportContainer.insert(config_key::container, containerToString(container)); + + ui->textEdit_share_amnezia_code->setPlainText(QJsonDocument(exportContainer).toJson()); } void MainWindow::makeSitesListItem(QListWidget *listWidget, const QString &address) @@ -1472,10 +1766,10 @@ void MainWindow::makeServersListItem(QListWidget *listWidget, const QJsonObject updateServersListPage(); }); - connect(widget->ui->pushButton_share, &QPushButton::clicked, this, [this, index](){ - goToPage(Page::ShareConnection); - // update share page - }); +// connect(widget->ui->pushButton_share, &QPushButton::clicked, this, [this, index](){ +// goToPage(Page::ShareConnection); +// // update share page +// }); connect(widget->ui->pushButton_settings, &QPushButton::clicked, this, [this, index](){ selectedServerIndex = index; @@ -1521,6 +1815,24 @@ QJsonObject MainWindow::getOpenVpnConfigFromPage(QJsonObject oldConfig) oldConfig.insert(config_key::cipher, ui->comboBox_proto_openvpn_cipher->currentText()); oldConfig.insert(config_key::hash, ui->comboBox_proto_openvpn_hash->currentText()); oldConfig.insert(config_key::block_outside_dns, ui->checkBox_proto_openvpn_block_dns->isChecked()); + oldConfig.insert(config_key::port, ui->lineEdit_proto_openvpn_port->text()); + + return oldConfig; +} + +QJsonObject MainWindow::getShadowSocksConfigFromPage(QJsonObject oldConfig) +{ + oldConfig.insert(config_key::cipher, ui->comboBox_proto_shadowsocks_cipher->currentText()); + oldConfig.insert(config_key::port, ui->lineEdit_proto_shadowsocks_port->text()); + + return oldConfig; +} + +QJsonObject MainWindow::getCloakConfigFromPage(QJsonObject oldConfig) +{ + oldConfig.insert(config_key::cipher, ui->comboBox_proto_cloak_cipher->currentText()); + oldConfig.insert(config_key::site, ui->lineEdit_proto_cloak_site->text()); + oldConfig.insert(config_key::port, ui->lineEdit_proto_cloak_port->text()); return oldConfig; } diff --git a/client/ui/mainwindow.h b/client/ui/mainwindow.h index c497280c..b1b97da9 100644 --- a/client/ui/mainwindow.h +++ b/client/ui/mainwindow.h @@ -55,7 +55,6 @@ private slots: void onPushButtonNewServerConnectConfigure(bool); void onPushButtonNewServerImport(bool); - void onPushButtonReinstallServer(bool); void onPushButtonClearServer(bool); void onPushButtonForgetServer(bool); @@ -90,6 +89,8 @@ private: void setupUiConnections(); void setupProtocolsPageConnections(); void setupNewServerPageConnections(); + void setupServerSettingsPageConnections(); + void setupSharePageConnections(); void updateSettings(); @@ -100,7 +101,12 @@ private: void updateServersListPage(); void updateProtocolsPage(); void updateShareCodePage(); - void updateOpenVpnPage(const QJsonObject &openvpnConfig, DockerContainer container = DockerContainer::None); + void updateOpenVpnPage(const QJsonObject &openvpnConfig, DockerContainer container); + void updateShadowSocksPage(const QJsonObject &ssConfig, DockerContainer container); + void updateCloakPage(const QJsonObject &ckConfig, DockerContainer container); + + void updateSharingPage(int serverIndex, const ServerCredentials &credentials, + DockerContainer container); void makeSitesListItem(QListWidget* listWidget, const QString &address); void makeServersListItem(QListWidget* listWidget, const QJsonObject &server, bool isDefault, int index); @@ -108,6 +114,8 @@ private: void updateQRCodeImage(const QString &text, QLabel *label); QJsonObject getOpenVpnConfigFromPage(QJsonObject oldConfig); + QJsonObject getShadowSocksConfigFromPage(QJsonObject oldConfig); + QJsonObject getCloakConfigFromPage(QJsonObject oldConfig); private: Ui::MainWindow *ui; @@ -123,6 +131,7 @@ private: QRegExpValidator m_ipAddressValidator; QRegExpValidator m_ipAddressPortValidator; QRegExpValidator m_ipNetwok24Validator; + QRegExpValidator m_ipPortValidator; CQR_Encode m_qrEncode; diff --git a/client/ui/mainwindow.ui b/client/ui/mainwindow.ui index 16f9b7af..44033597 100644 --- a/client/ui/mainwindow.ui +++ b/client/ui/mainwindow.ui @@ -287,7 +287,7 @@ QPushButton:hover { - 14 + 11 @@ -1206,6 +1206,16 @@ border: none; + + + chacha20-ietf-poly1305 + + + + + xchacha20-ietf-poly1305 + + aes-256-gcm @@ -1221,16 +1231,6 @@ border: none; aes-128-gcm - - - chacha20-ietf-poly1305 - - - - - xchacha20-ietf-poly1305 - - @@ -2984,7 +2984,7 @@ padding:0px; true - + 40 @@ -3015,7 +3015,7 @@ background: #211966; } - Reinstall Amnezia server + Clear client cached profile @@ -3078,50 +3078,6 @@ color: #100A44; true - - - - 40 - 350 - 300 - 40 - - - - QProgressBar{ -color:rgb(212, 212, 212); -border-radius: 4px; - -font-family: Lato; -font-style: normal; -font-weight: normal; -font-size: 16px; -line-height: 21px; - -background: #100A44; -border-radius: 4px; -} - -QProgressBar::chunk { -background: rgba(255, 255, 255, 0.15); -border-radius: 4px 0px 0px 4px; - -} - - - - 24 - - - Qt::AlignCenter - - - true - - - Configuring... - - @@ -3322,9 +3278,8 @@ font-size: 20px; label_server_settings_wait_info label_16 - progressBar_server_settings_reinstall label_17 - pushButton_server_settings_reinstall + pushButton_server_settings_clear_client_cache pushButton_server_settings_clear pushButton_server_settings_forget label_server_settings_server @@ -4144,8 +4099,7 @@ background: transparent; } QToolBox > QWidget { - font: 25px "Lato"; - +font: 25px "Lato"; background: transparent; border-radius: 5px; @@ -4163,7 +4117,7 @@ border-radius: 2px; font-family: Lato; font-style: normal; font-weight: bold; -font-size: 23px; +font-size: 18px; color: #100A44; image: url(:/images/share.png); image-position: left; @@ -4188,15 +4142,15 @@ QToolBox::tab:hover { 1 - 2 + 6 - + 0 0 360 - 500 + 360 @@ -4205,12 +4159,12 @@ QToolBox::tab:hover { Full access - + 10 10 - 330 + 341 100 @@ -4255,7 +4209,7 @@ p, li { white-space: pre-wrap; } 10 180 - 321 + 341 111 @@ -4275,18 +4229,18 @@ This code includes your server credentials! Provide this code only to TRUSTED users. - Qt::AlignJustify|Qt::AlignVCenter + Qt::AlignJustify|Qt::AlignTop true - + 10 130 - 331 + 341 40 @@ -4318,20 +4272,346 @@ background: #282932; + + + + 0 + 0 + 360 + 360 + + + + Share for Amnezia client + + + + + 10 + 10 + 341 + 100 + + + + QTextEdit { + +background: #F5F5F5; +border-radius: 10px; + + +font-family: Consolas; +font-style: normal; +font-weight: bold; +font-size: 20px; + +text-align: center; + +color: #15CDCB; + +} + + + + QTextEdit::FixedColumnWidth + + + 30 + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Consolas'; font-size:20px; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:20pt;">vpn:\\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</span></p></body></html> + + + + + + 10 + 230 + 341 + 81 + + + + font-family: Lato; +font-style: normal; +font-weight: normal; +font-size: 16px; +line-height: 150%; + +color: #181922; + + + + Anyone who logs in with this code will be able to connect to this VPN server. +This code does not include server credentials. + + + Qt::AlignJustify|Qt::AlignTop + + + true + + + + + + 10 + 180 + 341 + 40 + + + + PointingHandCursor + + + QPushButton { + font-size: 13pt; + font: "Open Sans Semibold"; + color:rgb(212, 212, 212); + +background: #181922; +border-radius: 4px; + +font-family: Lato; +font-style: normal; +font-weight: normal; +font-size: 16px; +line-height: 21px; + +} +QPushButton:hover { +background: #282932; +} + + + Copy + + + + + + 10 + 130 + 341 + 40 + + + + PointingHandCursor + + + QPushButton { + font-size: 13pt; + font: "Open Sans Semibold"; + color:rgb(212, 212, 212); + +background: #181922; +border-radius: 4px; + +font-family: Lato; +font-style: normal; +font-weight: normal; +font-size: 16px; +line-height: 21px; + +} +QPushButton:hover { +background: #282932; +} + + + Generate config + + + + + + + 0 + 0 + 360 + 360 + + + + Share for OpenVPN client + + + + + 10 + 10 + 341 + 100 + + + + QTextEdit { + +background: #F5F5F5; +border-radius: 10px; + + +font-family: Consolas; +font-style: normal; +font-weight: bold; +font-size: 20px; + +text-align: center; + +color: #15CDCB; + +} + + + + QTextEdit::FixedColumnWidth + + + 30 + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Consolas'; font-size:20px; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:20pt;">vpn:\\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</span></p></body></html> + + + + + + 10 + 180 + 341 + 40 + + + + PointingHandCursor + + + QPushButton { + font-size: 13pt; + font: "Open Sans Semibold"; + color:rgb(212, 212, 212); + +background: #181922; +border-radius: 4px; + +font-family: Lato; +font-style: normal; +font-weight: normal; +font-size: 16px; +line-height: 21px; + +} +QPushButton:hover { +background: #282932; +} + + + Copy + + + + + + 10 + 230 + 341 + 40 + + + + PointingHandCursor + + + QPushButton { + font-size: 13pt; + font: "Open Sans Semibold"; + color:rgb(212, 212, 212); + +background: #181922; +border-radius: 4px; + +font-family: Lato; +font-style: normal; +font-weight: normal; +font-size: 16px; +line-height: 21px; + +} +QPushButton:hover { +background: #282932; +} + + + Save file + + + + + + 10 + 130 + 341 + 40 + + + + PointingHandCursor + + + QPushButton { + font-size: 13pt; + font: "Open Sans Semibold"; + color:rgb(212, 212, 212); + +background: #181922; +border-radius: 4px; + +font-family: Lato; +font-style: normal; +font-weight: normal; +font-size: 16px; +line-height: 21px; + +} +QPushButton:hover { +background: #282932; +} + + + Generate config + + + 0 0 360 - 500 + 360 - ShadowSocks + Share for ShadowSocks client @@ -4462,7 +4742,7 @@ background: #282932; Connection string - + 10 @@ -4542,6 +4822,19 @@ color: #15CDCB; + + + + 0 + 0 + 360 + 360 + + + + Share for Cloak client + + @@ -4644,7 +4937,7 @@ QPushButton:hover { 30 - 330 + 380 151 31 @@ -4694,6 +4987,11 @@ QPushButton:hover { CAMELLIA-256-CBC + + + none + + @@ -4702,7 +5000,7 @@ QPushButton:hover { 30 - 300 + 350 151 21 @@ -4718,7 +5016,7 @@ QPushButton:hover { 200 - 330 + 380 151 31 @@ -4776,7 +5074,7 @@ QPushButton:hover { 200 - 300 + 350 151 21 @@ -4792,7 +5090,7 @@ QPushButton:hover { 30 - 390 + 440 321 21 @@ -4807,9 +5105,9 @@ QPushButton:hover { - 40 + 30 530 - 300 + 311 40 @@ -4911,7 +5209,7 @@ background: #211966; 30 - 270 + 320 321 21 @@ -4926,9 +5224,9 @@ background: #211966; - 40 + 30 530 - 301 + 311 40 @@ -4989,6 +5287,41 @@ border-radius: 4px 0px 0px 4px; true + + + + 200 + 260 + 151 + 31 + + + + + + + + + + + + true + + + + 30 + 260 + 151 + 31 + + + + Port + + + true + + progressBar_proto_openvpn_reset label_38 pushButton_back_from_openvpn_settings @@ -5004,6 +5337,8 @@ border-radius: 4px 0px 0px 4px; frame_3 checkBox_proto_openvpn_auto_encryption label_proto_openvpn_info + lineEdit_proto_openvpn_port + label_103 @@ -5090,33 +5425,13 @@ QPushButton:hover { aes-128-gcm - - - aes-256-cfb - - - - - aes-128-cfb - - - - - chacha20 - - - - - chacha20-ietf - - - 40 + 30 530 - 301 + 311 40 @@ -5158,9 +5473,9 @@ border-radius: 4px 0px 0px 4px; - 40 + 30 530 - 300 + 311 40 @@ -5230,6 +5545,41 @@ background: #211966; true + + + + 190 + 130 + 151 + 31 + + + + + + + + + + + + true + + + + 30 + 130 + 151 + 31 + + + + Port + + + true + + @@ -5251,7 +5601,7 @@ color: #100A44; - OpenVPN Settings + Cloak Settings Qt::AlignCenter @@ -5311,6 +5661,11 @@ QPushButton:hover { aes-256-gcm + + + aes-192-gcm + + aes-128-gcm @@ -5344,9 +5699,9 @@ QPushButton:hover { - 40 + 30 530 - 301 + 311 40 @@ -5410,9 +5765,9 @@ border-radius: 4px 0px 0px 4px; - 40 + 30 530 - 300 + 311 40 @@ -5441,6 +5796,82 @@ background: #211966; Save and restart VPN + + + + 30 + 130 + 130 + 31 + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + Fake Web Site + + + + + + 190 + 180 + 151 + 31 + + + + + + + + + + + + true + + + + 30 + 180 + 151 + 31 + + + + Port + + + true + + + + + + 190 + 130 + 151 + 31 + + + + + + + mail.ru + + diff --git a/client/ui/server_widget.cpp b/client/ui/server_widget.cpp index 647568af..9b61aa8e 100644 --- a/client/ui/server_widget.cpp +++ b/client/ui/server_widget.cpp @@ -9,6 +9,19 @@ ServerWidget::ServerWidget(const QJsonObject &server, bool isDefault, QWidget *p ui(new Ui::ServerWidget) { ui->setupUi(this); + ui->pushButton_connect->hide(); + ui->pushButton_share->hide(); + + //ui->pushButton_settings->hide();\\ + + ui->pushButton_settings->setGraphicsEffect(&eff); + animation.setTargetObject(&eff); + animation.setPropertyName("opacity"); + animation.setDuration(150); + animation.setEasingCurve(QEasingCurve::InOutQuad); + + eff.setOpacity(0); + QString desc = server.value(config_key::description).toString(); QString address = server.value(config_key::hostName).toString(); @@ -29,3 +42,20 @@ ServerWidget::~ServerWidget() { delete ui; } + +void ServerWidget::enterEvent(QEvent *e) +{ + animation.setStartValue(0); + animation.setEndValue(1); + + animation.start(); +} + +void ServerWidget::leaveEvent(QEvent *e) +{ + animation.setStartValue(1); + animation.setEndValue(0); + + animation.start(); +} + diff --git a/client/ui/server_widget.h b/client/ui/server_widget.h index dd529979..5b7c68b3 100644 --- a/client/ui/server_widget.h +++ b/client/ui/server_widget.h @@ -4,6 +4,9 @@ #include #include +#include +#include + namespace Ui { class ServerWidget; } @@ -16,7 +19,12 @@ public: explicit ServerWidget(const QJsonObject &server, bool isDefault, QWidget *parent = nullptr); ~ServerWidget(); Ui::ServerWidget *ui; +private: + void enterEvent(QEvent *e) override; + void leaveEvent(QEvent *e) override; + QPropertyAnimation animation; + QGraphicsOpacityEffect eff; }; #endif // SERVER_WIDGET_H diff --git a/client/ui/server_widget.ui b/client/ui/server_widget.ui index 69779f9a..e819216f 100644 --- a/client/ui/server_widget.ui +++ b/client/ui/server_widget.ui @@ -84,7 +84,7 @@ QPushButton:!checked { - 260 + 170 25 24 24 @@ -139,7 +139,7 @@ QPushButton:!checked { - 174 + 260 25 24 24 diff --git a/client/utils.h b/client/utils.h index 84031707..b4b4b425 100644 --- a/client/utils.h +++ b/client/utils.h @@ -30,6 +30,8 @@ public: static QRegExp ipNetwork24RegExp() { return QRegExp("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}" "0$"); } + static QRegExp ipPortRegExp() { return QRegExp("^()([1-9]|[1-5]?[0-9]{2,4}|6[1-4][0-9]{3}|65[1-4][0-9]{2}|655[1-2][0-9]|6553[1-5])$"); } + static bool processIsRunning(const QString& fileName); static void killProcessByName(const QString &name); diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 0b222132..79c063d2 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -105,10 +105,11 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex, QString configData; if (lastVpnConfig.contains(proto)) { - configData = lastVpnConfig.value(proto); - qDebug() << "VpnConnection::createVpnConfiguration using saved config for " << protoToString(proto); + configData = OpenVpnConfigurator::processConfigWithLocalSettings(lastVpnConfig.value(proto)); + qDebug() << "VpnConnection::createVpnConfiguration: using saved config for" << protoToString(proto); } else { + qDebug() << "VpnConnection::createVpnConfiguration: gen new config for" << protoToString(proto); if (proto == Protocol::OpenVpn) { configData = OpenVpnConfigurator::genOpenVpnConfig(credentials, container, containerConfig, &e); @@ -129,6 +130,7 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex, if (serverIndex >= 0) { + qDebug() << "VpnConnection::createVpnConfiguration: saving config for server #" << serverIndex << container << proto; QJsonObject protoObject = m_settings.protocolConfig(serverIndex, container, proto); protoObject.insert(config_key::last_config, configData); m_settings.setProtocolConfig(serverIndex, container, proto, protoObject); @@ -197,6 +199,8 @@ ErrorCode VpnConnection::connectToVpn(int serverIndex, const ServerCredentials & emit connectionStateChanged(VpnProtocol::ConnectionState::Connecting); + ServerController::setupServerFirewall(credentials); + if (m_vpnProtocol) { disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError); m_vpnProtocol->stop();