diff --git a/client/configurators/cloak_configurator.cpp b/client/configurators/cloak_configurator.cpp index dddec337d..fb7da82da 100644 --- a/client/configurators/cloak_configurator.cpp +++ b/client/configurators/cloak_configurator.cpp @@ -14,11 +14,11 @@ QJsonObject CloakConfigurator::genCloakConfig(const ServerCredentials &credentia DockerContainer container = amnezia::containerForProto(proto); QString cloakPublicKey = ServerController::getTextFileFromContainer(container, credentials, - amnezia::protocols::cloak::ckPublicKeyPath(), &e); + amnezia::protocols::cloak::ckPublicKeyPath, &e); cloakPublicKey.replace("\n", ""); QString cloakBypassUid = ServerController::getTextFileFromContainer(container, credentials, - amnezia::protocols::cloak::ckBypassUidKeyPath(), &e); + amnezia::protocols::cloak::ckBypassUidKeyPath, &e); cloakBypassUid.replace("\n", ""); if (e) { @@ -32,7 +32,7 @@ QJsonObject CloakConfigurator::genCloakConfig(const ServerCredentials &credentia config.insert("EncryptionMethod", "aes-gcm"); config.insert("UID", cloakBypassUid); config.insert("PublicKey", cloakPublicKey); - config.insert("ServerName", amnezia::protocols::cloak::ckDefaultRedirSite()); + config.insert("ServerName", amnezia::protocols::cloak::ckDefaultRedirSite); config.insert("NumConn", 4); config.insert("BrowserSig", "chrome"); config.insert("StreamTimeout", 300); diff --git a/client/configurators/openvpn_configurator.cpp b/client/configurators/openvpn_configurator.cpp index 89cf2c6d0..752dbefd6 100644 --- a/client/configurators/openvpn_configurator.cpp +++ b/client/configurators/openvpn_configurator.cpp @@ -150,7 +150,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co } QString reqFileName = QString("%1/%2.req"). - arg(amnezia::protocols::openvpn::clientsDirPath()). + arg(amnezia::protocols::openvpn::clientsDirPath). arg(connData.clientId); DockerContainer container = amnezia::containerForProto(proto); @@ -167,16 +167,16 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co return connData; } - connData.caCert = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::caCertPath(), &e); + connData.caCert = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::caCertPath, &e); connData.clientCert = ServerController::getTextFileFromContainer(container, credentials, - QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath()).arg(connData.clientId), &e); + QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), &e); if (e) { if (errorCode) *errorCode = e; return connData; } - connData.taKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath(), &e); + connData.taKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath, &e); if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) { if (errorCode) *errorCode = ErrorCode::RemoteProcessCrashError; @@ -217,7 +217,7 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia config.replace("$PROTO", "udp"); else if (proto == Protocol::ShadowSocksOverOpenVpn) { config.replace("$PROTO", "tcp"); - config.replace("$LOCAL_PROXY_PORT", QString::number(amnezia::protocols::shadowsocks::ssContainerPort())); + config.replace("$LOCAL_PROXY_PORT", amnezia::protocols::shadowsocks::ssLocalProxyPort); } else if (proto == Protocol::OpenVpnOverCloak) { config.replace("$PROTO", "tcp"); @@ -231,7 +231,7 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia } config.replace("$REMOTE_HOST", connData.host); - config.replace("$REMOTE_PORT", amnezia::protocols::openvpn::openvpnDefaultPort()); + config.replace("$REMOTE_PORT", amnezia::protocols::openvpn::openvpnDefaultPort); config.replace("$CA_CERT", connData.caCert); config.replace("$CLIENT_CERT", connData.clientCert); config.replace("$PRIV_KEY", connData.privKey); @@ -284,7 +284,7 @@ ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, QString script_import = QString("sudo docker exec -i %1 bash -c \"cd /opt/amnezia/openvpn && " "easyrsa import-req %2/%3.req %3\"") .arg(amnezia::server::getContainerName(container)) - .arg(amnezia::protocols::openvpn::clientsDirPath()) + .arg(amnezia::protocols::openvpn::clientsDirPath) .arg(clientId); QString script_sign = QString("sudo docker exec -i %1 bash -c \"export EASYRSA_BATCH=1; cd /opt/amnezia/openvpn && " diff --git a/client/core/scripts_registry.cpp b/client/core/scripts_registry.cpp index dc01a44ee..e73996c29 100644 --- a/client/core/scripts_registry.cpp +++ b/client/core/scripts_registry.cpp @@ -21,7 +21,10 @@ QString amnezia::scriptName(SharedScriptType type) case SharedScriptType::prepare_host: return QLatin1String("prepare_host.sh"); case SharedScriptType::install_docker: return QLatin1String("install_docker.sh"); case SharedScriptType::build_container: return QLatin1String("build_container.sh"); + case SharedScriptType::remove_container: return QLatin1String("remove_container.sh"); + case SharedScriptType::remove_all_containers: return QLatin1String("remove_all_containers.sh"); case SharedScriptType::setup_host_firewall: return QLatin1String("setup_host_firewall.sh"); + case SharedScriptType::check_connection: return QLatin1String("check_connection.sh"); } } diff --git a/client/core/scripts_registry.h b/client/core/scripts_registry.h index a59f9cbb0..57755e5b8 100644 --- a/client/core/scripts_registry.h +++ b/client/core/scripts_registry.h @@ -11,7 +11,10 @@ enum SharedScriptType { prepare_host, install_docker, build_container, + remove_container, + remove_all_containers, setup_host_firewall, + check_connection }; enum ProtocolScriptType { // Protocol scripts diff --git a/client/core/server_defs.h b/client/core/server_defs.h index 99865a02f..3e767cbd9 100644 --- a/client/core/server_defs.h +++ b/client/core/server_defs.h @@ -9,10 +9,6 @@ namespace server { QString getContainerName(amnezia::DockerContainer container); QString getDockerfileFolder(amnezia::DockerContainer container); -const char vpnDefaultSubnetIp[] = "10.8.0.0"; -const char vpnDefaultSubnetMask[] = "255.255.255.0"; -const char vpnDefaultSubnetMaskVal[] = "24"; - } } diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index ce4f8dd96..a7d5b3627 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -27,7 +27,12 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams, const std::function)> &cbReadStdErr) { SshConnection *client = connectToHost(sshParams); - if (client->state() != SshConnection::State::Connected) { + if (client->state() == SshConnection::State::Connecting) { + qDebug() << "ServerController::runScript aborted, connectToHost in progress"; + return ErrorCode::SshTimeoutError; + } + else if (client->state() != SshConnection::State::Connected) { + qDebug() << "ServerController::runScript connectToHost error: " << fromSshConnectionErrorCode(client->errorState()); return fromSshConnectionErrorCode(client->errorState()); } @@ -260,9 +265,9 @@ QString ServerController::getTextFileFromContainer(DockerContainer container, ErrorCode ServerController::checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials) { QString caCert = ServerController::getTextFileFromContainer(container, - credentials, amnezia::protocols::openvpn::caCertPath()); + credentials, amnezia::protocols::openvpn::caCertPath); QString taKey = ServerController::getTextFileFromContainer(container, - credentials, amnezia::protocols::openvpn::taKeyPath()); + credentials, amnezia::protocols::openvpn::taKeyPath); if (!caCert.isEmpty() && !taKey.isEmpty()) { return ErrorCode::NoError; @@ -382,66 +387,42 @@ SshConnectionParameters ServerController::sshParams(const ServerCredentials &cre return sshParams; } -ErrorCode ServerController::removeServer(const ServerCredentials &credentials, Protocol proto) +ErrorCode ServerController::removeAllContainers(const ServerCredentials &credentials) { - QString scriptFileName; - DockerContainer container; - - if (proto == Protocol::Any) { - ErrorCode e = removeServer(credentials, Protocol::OpenVpn); - if (e) { - return e; - } - return removeServer(credentials, Protocol::ShadowSocksOverOpenVpn); - } - else if (proto == Protocol::OpenVpn) { - scriptFileName = ":/server_scripts/remove_container.sh"; - container = DockerContainer::OpenVpn; - } - else if (proto == Protocol::ShadowSocksOverOpenVpn) { - scriptFileName = ":/server_scripts/remove_container.sh"; - container = DockerContainer::ShadowSocksOverOpenVpn; - } - else return ErrorCode::NotImplementedError; - - - QString scriptData; - - QFile file(scriptFileName); - if (! file.open(QIODevice::ReadOnly)) return ErrorCode::InternalError; - - scriptData = file.readAll(); - if (scriptData.isEmpty()) return ErrorCode::InternalError; - - return runScript(sshParams(credentials), replaceVars(scriptData, genVarsForScript(credentials, container))); + return runScript(sshParams(credentials), + amnezia::scriptData(SharedScriptType::remove_all_containers)); } -ErrorCode ServerController::setupServer(const ServerCredentials &credentials, Protocol proto) +ErrorCode ServerController::removeContainer(const ServerCredentials &credentials, DockerContainer container) +{ + return runScript(sshParams(credentials), + replaceVars(amnezia::scriptData(SharedScriptType::remove_container), + genVarsForScript(credentials, container))); +} + +ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config) { ErrorCode e = runScript(sshParams(credentials), replaceVars(amnezia::scriptData(SharedScriptType::install_docker), genVarsForScript(credentials))); + if (e) return e; - if (proto == Protocol::OpenVpn) { + if (container == DockerContainer::OpenVpn) { return ErrorCode::NoError; - //return setupOpenVpnServer(credentials); + //return setupOpenVpnServer(credentials, config); } - else if (proto == Protocol::ShadowSocksOverOpenVpn) { - return setupShadowSocksServer(credentials); + else if (container == DockerContainer::ShadowSocksOverOpenVpn) { + return setupShadowSocksServer(credentials, config); } - else if (proto == Protocol::Any) { - //return ErrorCode::NotImplementedError; - - //setupOpenVpnServer(credentials); - //return setupShadowSocksServer(credentials); - return setupOpenVpnOverCloakServer(credentials); + else if (container == DockerContainer::OpenVpnOverCloak) { + return setupOpenVpnOverCloakServer(credentials, config); } return ErrorCode::NoError; } -ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credentials) +ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credentials, const QJsonObject &config) { return ErrorCode::NotImplementedError; @@ -475,7 +456,7 @@ ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credenti // return checkOpenVpnServer(DockerContainer::OpenVpn, credentials); } -ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials &credentials) +ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials &credentials, const QJsonObject &config) { ErrorCode e; DockerContainer container = DockerContainer::OpenVpnOverCloak; @@ -490,7 +471,6 @@ ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials amnezia::server::getDockerfileFolder(container) + "/Dockerfile"); - // Setup openvpn part QString scriptData = amnezia::scriptData(SharedScriptType::build_container); if (scriptData.isEmpty()) return ErrorCode::InternalError; @@ -518,11 +498,6 @@ ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials genVarsForScript(credentials, container)), "/opt/amnezia/start.sh"); -// qDebug().noquote() << "AAAA" -// << amnezia::scriptData(ProtocolScriptType::container_startup, Protocol::OpenVpnOverCloak), -// replaceVars("/opt/amnezia/start.sh", -// genVarsForScript(credentials, container)); - runScript(sshParams(credentials), replaceVars("sudo docker exec -d $CONTAINER_NAME sh -c \"chmod a+x /opt/amnezia/start.sh && /opt/amnezia/start.sh\"", genVarsForScript(credentials, container))); @@ -531,7 +506,7 @@ ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials return e; } -ErrorCode ServerController::setupShadowSocksServer(const ServerCredentials &credentials) +ErrorCode ServerController::setupShadowSocksServer(const ServerCredentials &credentials, const QJsonObject &config) { return ErrorCode::NotImplementedError; // // Setup openvpn part @@ -582,20 +557,20 @@ ErrorCode ServerController::setupShadowSocksServer(const ServerCredentials &cred // return e; } -ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container) +ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config) { Vars vars; - vars.append(qMakePair("$VPN_SUBNET_IP", amnezia::server::vpnDefaultSubnetIp)); - vars.append(qMakePair("$VPN_SUBNET_MASK_VAL", amnezia::server::vpnDefaultSubnetMaskVal)); - vars.append(qMakePair("$VPN_SUBNET_MASK", amnezia::server::vpnDefaultSubnetMask)); + vars.append({{"$VPN_SUBNET_IP", nonEmpty(config.value(config_key::subnet_address).toString(), amnezia::protocols::vpnDefaultSubnetAddress) }}); + vars.append({{"$VPN_SUBNET_MASK_VAL", nonEmpty(config.value(config_key::subnet_mask_val).toString(), amnezia::protocols::vpnDefaultSubnetMaskVal) }}); + vars.append({{"$VPN_SUBNET_MASK", nonEmpty(config.value(config_key::subnet_mask).toString(), amnezia::protocols::vpnDefaultSubnetMask) }}); - vars.append(qMakePair("$CONTAINER_NAME", amnezia::server::getContainerName(container))); - vars.append(qMakePair("$DOCKERFILE_FOLDER", "/opt/amnezia/" + amnezia::server::getContainerName(container))); + vars.append({{"$CONTAINER_NAME", amnezia::server::getContainerName(container)}}); + vars.append({{"$DOCKERFILE_FOLDER", "/opt/amnezia/" + amnezia::server::getContainerName(container)}}); QString serverIp = Utils::getIPAddress(credentials.hostName); if (!serverIp.isEmpty()) { - vars.append(qMakePair("$SERVER_IP_ADDRESS", serverIp)); + vars.append({{"$SERVER_IP_ADDRESS", serverIp}}); } else { qWarning() << "ServerController::genVarsForScript unable to resolve address for credentials.hostName"; @@ -603,23 +578,47 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential // + const QJsonObject &openvpnConfig = config.value(config_key::openvpn).toObject(); + const QJsonObject &cloakConfig = config.value(config_key::cloak).toObject(); + const QJsonObject &ssConfig = config.value(config_key::shadowsocks).toObject(); + if (container == DockerContainer::OpenVpn) { - vars.append(qMakePair("$SERVER_PORT", amnezia::protocols::openvpn::openvpnDefaultPort())); + vars.append({{"$DOCKER_PORT", nonEmpty(config.value(config_key::port).toString(), protocols::openvpn::openvpnDefaultPort) }}); } else if (container == DockerContainer::OpenVpnOverCloak) { - vars.append(qMakePair("$SERVER_PORT", amnezia::protocols::cloak::ckDefaultPort())); - vars.append(qMakePair("$FAKE_WEB_SITE_ADDRESS", amnezia::protocols::cloak::ckDefaultRedirSite())); + vars.append({{"$DOCKER_PORT", nonEmpty(config.value(config_key::port).toString(), protocols::cloak::ckDefaultPort) }}); + + vars.append({{"$FAKE_WEB_SITE_ADDRESS", nonEmpty(cloakConfig.value(config_key::site).toString(), protocols::cloak::ckDefaultRedirSite) }}); } else if (container == DockerContainer::ShadowSocksOverOpenVpn) { - vars.append(qMakePair("$SERVER_PORT", "6789")); + vars.append({{"$DOCKER_PORT", nonEmpty(config.value(config_key::port).toString(), protocols::shadowsocks::ssDefaultPort) }}); } return vars; } +QString ServerController::checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode) +{ + QString stdOut; + auto cbReadStdOut = [&](const QString &data, QSharedPointer proc) { + stdOut += data + "\n"; + }; + auto cbReadStdErr = [&](const QString &data, QSharedPointer ) { + stdOut += data + "\n"; + }; + + ErrorCode e = runScript(sshParams(credentials), + amnezia::scriptData(SharedScriptType::check_connection), cbReadStdOut, cbReadStdErr); + + if (errorCode) *errorCode = e; + + return stdOut; +} + SshConnection *ServerController::connectToHost(const SshConnectionParameters &sshParams) { SshConnection *client = acquireConnection(sshParams); + if (!client) return nullptr; QEventLoop waitssh; QObject::connect(client, &SshConnection::connected, &waitssh, [&]() { @@ -670,6 +669,12 @@ SshConnection *ServerController::connectToHost(const SshConnectionParameters &ss return client; } +void ServerController::disconnectFromHost(const ServerCredentials &credentials) +{ + SshConnection *client = acquireConnection(sshParams(credentials)); + if (client) client->disconnectFromHost(); +} + ErrorCode ServerController::setupServerFirewall(const ServerCredentials &credentials) { return runScript(sshParams(credentials), diff --git a/client/core/servercontroller.h b/client/core/servercontroller.h index b1e47406f..ebfd01f19 100644 --- a/client/core/servercontroller.h +++ b/client/core/servercontroller.h @@ -1,6 +1,7 @@ #ifndef SERVERCONTROLLER_H #define SERVERCONTROLLER_H +#include #include #include "sshconnection.h" #include "sshremoteprocess.h" @@ -20,9 +21,11 @@ public: static ErrorCode fromSshProcessExitStatus(int exitStatus); static QSsh::SshConnectionParameters sshParams(const ServerCredentials &credentials); + static void disconnectFromHost(const ServerCredentials &credentials); - static ErrorCode removeServer(const ServerCredentials &credentials, Protocol proto); - static ErrorCode setupServer(const ServerCredentials &credentials, Protocol proto); + static ErrorCode removeAllContainers(const ServerCredentials &credentials); + static ErrorCode removeContainer(const ServerCredentials &credentials, DockerContainer container); + static ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); static ErrorCode checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials); @@ -42,16 +45,17 @@ public: const std::function)> &cbReadStdOut = nullptr, const std::function)> &cbReadStdErr = nullptr); - static Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None); + static Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject()); + static QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr); private: static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams); static ErrorCode installDocker(const ServerCredentials &credentials); - static ErrorCode setupOpenVpnServer(const ServerCredentials &credentials); - static ErrorCode setupOpenVpnOverCloakServer(const ServerCredentials &credentials); - static ErrorCode setupShadowSocksServer(const ServerCredentials &credentials); + static ErrorCode setupOpenVpnServer(const ServerCredentials &credentials, const QJsonObject &config = QJsonObject()); + static ErrorCode setupOpenVpnOverCloakServer(const ServerCredentials &credentials, const QJsonObject &config = QJsonObject()); + static ErrorCode setupShadowSocksServer(const ServerCredentials &credentials, const QJsonObject &config = QJsonObject()); }; #endif // SERVERCONTROLLER_H diff --git a/client/images/check.png b/client/images/check.png index 558bed5d0..43039eb1d 100644 Binary files a/client/images/check.png and b/client/images/check.png differ diff --git a/client/images/uncheck.png b/client/images/uncheck.png index 233843c5b..b6723a447 100644 Binary files a/client/images/uncheck.png and b/client/images/uncheck.png differ diff --git a/client/protocols/openvpnovercloakprotocol.cpp b/client/protocols/openvpnovercloakprotocol.cpp index 3338b0ac3..c220267d3 100644 --- a/client/protocols/openvpnovercloakprotocol.cpp +++ b/client/protocols/openvpnovercloakprotocol.cpp @@ -38,8 +38,8 @@ ErrorCode OpenVpnOverCloakProtocol::start() QStringList args = QStringList() << "-c" << m_cloakCfgFile.fileName() << "-s" << m_cloakConfig.value("Remote").toString() - << "-p" << amnezia::protocols::cloak::ckDefaultPort() - << "-l" << amnezia::protocols::openvpn::openvpnDefaultPort(); + << "-p" << amnezia::protocols::cloak::ckDefaultPort + << "-l" << amnezia::protocols::openvpn::openvpnDefaultPort; qDebug().noquote() << "OpenVpnOverCloakProtocol::start()" << cloakExecPath() << args.join(" "); diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 7a97852e1..68e0f64e2 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -4,28 +4,73 @@ #include namespace amnezia { -namespace protocols { -namespace openvpn { -static QString caCertPath() { return "/opt/amnezia/openvpn/pki/ca.crt"; } -static QString clientCertPath() { return "/opt/amnezia/openvpn/pki/issued"; } -static QString taKeyPath() { return "/opt/amnezia/openvpn/ta.key"; } -static QString clientsDirPath() { return "/opt/amnezia/openvpn/clients"; } -static QString openvpnDefaultPort() { return "1194"; } +inline QString nonEmpty(const QString &val, const QString &deflt) { return val.isEmpty() ? deflt : val; } + + +namespace config_key { + +// Json config strings +const char hostName[] = "hostName"; +const char userName[] = "userName"; +const char password[] = "password"; +const char port[] = "port"; +const char description[] = "description"; + + +const char containers[] = "containers"; +const char container[] = "container"; +const char defaultContainer[] = "defaultContainer"; + +const char protocols[] = "protocols"; +const char protocol[] = "protocol"; + +const char transport_protocol[] = "transport_protocol"; +const char cipher[] = "cipher"; +const char hash[] = "hash"; + +const char site[] = "site"; + +const char subnet_address[] = "subnet_address"; +const char subnet_mask[] = "subnet_mask"; +const char subnet_mask_val[] = "subnet_mask_val"; + +const char openvpn[] = "openvpn"; +const char shadowsocks[] = "shadowsocks"; +const char cloak[] = "cloak"; + +} + +namespace protocols { + +const char vpnDefaultSubnetAddress[] = "10.8.0.0"; +const char vpnDefaultSubnetMask[] = "255.255.255.0"; +const char vpnDefaultSubnetMaskVal[] = "24"; + +namespace openvpn { +const char caCertPath[] = "/opt/amnezia/openvpn/pki/ca.crt"; +const char clientCertPath[] = "/opt/amnezia/openvpn/pki/issued"; +const char taKeyPath[] = "/opt/amnezia/openvpn/ta.key"; +const char clientsDirPath[] = "/opt/amnezia/openvpn/clients"; +const char openvpnDefaultPort[] = "1194"; +const char openvpnDefaultProto[] = "UDP"; +const char openvpnDefaultCipher[] = "AES-256-GCM"; +const char openvpnDefaultHash[] = "SHA512"; +const bool blockOutsideDNS = true; } namespace shadowsocks { -static int ssRemotePort() { return 6789; } -static int ssContainerPort() { return 8585; } -static QString ssEncryption() { return "chacha20-ietf-poly1305"; } +const char ssDefaultPort[] = "6789"; +const char ssLocalProxyPort[] = "8585"; +const char ssDefaultCipher[] = "chacha20-ietf-poly1305"; } namespace cloak { -static QString ckPublicKeyPath() { return "/opt/amnezia/cloak/cloak_public.key"; } -static QString ckBypassUidKeyPath() { return "/opt/amnezia/cloak/cloak_bypass_uid.key"; } -static QString ckAdminKeyPath() { return "/opt/amnezia/cloak/cloak_admin_uid.key"; } -static QString ckDefaultPort() { return "443"; } -static QString ckDefaultRedirSite() { return "mail.ru"; } +const char ckPublicKeyPath[] = "/opt/amnezia/cloak/cloak_public.key"; +const char ckBypassUidKeyPath[] = "/opt/amnezia/cloak/cloak_bypass_uid.key"; +const char ckAdminKeyPath[] = "/opt/amnezia/cloak/cloak_admin_uid.key"; +const char ckDefaultPort[] = "443"; +const char ckDefaultRedirSite[] = "mail.ru"; } diff --git a/client/protocols/shadowsocksvpnprotocol.cpp b/client/protocols/shadowsocksvpnprotocol.cpp index 74e0ec4d5..0b767d868 100644 --- a/client/protocols/shadowsocksvpnprotocol.cpp +++ b/client/protocols/shadowsocksvpnprotocol.cpp @@ -100,11 +100,11 @@ QJsonObject ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials { QJsonObject ssConfig; ssConfig.insert("server", credentials.hostName); - ssConfig.insert("server_port", amnezia::protocols::shadowsocks::ssRemotePort()); - ssConfig.insert("local_port", amnezia::protocols::shadowsocks::ssContainerPort()); + ssConfig.insert("server_port", amnezia::protocols::shadowsocks::ssDefaultPort); + ssConfig.insert("local_port", amnezia::protocols::shadowsocks::ssLocalProxyPort); ssConfig.insert("password", QString(QCryptographicHash::hash(credentials.password.toUtf8(), QCryptographicHash::Sha256).toHex())); ssConfig.insert("timeout", 60); - ssConfig.insert("method", amnezia::protocols::shadowsocks::ssEncryption()); + ssConfig.insert("method", amnezia::protocols::shadowsocks::ssDefaultCipher); return ssConfig; } diff --git a/client/resources.qrc b/client/resources.qrc index 6e87c0449..be575644c 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -52,5 +52,7 @@ images/uncheck.png images/settings_grey.png images/plus.png + server_scripts/check_connection.sh + server_scripts/remove_all_containers.sh diff --git a/client/server_scripts/check_connection.sh b/client/server_scripts/check_connection.sh new file mode 100644 index 000000000..9301d1a2b --- /dev/null +++ b/client/server_scripts/check_connection.sh @@ -0,0 +1 @@ +uname -a diff --git a/client/server_scripts/openvpn_cloak/configure_container.sh b/client/server_scripts/openvpn_cloak/configure_container.sh index 18f4b7fd9..d36e8c81b 100644 --- a/client/server_scripts/openvpn_cloak/configure_container.sh +++ b/client/server_scripts/openvpn_cloak/configure_container.sh @@ -5,11 +5,11 @@ #sudo docker stop $CONTAINER_NAME #sudo docker rm -f $CONTAINER_NAME #sudo docker pull amneziavpn/openvpn-cloak:latest -#sudo docker run -d --restart always --cap-add=NET_ADMIN -p $SERVER_PORT:443/tcp --name $CONTAINER_NAME amneziavpn/openvpn-cloak:latest +#sudo docker run -d --restart always --cap-add=NET_ADMIN -p $DOCKER_PORT:443/tcp --name $CONTAINER_NAME amneziavpn/openvpn-cloak:latest sudo docker stop $CONTAINER_NAME sudo docker rm -f $CONTAINER_NAME -sudo docker run -d --restart always --cap-add=NET_ADMIN -p $SERVER_PORT:443/tcp --name $CONTAINER_NAME $CONTAINER_NAME +sudo docker run -d --restart always --cap-add=NET_ADMIN -p $DOCKER_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/remove_all_containers.sh b/client/server_scripts/remove_all_containers.sh new file mode 100644 index 000000000..745aabb0e --- /dev/null +++ b/client/server_scripts/remove_all_containers.sh @@ -0,0 +1,3 @@ +sudo docker ps | grep amnezia | awk '{print $1}' | xargs sudo docker stop +sudo docker ps | grep amnezia | awk '{print $1}' | xargs sudo docker rm +sudo docker images -a | grep amnezia | awk '{print $3}' | xargs docker rmi diff --git a/client/settings.cpp b/client/settings.cpp index 27a9c9281..68a532bc0 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -2,6 +2,7 @@ #include "settings.h" #include +#include "protocols/protocols_defs.h" Settings::Settings(QObject* parent) : QObject(parent), @@ -16,11 +17,11 @@ Settings::Settings(QObject* parent) : if (!user.isEmpty() && !password.isEmpty() && !serverName.isEmpty()){ QJsonObject server; - server.insert(userNameString, user); - server.insert(passwordString, password); - server.insert(hostNameString, serverName); - server.insert(portString, port); - server.insert(descriptionString, tr("Server #1")); + server.insert(config_key::userName, user); + server.insert(config_key::password, password); + server.insert(config_key::hostName, serverName); + server.insert(config_key::port, port); + server.insert(config_key::description, tr("Server #1")); addServer(server); } @@ -69,7 +70,7 @@ bool Settings::editServer(int index, const QJsonObject &server) void Settings::setDefaultContainer(int serverIndex, DockerContainer container) { QJsonObject s = server(serverIndex); - s.insert(defaultContainerString, containerToString(container)); + s.insert(config_key::defaultContainer, containerToString(container)); editServer(serverIndex, s); } @@ -80,13 +81,42 @@ DockerContainer Settings::defaultContainer(int serverIndex) const QString Settings::defaultContainerName(int serverIndex) const { - QString name = server(serverIndex).value(defaultContainerString).toString(); + QString name = server(serverIndex).value(config_key::defaultContainer).toString(); if (name.isEmpty()) { return containerToString(DockerContainer::OpenVpnOverCloak); } else return name; } +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(); +} + +QJsonObject Settings::protocolConfig(int serverIndex, DockerContainer container, Protocol proto) +{ + const QJsonObject &c = containerConfig(serverIndex, container); + + switch (proto) { + case Protocol::OpenVpn: + return c.value(config_key::openvpn).toObject(); + case Protocol::OpenVpnOverCloak: + return c.value(config_key::openvpn).toObject(); + case Protocol::ShadowSocksOverOpenVpn: + return c.value(config_key::openvpn).toObject(); + default: + break; + } +} + bool Settings::haveAuthData() const { ServerCredentials cred = defaultServerCredentials(); @@ -94,6 +124,26 @@ bool Settings::haveAuthData() const return (!cred.hostName.isEmpty() && !cred.userName.isEmpty() && !cred.password.isEmpty()); } +QString Settings::nextAvailableServerName() const +{ + int i = 0; + //bool found = false; + bool nameExist = false; + + do { + i++; + nameExist = false; + for (const QJsonValue &server: serversArray()) { + if (server.toObject().value(config_key::description).toString() == tr("Server") + " " + QString::number(i)) { + nameExist = true; + break; + } + } + } while (nameExist); + + return tr("Server") + " " + QString::number(i); +} + //void Settings::setServerCredentials(const ServerCredentials &credentials) //{ // setServerName(credentials.hostName); @@ -104,13 +154,18 @@ bool Settings::haveAuthData() const ServerCredentials Settings::defaultServerCredentials() const { - const QJsonObject &s = defaultServer(); + return serverCredentials(defaultServerIndex()); +} + +ServerCredentials Settings::serverCredentials(int index) const +{ + const QJsonObject &s = server(index); ServerCredentials credentials; - credentials.hostName = s.value(hostNameString).toString(); - credentials.userName = s.value(userNameString).toString(); - credentials.password = s.value(passwordString).toString(); - credentials.port = s.value(portString).toInt(); + credentials.hostName = s.value(config_key::hostName).toString(); + credentials.userName = s.value(config_key::userName).toString(); + credentials.password = s.value(config_key::password).toString(); + credentials.port = s.value(config_key::port).toInt(); return credentials; } diff --git a/client/settings.h b/client/settings.h index 4fe5b1835..e6c21372a 100644 --- a/client/settings.h +++ b/client/settings.h @@ -36,9 +36,10 @@ public: // void setServerPort(int serverPort = 22) { m_settings.setValue("Server/serverPort", serverPort); } ServerCredentials defaultServerCredentials() const; + ServerCredentials serverCredentials(int index) const; //void setServerCredentials(const ServerCredentials &credentials); - QJsonArray serversArray() const {return QJsonDocument::fromJson(m_settings.value("Servers/serversList").toByteArray()).array(); } + QJsonArray serversArray() const { return QJsonDocument::fromJson(m_settings.value("Servers/serversList").toByteArray()).array(); } void setServersArray(const QJsonArray &servers) { m_settings.setValue("Servers/serversList", QJsonDocument(servers).toJson()); } // Servers section @@ -52,11 +53,15 @@ public: void setDefaultServer(int index) { m_settings.setValue("Servers/defaultServerIndex", index); } QJsonObject defaultServer() const { return server(defaultServerIndex()); } - void setDefaultContainer(int serverIndex, DockerContainer container ); + void setDefaultContainer(int serverIndex, DockerContainer container); DockerContainer defaultContainer(int serverIndex) const; QString defaultContainerName(int serverIndex) const; + QJsonObject containerConfig(int serverIndex, DockerContainer container); + QJsonObject protocolConfig(int serverIndex, DockerContainer container, Protocol proto); + bool haveAuthData() const; + QString nextAvailableServerName() const; // App settings section bool isAutoConnect() const { return m_settings.value("Conf/autoConnect", QString()).toBool(); } @@ -90,21 +95,12 @@ public: public: - // Json strings - static constexpr char hostNameString[] = "hostName"; - static constexpr char userNameString[] = "userName"; - static constexpr char passwordString[] = "password"; - static constexpr char portString[] = "port"; - static constexpr char descriptionString[] = "description"; - static constexpr char defaultContainerString[] = "defaultContainer"; private: QSettings m_settings; - - }; #endif // SETTINGS_H diff --git a/client/ui/mainwindow.cpp b/client/ui/mainwindow.cpp index 23d6350f5..93a536423 100644 --- a/client/ui/mainwindow.cpp +++ b/client/ui/mainwindow.cpp @@ -17,14 +17,16 @@ #include "core/errorstrings.h" #include "configurators/openvpn_configurator.h" #include "core/servercontroller.h" +#include "core/server_defs.h" +#include "protocols/protocols_defs.h" #include "ui/qautostart.h" #include "debug.h" #include "defines.h" #include "mainwindow.h" -#include "ui_mainwindow.h" #include "utils.h" #include "vpnconnection.h" +#include "ui_mainwindow.h" #include "ui/server_widget.h" #include "ui_server_widget.h" @@ -32,6 +34,8 @@ #include "ui/macos_util.h" #endif +using namespace amnezia; + MainWindow::MainWindow(QWidget *parent) : #ifdef Q_OS_WIN CFramelessWindow(parent), @@ -45,7 +49,8 @@ MainWindow::MainWindow(QWidget *parent) : setupTray(); setupUiConnections(); - setupProtocolsPage(); + setupProtocolsPageConnections(); + setupNewServerPageConnections(); ui->label_error_text->clear(); installEventFilter(this); @@ -142,20 +147,20 @@ void MainWindow::goToPage(Page page, bool reset, bool slide) { qDebug() << "goToPage" << page; if (reset) { - if (page == Page::NewServer) { - ui->label_new_server_wait_info->hide(); - ui->label_new_server_wait_info->clear(); - - ui->progressBar_new_server_connection->setMinimum(0); - ui->progressBar_new_server_connection->setMaximum(300); - } if (page == Page::ServerSettings) { + updateSettings(); + ui->label_server_settings_wait_info->hide(); ui->label_server_settings_wait_info->clear(); -// ui->label_server_settings_server->setText(QString("%1@%2:%3") -// .arg(m_settings.userName()) -// .arg(m_settings.serverName()) -// .arg(m_settings.serverPort())); + + QJsonObject server = m_settings.server(selectedServerIndex); + QString port = server.value(config_key::port).toString(); + ui->label_server_settings_server->setText(QString("%1@%2%3%4") + .arg(server.value(config_key::userName).toString()) + .arg(server.value(config_key::hostName).toString()) + .arg(port.isEmpty() ? "" : ":") + .arg(port)); + ui->lineEdit_server_settings_description->setText(server.value(config_key::description).toString()); } if (page == Page::ShareConnection) { QJsonObject ssConfig = ShadowSocksVpnProtocol::genShadowSocksConfig(m_settings.defaultServerCredentials()); @@ -175,12 +180,35 @@ void MainWindow::goToPage(Page page, bool reset, bool slide) ui->label_share_ss_method->setText(ssConfig.value("method").toString()); ui->label_share_ss_password->setText(ssConfig.value("password").toString()); } - if (page == Page::ServerSettings) { - updateSettings(); + if (page == Page::ServersList) { + updateServersPage(); } if (page == Page::Start) { + ui->label_new_server_wait_info->hide(); + ui->label_new_server_wait_info->clear(); + + ui->progressBar_new_server_connection->setMinimum(0); + ui->progressBar_new_server_connection->setMaximum(300); + ui->pushButton_back_from_start->setVisible(!pagesStack.isEmpty()); } + if (page == Page::NewServer_2) { + ui->pushButton_new_server_settings_cloak->setChecked(true); + ui->pushButton_new_server_settings_cloak->setChecked(false); + ui->pushButton_new_server_settings_ss->setChecked(true); + ui->pushButton_new_server_settings_ss->setChecked(false); + ui->pushButton_new_server_settings_openvpn->setChecked(true); + ui->pushButton_new_server_settings_openvpn->setChecked(false); + + ui->lineEdit_new_server_cloak_port->setText(amnezia::protocols::cloak::ckDefaultPort); + ui->lineEdit_new_server_cloak_site->setText(amnezia::protocols::cloak::ckDefaultRedirSite); + + ui->lineEdit_new_server_ss_port->setText(amnezia::protocols::shadowsocks::ssDefaultPort); + ui->comboBox_new_server_ss_cipher->setCurrentText(amnezia::protocols::shadowsocks::ssDefaultCipher); + + ui->lineEdit_new_server_openvpn_port->setText(amnezia::protocols::openvpn::openvpnDefaultPort); + ui->comboBox_new_server_openvpn_proto->setCurrentText(amnezia::protocols::openvpn::openvpnDefaultProto); + } ui->pushButton_new_server_connect_key->setChecked(false); } @@ -196,7 +224,7 @@ void MainWindow::goToPage(Page page, bool reset, bool slide) void MainWindow::closePage() { Page prev = pagesStack.pop(); - qDebug() << "closePage" << prev << "Set page" << pagesStack.top(); + //qDebug() << "closePage" << prev << "Set page" << pagesStack.top(); ui->stackedWidget_main->slideInWidget(getPageWidget(pagesStack.top()), SlidingStackedWidget::LEFT2RIGHT); } @@ -205,6 +233,7 @@ QWidget *MainWindow::getPageWidget(MainWindow::Page page) switch (page) { case(Page::Start): return ui->page_start; case(Page::NewServer): return ui->page_new_server; + case(Page::NewServer_2): return ui->page_new_server_2; case(Page::Vpn): return ui->page_vpn; case(Page::GeneralSettings): return ui->page_general_settings; case(Page::AppSettings): return ui->page_app_settings; @@ -268,8 +297,19 @@ void MainWindow::keyPressEvent(QKeyEvent *event) QMessageBox::warning(this, APPLICATION_NAME, tr("Cannot open logs folder!")); } break; +#ifdef QT_DEBUG case Qt::Key_Q: qApp->quit(); + case Qt::Key_C: + qDebug().noquote() << QJsonDocument(m_settings.serversArray()).toJson(); + break; +#endif + case Qt::Key_A: + goToPage(Page::Start); + break; + case Qt::Key_S: + goToPage(Page::ServerSettings); + break; default: ; } @@ -302,7 +342,7 @@ void MainWindow::hideEvent(QHideEvent *event) #endif } -void MainWindow::onPushButtonNewServerConnectWithNewData(bool) +void MainWindow::onPushButtonNewServerConnect(bool) { if (ui->pushButton_new_server_connect_key->isChecked()){ if (ui->lineEdit_new_server_ip->text().isEmpty() || @@ -324,7 +364,8 @@ void MainWindow::onPushButtonNewServerConnectWithNewData(bool) } - qDebug() << "Start connection with new data"; + qDebug() << "MainWindow::onPushButtonNewServerConnect checking new server"; + ServerCredentials serverCredentials; serverCredentials.hostName = ui->lineEdit_new_server_ip->text(); @@ -352,24 +393,103 @@ void MainWindow::onPushButtonNewServerConnectWithNewData(bool) serverCredentials.password = ui->lineEdit_new_server_password->text(); } + ui->pushButton_new_server_connect->setEnabled(false); + ui->pushButton_new_server_connect->setText(tr("Connecting...")); + ErrorCode e = ErrorCode::NoError; + //QString output = ServerController::checkSshConnection(serverCredentials, &e); + QString output; + bool ok = true; + if (e) { + ui->label_new_server_wait_info->show(); + ui->label_new_server_wait_info->setText(errorString(e)); + ok = false; + } + else { + if (output.contains("Please login as the user")) { + output.replace("\n", ""); + ui->label_new_server_wait_info->show(); + ui->label_new_server_wait_info->setText(output); + ok = false; + } + } - bool ok = installServer(serverCredentials, - ui->page_new_server, - ui->progressBar_new_server_connection, - ui->pushButton_new_server_connect_with_new_data, - ui->label_new_server_wait_info); + ui->pushButton_new_server_connect->setEnabled(true); + ui->pushButton_new_server_connect->setText(tr("Connect")); + + installCredentials = serverCredentials; + if (ok) goToPage(Page::NewServer_2); +} + +void MainWindow::onPushButtonNewServerConnectConfigure(bool) +{ + QJsonObject cloakConfig { + { config_key::port, ui->lineEdit_new_server_cloak_port->text() }, + { config_key::container, amnezia::server::getContainerName(DockerContainer::OpenVpnOverCloak) }, + { config_key::cloak, QJsonObject { + { config_key::site, ui->lineEdit_new_server_cloak_site->text() }} + } + }; + QJsonObject ssConfig { + { config_key::port, ui->lineEdit_new_server_ss_port->text() }, + { config_key::container, amnezia::server::getContainerName(DockerContainer::ShadowSocksOverOpenVpn) }, + { config_key::shadowsocks, QJsonObject { + { config_key::cipher, ui->comboBox_new_server_ss_cipher->currentText() }} + } + }; + QJsonObject openVpnConfig { + { config_key::port, ui->lineEdit_new_server_openvpn_port->text() }, + { config_key::container, amnezia::server::getContainerName(DockerContainer::OpenVpn) }, + { config_key::openvpn, QJsonObject { + { config_key::transport_protocol, ui->comboBox_new_server_openvpn_proto->currentText() }} + } + }; + + QJsonArray containerConfigs; + QList containers; + + if (ui->checkBox_new_server_cloak->isChecked()) { + containerConfigs.append(cloakConfig); + containers.append(DockerContainer::OpenVpnOverCloak); + } + + if (ui->checkBox_new_server_ss->isChecked()) { + containerConfigs.append(ssConfig); + containers.append(DockerContainer::ShadowSocksOverOpenVpn); + } + + if (ui->checkBox_new_server_openvpn->isChecked()) { + containerConfigs.append(openVpnConfig); + containers.append(DockerContainer::ShadowSocksOverOpenVpn); + } + + bool ok = true; +// bool ok = installServer(installCredentials, containers, configs, +// ui->page_new_server, +// ui->progressBar_new_server_connection, +// ui->pushButton_new_server_connect, +// ui->label_new_server_wait_info); if (ok) { - //m_settings.setServerCredentials(serverCredentials); + QJsonObject server; + server.insert(config_key::hostName, installCredentials.hostName); + server.insert(config_key::userName, installCredentials.userName); + server.insert(config_key::password, installCredentials.password); + server.insert(config_key::port, installCredentials.port); + server.insert(config_key::description, m_settings.nextAvailableServerName()); + + server.insert(config_key::containers, containerConfigs); + + m_settings.addServer(server); + updateSettings(); goToPage(Page::Vpn); qApp->processEvents(); - onConnect(); + //onConnect(); } } -void MainWindow::onPushButtonNewServerConnectWithExistingCode(bool) +void MainWindow::onPushButtonNewServerImport(bool) { QString s = ui->lineEdit_start_existing_code->text(); s.replace("vpn://", ""); @@ -398,7 +518,8 @@ void MainWindow::onPushButtonNewServerConnectWithExistingCode(bool) } bool MainWindow::installServer(ServerCredentials credentials, - QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info) + QList containers, QJsonArray configs, + QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info) { page->setEnabled(false); button->setVisible(false); @@ -406,95 +527,112 @@ bool MainWindow::installServer(ServerCredentials credentials, info->setVisible(true); info->setText(tr("Please wait, configuring process may take up to 5 minutes")); - QTimer timer; - connect(&timer, &QTimer::timeout, [progress](){ - progress->setValue(progress->value() + 1); - }); - progress->setValue(0); - timer.start(1000); - - - ErrorCode e = ServerController::setupServer(credentials, Protocol::Any); - qDebug() << "Setup server finished with code" << e; - if (e) { - page->setEnabled(true); - button->setVisible(true); - info->setVisible(false); - - QMessageBox::warning(this, APPLICATION_NAME, - tr("Error occurred while configuring server.") + "\n" + - errorString(e)); - - return false; - } - - // just ui progressbar tweak - timer.stop(); - - int remaining_val = progress->maximum() - progress->value(); - - if (remaining_val > 0) { - QTimer timer1; - QEventLoop loop1; - - connect(&timer1, &QTimer::timeout, [&](){ + for (int i = 0; i < containers.size(); ++i) { + QTimer timer; + connect(&timer, &QTimer::timeout, [progress](){ progress->setValue(progress->value() + 1); - if (progress->value() >= progress->maximum()) { - loop1.quit(); - } }); - timer1.start(5); - loop1.exec(); + progress->setValue(0); + timer.start(1000); + + progress->setTextVisible(true); + progress->setFormat(QString("%1%2%3").arg(i+1).arg(tr("of")).arg(containers.size())); + + ErrorCode e = ServerController::setupContainer(credentials, containers.at(i), configs.at(i).toObject()); + qDebug() << "Setup server finished with code" << e; + ServerController::disconnectFromHost(credentials); + + if (e) { + page->setEnabled(true); + button->setVisible(true); + info->setVisible(false); + + QMessageBox::warning(this, APPLICATION_NAME, + tr("Error occurred while configuring server.") + "\n" + + errorString(e)); + + return false; + } + + // just ui progressbar tweak + timer.stop(); + + int remaining_val = progress->maximum() - progress->value(); + + if (remaining_val > 0) { + QTimer timer1; + QEventLoop loop1; + + connect(&timer1, &QTimer::timeout, [&](){ + progress->setValue(progress->value() + 1); + if (progress->value() >= progress->maximum()) { + loop1.quit(); + } + }); + + timer1.start(5); + loop1.exec(); + } } - button->show(); - page->setEnabled(true); - info->setText(tr("Amnezia server installed")); + + + +// button->show(); +// page->setEnabled(true); +// info->setText(tr("Amnezia server installed")); return true; } 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); +// 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) { - onDisconnect(); + ui->page_server_settings->setEnabled(false); + ui->pushButton_server_settings_clear->setText(tr("Uninstalling Amnezia software...")); - ErrorCode e = ServerController::removeServer(m_settings.defaultServerCredentials(), Protocol::Any); + if (m_settings.defaultServerIndex() == selectedServerIndex) { + onDisconnect(); + } + + ErrorCode e = ServerController::removeContainer(m_settings.serverCredentials(selectedServerIndex), DockerContainer::None); + ServerController::disconnectFromHost(m_settings.serverCredentials(selectedServerIndex)); if (e) { QMessageBox::warning(this, APPLICATION_NAME, tr("Error occurred while configuring server.") + "\n" + errorString(e) + "\n" + tr("See logs for details.")); - return; } else { ui->label_server_settings_wait_info->show(); ui->label_server_settings_wait_info->setText(tr("Amnezia server successfully uninstalled")); } + + ui->page_server_settings->setEnabled(true); + ui->pushButton_server_settings_clear->setText(tr("Clear server from Amnezia software")); } void MainWindow::onPushButtonForgetServer(bool) { - onDisconnect(); + if (m_settings.defaultServerIndex() == selectedServerIndex) { + onDisconnect(); + } + m_settings.removeServer(selectedServerIndex); -// m_settings.setUserName(""); -// m_settings.setPassword(""); -// m_settings.setServerName(""); -// m_settings.setServerPort(); - - goToPage(Page::Start); + closePage(); + updateServersPage(); } void MainWindow::onBytesChanged(quint64 receivedData, quint64 sentData) @@ -638,10 +776,10 @@ void MainWindow::setupUiConnections() QDesktopServices::openUrl(QUrl("https://amnezia.org")); }); - connect(ui->pushButton_connect, SIGNAL(clicked(bool)), this, SLOT(onPushButtonConnectClicked(bool))); - connect(ui->pushButton_new_server_setup, &QPushButton::clicked, this, [this](){ goToPage(Page::NewServer); }); - connect(ui->pushButton_new_server_connect_with_new_data, SIGNAL(clicked(bool)), this, SLOT(onPushButtonNewServerConnectWithNewData(bool))); - connect(ui->pushButton_new_server_connect, SIGNAL(clicked(bool)), this, SLOT(onPushButtonNewServerConnectWithExistingCode(bool))); + + connect(ui->pushButton_new_server_connect, SIGNAL(clicked(bool)), this, SLOT(onPushButtonNewServerConnect(bool))); + 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))); @@ -651,12 +789,15 @@ void MainWindow::setupUiConnections() connect(ui->pushButton_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); }); connect(ui->pushButton_app_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::AppSettings); }); connect(ui->pushButton_network_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::NetworkSettings); }); - connect(ui->pushButton_server_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerSettings); }); + connect(ui->pushButton_server_settings, &QPushButton::clicked, this, [this](){ + 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); - updateShareCode(); + updateShareCodePage(); }); connect(ui->pushButton_copy_sharing_code, &QPushButton::clicked, this, [this](){ @@ -668,25 +809,11 @@ void MainWindow::setupUiConnections() }); }); - -// connect(ui->pushButton_back_from_sites, &QPushButton::clicked, this, [this](){ goToPage(Page::Vpn); }); -// connect(ui->pushButton_back_from_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::Vpn); }); -// connect(ui->pushButton_back_from_new_server, &QPushButton::clicked, this, [this](){ goToPage(Page::Start); }); -// connect(ui->pushButton_back_from_app_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); }); -// connect(ui->pushButton_back_from_network_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); }); -// connect(ui->pushButton_back_from_server_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); }); -// connect(ui->pushButton_back_from_servers, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); }); -// connect(ui->pushButton_back_from_share, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); }); -// connect(ui->pushButton_back_from_server_vpn_protocols, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerSettings); }); - -// connect(ui->pushButton_back_from_server_vpn_protocols, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerSettings); }); -// connect(ui->pushButton_back_from_server_vpn_protocols, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerSettings); }); -// connect(ui->pushButton_back_from_server_vpn_protocols, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerSettings); }); - connect(ui->pushButton_back_from_sites, &QPushButton::clicked, this, [this](){ closePage(); }); connect(ui->pushButton_back_from_settings, &QPushButton::clicked, this, [this](){ closePage(); }); connect(ui->pushButton_back_from_start, &QPushButton::clicked, this, [this](){ closePage(); }); connect(ui->pushButton_back_from_new_server, &QPushButton::clicked, this, [this](){ closePage(); }); + connect(ui->pushButton_back_from_new_server_2, &QPushButton::clicked, this, [this](){ closePage(); }); connect(ui->pushButton_back_from_app_settings, &QPushButton::clicked, this, [this](){ closePage(); }); connect(ui->pushButton_back_from_network_settings, &QPushButton::clicked, this, [this](){ closePage(); }); connect(ui->pushButton_back_from_server_settings, &QPushButton::clicked, this, [this](){ closePage(); }); @@ -738,23 +865,33 @@ void MainWindow::setupUiConnections() } }); - connect(ui->pushButton_new_server_connect_key, &QPushButton::toggled, this, [this](bool checked){ - ui->label_new_server_password->setText(checked ? tr("Private key") : tr("Password")); - ui->pushButton_new_server_connect_key->setText(checked ? tr("Connect using SSH password") : tr("Connect using SSH key")); - ui->lineEdit_new_server_password->setVisible(!checked); - ui->textEdit_new_server_ssh_key->setVisible(checked); - }); connect(ui->pushButton_check_for_updates, &QPushButton::clicked, this, [this](){ QDesktopServices::openUrl(QUrl("https://github.com/amnezia-vpn/desktop-client/releases")); }); connect(ui->pushButton_servers_add_new, &QPushButton::clicked, this, [this](){ goToPage(Page::Start); }); + + connect(ui->lineEdit_server_settings_description, &QLineEdit::editingFinished, this, [this](){ + const QString &newText = ui->lineEdit_server_settings_description->text(); + QJsonObject server = m_settings.server(selectedServerIndex); + server.insert(config_key::description, newText); + m_settings.editServer(selectedServerIndex, server); + updateServersPage(); + }); + + connect(ui->lineEdit_server_settings_description, &QLineEdit::returnPressed, this, [this](){ + ui->lineEdit_server_settings_description->clearFocus(); + }); + + } -void MainWindow::setupProtocolsPage() +void MainWindow::setupProtocolsPageConnections() { + QJsonObject openvpnConfig; connect(ui->pushButton_proto_openvpn_cont_openvpn_config, &QPushButton::clicked, this, [this](){ + //updateOpenVpnPage(m_settings.server(selectedServerIndex).value()); goToPage(Page::OpenVpnSettings); }); connect(ui->pushButton_proto_ss_openvpn_cont_openvpn_config, &QPushButton::clicked, this, [this](){ @@ -781,6 +918,51 @@ void MainWindow::setupProtocolsPage() } +void MainWindow::setupNewServerPageConnections() +{ + connect(ui->pushButton_connect, SIGNAL(clicked(bool)), this, SLOT(onPushButtonConnectClicked(bool))); + connect(ui->pushButton_start_switch_page, &QPushButton::toggled, this, [this](bool toggled){ + if (toggled){ + ui->stackedWidget_start->setCurrentWidget(ui->page_start_new_server); + ui->pushButton_start_switch_page->setText(tr("Import connection")); + } + else { + ui->stackedWidget_start->setCurrentWidget(ui->page_start_import); + ui->pushButton_start_switch_page->setText(tr("Set up your own server")); + } + //goToPage(Page::NewServer); + }); + + connect(ui->pushButton_new_server_connect_key, &QPushButton::toggled, this, [this](bool checked){ + ui->label_new_server_password->setText(checked ? tr("Private key") : tr("Password")); + ui->pushButton_new_server_connect_key->setText(checked ? tr("Connect using SSH password") : tr("Connect using SSH key")); + ui->lineEdit_new_server_password->setVisible(!checked); + ui->textEdit_new_server_ssh_key->setVisible(checked); + }); + + connect(ui->pushButton_new_server_settings_cloak, &QPushButton::toggled, this, [this](bool toggle){ + ui->frame_new_server_settings_cloak->setMaximumHeight(toggle * 200); + if (toggle) + ui->frame_new_server_settings_parent_cloak->layout()->addWidget(ui->frame_new_server_settings_cloak); + else + ui->frame_new_server_settings_parent_cloak->layout()->removeWidget(ui->frame_new_server_settings_cloak); + }); + connect(ui->pushButton_new_server_settings_ss, &QPushButton::toggled, this, [this](bool toggle){ + ui->frame_new_server_settings_ss->setMaximumHeight(toggle * 200); + if (toggle) + ui->frame_new_server_settings_parent_ss->layout()->addWidget(ui->frame_new_server_settings_ss); + else + ui->frame_new_server_settings_parent_ss->layout()->removeWidget(ui->frame_new_server_settings_ss); + }); + connect(ui->pushButton_new_server_settings_openvpn, &QPushButton::toggled, this, [this](bool toggle){ + ui->frame_new_server_settings_openvpn->setMaximumHeight(toggle * 200); + if (toggle) + ui->frame_new_server_settings_parent_openvpn->layout()->addWidget(ui->frame_new_server_settings_openvpn); + else + ui->frame_new_server_settings_parent_openvpn->layout()->removeWidget(ui->frame_new_server_settings_ss); + }); +} + void MainWindow::setTrayState(VpnProtocol::ConnectionState state) { QString resourcesPath = ":/images/tray/%1"; @@ -949,19 +1131,11 @@ void MainWindow::updateSettings() ui->lineEdit_network_settings_dns1->setText(m_settings.primaryDns()); ui->lineEdit_network_settings_dns2->setText(m_settings.secondaryDns()); - ui->listWidget_sites->clear(); for(const QString &site : m_settings.customSites()) { makeSitesListItem(ui->listWidget_sites, site); } - ui->listWidget_servers->clear(); - const QJsonArray &servers = m_settings.serversArray(); - int defaultServer = m_settings.defaultServerIndex(); - - for(int i = 0; i < servers.size(); i++) { - makeServersListItem(ui->listWidget_servers, servers.at(i).toObject(), i == defaultServer, i); - } QJsonObject selectedServer = m_settings.server(selectedServerIndex); QString selectedContainerName = m_settings.defaultContainerName(selectedServerIndex); @@ -974,7 +1148,20 @@ void MainWindow::updateSettings() ui->pushButton_proto_openvpn_cont_default->setChecked(m_settings.defaultContainer(selectedServerIndex) == DockerContainer::OpenVpn); } -void MainWindow::updateShareCode() +void MainWindow::updateServersPage() +{ + ui->listWidget_servers->clear(); + const QJsonArray &servers = m_settings.serversArray(); + int defaultServer = m_settings.defaultServerIndex(); + + ui->listWidget_servers->setUpdatesEnabled(false); + for(int i = 0; i < servers.size(); i++) { + makeServersListItem(ui->listWidget_servers, servers.at(i).toObject(), i == defaultServer, i); + } + ui->listWidget_servers->setUpdatesEnabled(true); +} + +void MainWindow::updateShareCodePage() { // QJsonObject o; // o.insert("h", m_settings.serverName()); @@ -988,6 +1175,24 @@ void MainWindow::updateShareCode() //qDebug() << "Share code" << QJsonDocument(o).toJson(); } +void MainWindow::updateOpenVpnPage(const QJsonObject &openvpnConfig) +{ + ui->lineEdit_proto_openvpn_subnet->setText(nonEmpty(openvpnConfig.value(config_key::subnet_address).toString(), + protocols::vpnDefaultSubnetAddress)); + + QString trasnsport = nonEmpty(openvpnConfig.value(config_key::transport_protocol).toString(), + protocols::openvpn::openvpnDefaultProto); + + ui->radioButton_proto_openvpn_udp->setChecked(trasnsport == protocols::openvpn::openvpnDefaultProto); + ui->radioButton_proto_openvpn_tcp->setChecked(trasnsport != protocols::openvpn::openvpnDefaultProto); + + ui->comboBox_proto_openvpn_cipher->setCurrentText(nonEmpty(openvpnConfig.value(config_key::cipher).toString(), + protocols::openvpn::openvpnDefaultCipher)); + + ui->comboBox_proto_openvpn_cipher->setCurrentText(nonEmpty(openvpnConfig.value(config_key::hash).toString(), + protocols::openvpn::openvpnDefaultHash)); +} + void MainWindow::makeSitesListItem(QListWidget *listWidget, const QString &address) { QSize size(310, 25); @@ -1021,11 +1226,13 @@ void MainWindow::makeServersListItem(QListWidget *listWidget, const QJsonObject { QSize size(310, 70); ServerWidget* widget = new ServerWidget(server, isDefault); + widget->resize(size); connect(widget->ui->pushButton_default, &QPushButton::clicked, this, [this, index](){ m_settings.setDefaultServer(index); updateSettings(); + updateServersPage(); }); connect(widget->ui->pushButton_share, &QPushButton::clicked, this, [this, index](){ diff --git a/client/ui/mainwindow.h b/client/ui/mainwindow.h index 45c56a51d..7079514b8 100644 --- a/client/ui/mainwindow.h +++ b/client/ui/mainwindow.h @@ -40,7 +40,7 @@ public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); - enum Page {Start, NewServer, Vpn, GeneralSettings, AppSettings, NetworkSettings, + enum Page {Start, NewServer, NewServer_2, Vpn, GeneralSettings, AppSettings, NetworkSettings, ServerSettings, ServerVpnProtocols, ServersList, ShareConnection, Sites, OpenVpnSettings, ShadowSocksSettings, CloakSettings}; Q_ENUM(Page) @@ -51,8 +51,9 @@ private slots: void onVpnProtocolError(amnezia::ErrorCode errorCode); void onPushButtonConnectClicked(bool checked); - void onPushButtonNewServerConnectWithNewData(bool); - void onPushButtonNewServerConnectWithExistingCode(bool); + void onPushButtonNewServerConnect(bool); + void onPushButtonNewServerConnectConfigure(bool); + void onPushButtonNewServerImport(bool); void onPushButtonReinstallServer(bool); void onPushButtonClearServer(bool); @@ -77,21 +78,26 @@ private: QWidget *getPageWidget(Page page); Page currentPage(); - bool installServer(ServerCredentials credentials, QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info); + bool installServer(ServerCredentials credentials, QList containers, QJsonArray configs, + QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info); void setupTray(); void setTrayIcon(const QString &iconPath); void setupUiConnections(); - void setupProtocolsPage(); + void setupProtocolsPageConnections(); + void setupNewServerPageConnections(); void updateSettings(); + void updateServersPage(); + void updateShareCodePage(); + void updateOpenVpnPage(const QJsonObject &openvpnConfig); - void updateShareCode(); void makeSitesListItem(QListWidget* listWidget, const QString &address); void makeServersListItem(QListWidget* listWidget, const QJsonObject &server, bool isDefault, int index); void updateQRCodeImage(const QString &text, QLabel *label); + private: Ui::MainWindow *ui; VpnConnection* m_vpnConnection; @@ -123,6 +129,7 @@ private: QStack pagesStack; int selectedServerIndex = -1; // server index to use when proto settings page opened + ServerCredentials installCredentials; // used to save cred between pages new_server and new_server_2 }; #endif // MAINWINDOW_H diff --git a/client/ui/mainwindow.ui b/client/ui/mainwindow.ui index 1764970b8..b0d8d7742 100644 --- a/client/ui/mainwindow.ui +++ b/client/ui/mainwindow.ui @@ -14,7 +14,12 @@ - QWidget { + QMainWindow { + background: white; +} + + +QWidget { font-family: "Lato"; } @@ -282,62 +287,9 @@ QPushButton:hover { - 1 + 12 - - - - 10 - 50 - 361 - 71 - - - - font-family: Lato; -font-style: normal; -font-weight: bold; -font-size: 24px; -line-height: 25px; -color: #100A44; - - - - Connect to the already created VPN server - - - Qt::AlignCenter - - - true - - - - - - 40 - 130 - 171 - 21 - - - - font-family: Lato; -font-style: normal; -font-weight: normal; -font-size: 16px; -line-height: 150%; - -/* or 24px */ - -/* text */ -color: #333333; - - - Connection code - - @@ -354,69 +306,11 @@ color: #333333; - + 40 - 160 - 300 - 40 - - - - - - - - - - vpn://... - - - - - - 40 - 220 - 301 - 40 - - - - PointingHandCursor - - - QPushButton { - font-size: 13pt; - font: "Open Sans Semibold"; - 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; -} - -QPushButton:hover { -background: #211966; -} - - - - Connect - - - - - - 40 - 320 + 530 301 40 @@ -448,6 +342,9 @@ border-radius: 4px; Set up your own server + + true + @@ -481,6 +378,400 @@ QPushButton:hover { + + + + 0 + 35 + 380 + 481 + + + + + + + 40 + 210 + 301 + 40 + + + + PointingHandCursor + + + QPushButton { + font-size: 13pt; + font: "Open Sans Semibold"; + 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; +} + +QPushButton:hover { +background: #211966; +} + + + + Connect + + + + + + 40 + 140 + 300 + 40 + + + + + + + + + + vpn://... + + + + + + 0 + 20 + 381 + 71 + + + + QLabel { +font-family: Lato; +font-style: normal; +font-weight: bold; +font-size: 24px; +color: #100A44; +} + + + + Connect to the already created VPN server + + + Qt::AlignCenter + + + true + + + + + + 40 + 110 + 301 + 21 + + + + + + + Connection code + + + + + + + + 40 + 260 + 300 + 71 + + + + + + + <!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:'Lato'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16px;"><br /></p></body></html> + + + + + + 50 + 40 + 281 + 21 + + + + PointingHandCursor + + + font-family: Lato; +font-style: normal; +font-weight: normal; +font-size: 16px; +line-height: 20px; +text-align: center; + +/* акцент */ +color: #15CDCB; + + + Where to get connection data → + + + + + true + + + + 40 + 400 + 301 + 41 + + + + Please wait, configuring process may take up to 5 minutes + + + true + + + + + + 10 + 0 + 361 + 31 + + + + QLabel { +font-family: Lato; +font-style: normal; +font-weight: bold; +font-size: 24px; +color: #100A44; +} + + + + Setup your server to use VPN + + + Qt::AlignCenter + + + true + + + + + + 40 + 100 + 300 + 40 + + + + + + + + + + + + + 40 + 350 + 301 + 40 + + + + PointingHandCursor + + + QPushButton { +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; +} +QPushButton:hover { +background: #211966; +} + + + Connect + + + + + + 40 + 180 + 300 + 40 + + + + + + + root + + + + + + 40 + 450 + 281 + 21 + + + + PointingHandCursor + + + font-family: Lato; +font-style: normal; +font-weight: normal; +font-size: 16px; +line-height: 20px; +text-align: center; + +/* акцент */ +color: #15CDCB; + + + Connect using SSH key + + + true + + + true + + + + + + 40 + 260 + 300 + 40 + + + + QLineEdit { + background: #F4F4F4; + border: 1px solid #A7A7A7; + color: #333333; +} + + + + + + QLineEdit::Password + + + + + + 40 + 70 + 171 + 21 + + + + + + + Server IP address + + + + + + 40 + 150 + 261 + 21 + + + + + + + Login to connect via SSH + + + + + + 40 + 230 + 171 + 21 + + + + + + + Password + + + textEdit_new_server_ssh_key + pushButton_new_server_get_info + label_new_server_wait_info + lineEdit_new_server_ip + pushButton_new_server_connect + lineEdit_new_server_login + pushButton_new_server_connect_key + lineEdit_new_server_password + label_4 + label_5 + label_new_server_password + label_2 + + @@ -497,269 +788,6 @@ padding-left: 10px; border: 1px solid #A7A7A7; } - - - - 10 - 40 - 361 - 71 - - - - font-family: Lato; -font-style: normal; -font-weight: bold; -font-size: 24px; -line-height: 25px; -color: #100A44; - - - - Connect your server to use VPN - - - Qt::AlignCenter - - - true - - - - - - 40 - 150 - 171 - 21 - - - - font-family: Lato; -font-style: normal; -font-weight: normal; -font-size: 16px; -line-height: 150%; - -/* or 24px */ - -/* text */ -color: #333333; - - - Server IP address - - - - - - 40 - 235 - 261 - 21 - - - - font-family: Lato; -font-style: normal; -font-weight: normal; -font-size: 16px; -line-height: 150%; - -/* or 24px */ - -/* text */ -color: #333333; - - - Login to connect via SSH - - - - - - 40 - 320 - 171 - 21 - - - - font-family: Lato; -font-style: normal; -font-weight: normal; -font-size: 16px; -line-height: 150%; - -/* or 24px */ - -/* text */ -color: #333333; - - - Password - - - - - - 40 - 180 - 300 - 40 - - - - - - - - - - - - - 40 - 265 - 300 - 40 - - - - - - - root - - - - - - 40 - 350 - 300 - 40 - - - - background: #F4F4F4; - -/* grey */ -border: 1px solid #A7A7A7; -color: #333333; - - - - - - QLineEdit::Password - - - - - - 40 - 450 - 301 - 40 - - - - PointingHandCursor - - - QPushButton { -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; -} -QPushButton:hover { -background: #211966; -} - - - Connect - - - - - - 50 - 115 - 281 - 21 - - - - PointingHandCursor - - - font-family: Lato; -font-style: normal; -font-weight: normal; -font-size: 16px; -line-height: 20px; -text-align: center; - -/* акцент */ -color: #15CDCB; - - - Where to get connection data → - - - - - - 40 - 450 - 301 - 41 - - - - 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... - - @@ -808,93 +836,638 @@ QPushButton:hover { - - - true - + + + - 40 - 500 - 301 + 10 + 30 + 361 41 + + font-family: Lato; +font-style: normal; +font-weight: bold; +font-size: 24px; +line-height: 25px; +color: #100A44; + + - Please wait, configuring process may take up to 5 minutes + Select VPN protocols to install + + + Qt::AlignCenter true - + - 40 - 550 - 281 - 21 + 10 + 10 + 26 + 20 PointingHandCursor - font-family: Lato; -font-style: normal; -font-weight: normal; -font-size: 16px; -line-height: 20px; -text-align: center; + QPushButton { + image: url(:/images/arrow_right.png); + image-position: left; + text-align: left; + /*font: 17pt "Ancient";*/ -/* акцент */ -color: #15CDCB; + padding: 1px; + image: url(:/images/arrow_left.png); +} +QPushButton:hover { + padding: 0px; +} + + - Connect using SSH key - - - true - - - true + - + - 40 - 350 - 300 - 81 + 0 + 80 + 381 + 491 - + QScrollArea { background: transparent; } +QScrollArea > QWidget > QWidget { background: transparent; } +QScrollArea > QWidget > QScrollBar { background: palette(base); } + +QLineEdit { +background: transparent; +} +QPushButton { + text-align: left; + background-repeat:no-repeat; + background-position:left top; + + background-image: url(:/images/settings.png); + padding-left: 30px; + min-height: 24px; +} +QFrame { +background: transparent; +border: 1px solid lightgrey; +border-radius: 2px; +} +QFrame#scrollArea_server_protocols { +border: none; +} +QLabel { +border: none; +} - - <!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:'Lato'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16px;"><br /></p></body></html> + + true + + + + + 0 + 0 + 379 + 489 + + + + + 19 + + + + + + 0 + 0 + + + + + 0 + 100 + + + + + + + + QLayout::SetMinAndMaxSize + + + 9 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + OpenVPN and ShadowSocks + with masking using Cloak plugin + + + true + + + + + + + + 24 + 24 + + + + PointingHandCursor + + + + + + true + + + + + + + + + + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + Port (TCP) + + + + + + + 443 + + + + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + Fake Web Site + + + + + + + mail.ru + + + + + + + + + + + + + + 0 + 100 + + + + + + + + QLayout::SetMinAndMaxSize + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 24 + + + + ShadowSocks + + + + + + + + 24 + 24 + + + + PointingHandCursor + + + + + + true + + + + + + + + + + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + Port(TCP) + + + + + + + 6789 + + + + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + Encryption + + + + + + + + aes-256-gcm + + + + + aes-192-gcm + + + + + aes-128-gcm + + + + + chacha20-ietf-poly1305 + + + + + xchacha20-ietf-poly1305 + + + + + + + + + + + + + + + 0 + 100 + + + + + + + + QLayout::SetMinAndMaxSize + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 24 + + + + OpenVPN + + + + + + + + 24 + 24 + + + + PointingHandCursor + + + + + + true + + + + + + + + + + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + Port + + + + + + + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + Protocol + + + + + + + + UDP + + + + + TCP + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + + + + + + + 40 + 580 + 301 + 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... + + + + + + 40 + 580 + 301 + 40 + + + + PointingHandCursor + + + QPushButton { +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; +} +QPushButton:hover { +background: #211966; +} + + + Setup server - progressBar_new_server_connection - label_2 - label_4 - label_5 - label_new_server_password - lineEdit_new_server_ip - lineEdit_new_server_login - lineEdit_new_server_password - pushButton_new_server_connect_with_new_data - pushButton_new_server_get_info - pushButton_back_from_new_server - label_7 - label_new_server_wait_info - pushButton_new_server_connect_key - textEdit_new_server_ssh_key @@ -3661,8 +4234,8 @@ background: #282932; 0 0 - 360 - 500 + 100 + 30 @@ -3943,7 +4516,7 @@ QPushButton:hover { - + 30 @@ -4007,7 +4580,7 @@ QGroupBox::title { Network protocol - + 10 @@ -4020,7 +4593,7 @@ QGroupBox::title { UDP - + 10 @@ -4034,7 +4607,7 @@ QGroupBox::title { - + 30 @@ -4043,6 +4616,51 @@ QGroupBox::title { 31 + + + AES-256-GCM + + + + + AES-192-GCM + + + + + AES-128-GCM + + + + + AES-256-CBC + + + + + AES-192-CBC + + + + + AES-128-CBC + + + + + ChaCha20-Poly1305 + + + + + ARIA-256-CBC + + + + + CAMELLIA-256-CBC + + @@ -4063,7 +4681,7 @@ QGroupBox::title { true - + 200 @@ -4072,6 +4690,51 @@ QGroupBox::title { 31 + + + SHA512 + + + + + SHA384 + + + + + SHA256 + + + + + SHA3-512 + + + + + SHA3-384 + + + + + SHA3-256 + + + + + whirlpool + + + + + BLAKE2b512 + + + + + BLAKE2s256 + + @@ -4092,7 +4755,7 @@ QGroupBox::title { true - + 30 diff --git a/client/ui/server_widget.cpp b/client/ui/server_widget.cpp index 4c2f445ff..647568af8 100644 --- a/client/ui/server_widget.cpp +++ b/client/ui/server_widget.cpp @@ -2,14 +2,15 @@ #include "ui_server_widget.h" #include "settings.h" +#include "protocols/protocols_defs.h" ServerWidget::ServerWidget(const QJsonObject &server, bool isDefault, QWidget *parent) : QWidget(parent), ui(new Ui::ServerWidget) { ui->setupUi(this); - QString desc = server.value(Settings::descriptionString).toString(); - QString address = server.value(Settings::hostNameString).toString(); + QString desc = server.value(config_key::description).toString(); + QString address = server.value(config_key::hostName).toString(); ui->label_address->setText(address); diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index bd847d3c2..0d05009c9 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -185,6 +185,8 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Prot connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(VpnProtocol::ConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::ConnectionState))); connect(m_vpnProtocol.data(), SIGNAL(bytesChanged(quint64, quint64)), this, SLOT(onBytesChanged(quint64, quint64))); + ServerController::disconnectFromHost(credentials); + return m_vpnProtocol.data()->start(); }