Multiprotocol support
This commit is contained in:
parent
d424bb24cf
commit
de67f244da
44 changed files with 2159 additions and 863 deletions
|
@ -14,6 +14,7 @@ include("3rd/QRCodeGenerator/QRCodeGenerator.pri")
|
|||
HEADERS += \
|
||||
../ipc/ipc.h \
|
||||
configurators/cloak_configurator.h \
|
||||
configurators/shadowsocks_configurator.h \
|
||||
core/defs.h \
|
||||
core/errorstrings.h \
|
||||
core/ipcclient.h \
|
||||
|
@ -39,6 +40,7 @@ HEADERS += \
|
|||
|
||||
SOURCES += \
|
||||
configurators/cloak_configurator.cpp \
|
||||
configurators/shadowsocks_configurator.cpp \
|
||||
core/ipcclient.cpp \
|
||||
configurators/openvpn_configurator.cpp \
|
||||
core/scripts_registry.cpp \
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
QJsonObject CloakConfigurator::genCloakConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode)
|
||||
QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
|
||||
|
@ -21,7 +21,7 @@ QJsonObject CloakConfigurator::genCloakConfig(const ServerCredentials &credentia
|
|||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return QJsonObject();
|
||||
return "";
|
||||
}
|
||||
|
||||
QJsonObject config;
|
||||
|
@ -30,14 +30,18 @@ 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", "$FAKE_WEB_SITE_ADDRESS");
|
||||
config.insert("NumConn", 4);
|
||||
config.insert("BrowserSig", "chrome");
|
||||
config.insert("StreamTimeout", 300);
|
||||
|
||||
// Amnezia field
|
||||
config.insert("Remote", credentials.hostName);
|
||||
// transfer params to protocol runner
|
||||
config.insert(config_key::transport_proto, "$OPENVPN_TRANSPORT_PROTO");
|
||||
config.insert(config_key::remote, credentials.hostName);
|
||||
|
||||
qDebug().noquote() << QJsonDocument(config).toJson();
|
||||
return config;
|
||||
QString textCfg = ServerController::replaceVars(QJsonDocument(config).toJson(),
|
||||
ServerController::genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
// qDebug().noquote() << textCfg;
|
||||
return textCfg;
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ class CloakConfigurator
|
|||
{
|
||||
public:
|
||||
|
||||
static QJsonObject genCloakConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
ErrorCode *errorCode = nullptr);
|
||||
static QString genCloakConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
||||
#endif // CLOAK_CONFIGURATOR_H
|
||||
|
|
|
@ -192,35 +192,16 @@ Settings &OpenVpnConfigurator::m_settings()
|
|||
}
|
||||
|
||||
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode)
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
// QFile configTemplFile;
|
||||
// if (proto == Protocol::OpenVpn)
|
||||
// configTemplFile.setFileName(":/server_scripts/template_openvpn.ovpn");
|
||||
// else if (proto == Protocol::ShadowSocks) {
|
||||
// configTemplFile.setFileName(":/server_scripts/template_shadowsocks.ovpn");
|
||||
// }
|
||||
|
||||
// configTemplFile.open(QIODevice::ReadOnly);
|
||||
// QString config = configTemplFile.readAll();
|
||||
|
||||
QString config = amnezia::scriptData(ProtocolScriptType::openvpn_template, container);
|
||||
QString config = ServerController::replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
|
||||
ServerController::genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode);
|
||||
if (errorCode && *errorCode) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (container == DockerContainer::OpenVpn)
|
||||
config.replace("$PROTO", "udp");
|
||||
else if (container == DockerContainer::ShadowSocksOverOpenVpn) {
|
||||
config.replace("$PROTO", "tcp");
|
||||
config.replace("$LOCAL_PROXY_PORT", amnezia::protocols::shadowsocks::ssLocalProxyPort);
|
||||
}
|
||||
else if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
config.replace("$PROTO", "tcp");
|
||||
}
|
||||
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
|
@ -229,11 +210,11 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
|
|||
}
|
||||
|
||||
config.replace("$REMOTE_HOST", connData.host);
|
||||
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);
|
||||
config.replace("$TA_KEY", connData.taKey);
|
||||
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);
|
||||
config.replace("$OPENVPN_TA_KEY", connData.taKey);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
config.replace("block-outside-dns", "");
|
||||
|
@ -281,13 +262,13 @@ 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::containerToString(container))
|
||||
.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 && "
|
||||
"easyrsa sign-req client %2\"")
|
||||
.arg(amnezia::server::getContainerName(container))
|
||||
.arg(amnezia::containerToString(container))
|
||||
.arg(clientId);
|
||||
|
||||
QStringList scriptList {script_import, script_sign};
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
};
|
||||
|
||||
static QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
ErrorCode *errorCode = nullptr);
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static QString convertOpenSShKey(const QString &key);
|
||||
|
||||
|
|
37
client/configurators/shadowsocks_configurator.cpp
Normal file
37
client/configurators/shadowsocks_configurator.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "shadowsocks_configurator.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
|
||||
QString ssKey = ServerController::getTextFileFromContainer(container, credentials,
|
||||
amnezia::protocols::shadowsocks::ssKeyPath, &e);
|
||||
ssKey.replace("\n", "");
|
||||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return "";
|
||||
}
|
||||
|
||||
QJsonObject config;
|
||||
config.insert("server", credentials.hostName);
|
||||
config.insert("server_port", "$SHADOWSOCKS_SERVER_PORT");
|
||||
config.insert("local_port", "$SHADOWSOCKS_LOCAL_PORT");
|
||||
config.insert("password", ssKey);
|
||||
config.insert("timeout", 60);
|
||||
config.insert("method", "$SHADOWSOCKS_CIPHER");
|
||||
|
||||
|
||||
QString textCfg = ServerController::replaceVars(QJsonDocument(config).toJson(),
|
||||
ServerController::genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
qDebug().noquote() << textCfg;
|
||||
return textCfg;
|
||||
}
|
18
client/configurators/shadowsocks_configurator.h
Normal file
18
client/configurators/shadowsocks_configurator.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef SHADOWSOCKS_CONFIGURATOR_H
|
||||
#define SHADOWSOCKS_CONFIGURATOR_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "settings.h"
|
||||
#include "core/servercontroller.h"
|
||||
|
||||
class ShadowSocksConfigurator
|
||||
{
|
||||
public:
|
||||
|
||||
static QString genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
||||
#endif // SHADOWSOCKS_CONFIGURATOR_H
|
|
@ -5,44 +5,6 @@
|
|||
#include <QObject>
|
||||
|
||||
namespace amnezia {
|
||||
Q_NAMESPACE
|
||||
|
||||
enum class Protocol {
|
||||
Any,
|
||||
OpenVpn,
|
||||
ShadowSocks,
|
||||
Cloak,
|
||||
WireGuard
|
||||
};
|
||||
Q_ENUM_NS(Protocol)
|
||||
|
||||
inline Protocol protoFromString(QString proto){
|
||||
auto&& metaEnum = QMetaEnum::fromType<Protocol>();
|
||||
return static_cast<Protocol>(metaEnum.keyToValue(proto.toStdString().c_str()));
|
||||
}
|
||||
|
||||
inline QString protoToString(Protocol proto){
|
||||
return QVariant::fromValue(proto).toString();
|
||||
}
|
||||
|
||||
|
||||
enum class DockerContainer {
|
||||
None,
|
||||
OpenVpn,
|
||||
ShadowSocksOverOpenVpn,
|
||||
OpenVpnOverCloak,
|
||||
WireGuard
|
||||
};
|
||||
Q_ENUM_NS(DockerContainer)
|
||||
|
||||
inline DockerContainer containerFromString(QString container){
|
||||
auto&& metaEnum = QMetaEnum::fromType<DockerContainer>();
|
||||
return static_cast<DockerContainer>(metaEnum.keyToValue(container.toStdString().c_str()));
|
||||
}
|
||||
|
||||
inline QString containerToString(DockerContainer container){
|
||||
return QVariant::fromValue(container).toString();
|
||||
}
|
||||
|
||||
//static DockerContainer containerForProto(Protocol proto)
|
||||
//{
|
||||
|
@ -78,6 +40,7 @@ enum ErrorCode
|
|||
// Server errors
|
||||
ServerCheckFailed,
|
||||
ServerPortAlreadyAllocatedError,
|
||||
ServerContainerMissingError,
|
||||
|
||||
// Ssh connection errors
|
||||
SshSocketError, SshTimeoutError, SshProtocolError,
|
||||
|
|
|
@ -9,7 +9,7 @@ QString amnezia::scriptFolder(amnezia::DockerContainer container)
|
|||
switch (container) {
|
||||
case DockerContainer::OpenVpn: return QLatin1String("openvpn");
|
||||
case DockerContainer::OpenVpnOverCloak: return QLatin1String("openvpn_cloak");
|
||||
case DockerContainer::ShadowSocksOverOpenVpn: return QLatin1String("openvpn_shadowsocks");
|
||||
case DockerContainer::OpenVpnOverShadowSocks: return QLatin1String("openvpn_shadowsocks");
|
||||
case DockerContainer::WireGuard: return QLatin1String("wireguard");
|
||||
default: return "";
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ QString amnezia::scriptName(ProtocolScriptType type)
|
|||
{
|
||||
switch (type) {
|
||||
case ProtocolScriptType::dockerfile: return QLatin1String("Dockerfile");
|
||||
case ProtocolScriptType::run_container: return QLatin1String("run_container.sh");
|
||||
case ProtocolScriptType::configure_container: return QLatin1String("configure_container.sh");
|
||||
case ProtocolScriptType::container_startup: return QLatin1String("start.sh");
|
||||
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
|
||||
|
@ -46,7 +47,11 @@ QString amnezia::scriptData(amnezia::SharedScriptType type)
|
|||
qDebug() << "Error opening script" << fileName;
|
||||
return "";
|
||||
}
|
||||
return file.readAll();
|
||||
QByteArray ba = file.readAll();
|
||||
if (ba.isEmpty()) {
|
||||
qDebug() << "Error, script is empty" << fileName;
|
||||
}
|
||||
return ba;
|
||||
}
|
||||
|
||||
QString amnezia::scriptData(amnezia::ProtocolScriptType type, DockerContainer container)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <QLatin1String>
|
||||
#include "core/defs.h"
|
||||
#include "protocols/protocols_defs.h""
|
||||
|
||||
namespace amnezia {
|
||||
|
||||
|
@ -19,6 +20,7 @@ enum SharedScriptType {
|
|||
enum ProtocolScriptType {
|
||||
// Protocol scripts
|
||||
dockerfile,
|
||||
run_container,
|
||||
configure_container,
|
||||
container_startup,
|
||||
openvpn_template
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#include "server_defs.h"
|
||||
|
||||
QString amnezia::server::getContainerName(amnezia::DockerContainer container)
|
||||
{
|
||||
switch (container) {
|
||||
case(DockerContainer::OpenVpn): return "amnezia-openvpn";
|
||||
case(DockerContainer::OpenVpnOverCloak): return "amnezia-openvpn-cloak";
|
||||
case(DockerContainer::ShadowSocksOverOpenVpn): return "amnezia-shadowsocks";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
//QString amnezia::containerToString(amnezia::DockerContainer container)
|
||||
//{
|
||||
// switch (container) {
|
||||
// case(DockerContainer::OpenVpn): return "amnezia-openvpn";
|
||||
// case(DockerContainer::OpenVpnOverCloak): return "amnezia-openvpn-cloak";
|
||||
// case(DockerContainer::OpenVpnOverShadowSocks): return "amnezia-shadowsocks";
|
||||
// default: return "";
|
||||
// }
|
||||
//}
|
||||
|
||||
QString amnezia::server::getDockerfileFolder(amnezia::DockerContainer container)
|
||||
{
|
||||
return "/opt/amnezia/" + getContainerName(container);
|
||||
return "/opt/amnezia/" + containerToString(container);
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
#define SERVER_DEFS_H
|
||||
|
||||
#include <QObject>
|
||||
#include "core/defs.h"
|
||||
#include "protocols/protocols_defs.h""
|
||||
|
||||
namespace amnezia {
|
||||
namespace server {
|
||||
QString getContainerName(amnezia::DockerContainer container);
|
||||
//QString getContainerName(amnezia::DockerContainer container);
|
||||
QString getDockerfileFolder(amnezia::DockerContainer container);
|
||||
|
||||
}
|
||||
|
|
|
@ -119,41 +119,27 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams,
|
|||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::installDocker(const ServerCredentials &credentials)
|
||||
{
|
||||
// Setup openvpn part
|
||||
QString scriptData = amnezia::scriptData(SharedScriptType::install_docker);
|
||||
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
stdOut += data + "\n";
|
||||
|
||||
if (data.contains("Automatically restart Docker daemon?")) {
|
||||
proc->write("yes\n");
|
||||
}
|
||||
};
|
||||
auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> ) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
|
||||
return runScript(sshParams(credentials),
|
||||
replaceVars(scriptData, genVarsForScript(credentials, DockerContainer::OpenVpnOverCloak)),
|
||||
cbReadStdOut, cbReadStdErr);
|
||||
}
|
||||
|
||||
ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path)
|
||||
{
|
||||
ErrorCode e;
|
||||
QString tmpFileName = QString("/tmp/%1.tmp").arg(Utils::getRandomString(16));
|
||||
uploadFileToHost(credentials, file.toUtf8(), tmpFileName);
|
||||
e = uploadFileToHost(credentials, file.toUtf8(), tmpFileName);
|
||||
if (e) return e;
|
||||
|
||||
QString stdOut;
|
||||
auto cbReadStd = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> ) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
|
||||
genVarsForScript(credentials, container)));
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
|
||||
if (e) return e;
|
||||
if (stdOut.contains("Error: No such container:")) {
|
||||
return ErrorCode::ServerContainerMissingError;
|
||||
}
|
||||
|
||||
runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo shred %1").arg(tmpFileName),
|
||||
|
@ -164,52 +150,6 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
|||
genVarsForScript(credentials, container)));
|
||||
|
||||
return e;
|
||||
|
||||
// QString script = QString("sudo docker exec -i %1 sh -c \"echo \'%2\' > %3\"").
|
||||
// arg(amnezia::server::getContainerName(container)).arg(file).arg(path);
|
||||
|
||||
// qDebug().noquote() << "uploadTextFileToContainer\n" << script;
|
||||
|
||||
// SshConnection *client = connectToHost(sshParams(credentials));
|
||||
// if (client->state() != SshConnection::State::Connected) {
|
||||
// return fromSshConnectionErrorCode(client->errorState());
|
||||
// }
|
||||
|
||||
// QSharedPointer<SshRemoteProcess> proc = client->createRemoteProcess(script.toUtf8());
|
||||
|
||||
// if (!proc) {
|
||||
// qCritical() << "Failed to create SshRemoteProcess, breaking.";
|
||||
// return ErrorCode::SshRemoteProcessCreationError;
|
||||
// }
|
||||
|
||||
// QEventLoop wait;
|
||||
// int exitStatus = -1;
|
||||
|
||||
//// QObject::connect(proc.data(), &SshRemoteProcess::started, &wait, [](){
|
||||
//// qDebug() << "uploadTextFileToContainer started";
|
||||
//// });
|
||||
|
||||
// QObject::connect(proc.data(), &SshRemoteProcess::closed, &wait, [&](int status){
|
||||
// //qDebug() << "Remote process exited with status" << status;
|
||||
// exitStatus = status;
|
||||
// wait.quit();
|
||||
// });
|
||||
|
||||
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){
|
||||
// qDebug().noquote() << proc->readAllStandardOutput();
|
||||
// });
|
||||
|
||||
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, [proc](){
|
||||
// qDebug().noquote() << proc->readAllStandardError();
|
||||
// });
|
||||
|
||||
// proc->start();
|
||||
|
||||
// if (exitStatus < 0) {
|
||||
// wait.exec();
|
||||
// }
|
||||
|
||||
// return fromSshProcessExitStatus(exitStatus);
|
||||
}
|
||||
|
||||
QString ServerController::getTextFileFromContainer(DockerContainer container,
|
||||
|
@ -218,7 +158,7 @@ QString ServerController::getTextFileFromContainer(DockerContainer container,
|
|||
if (errorCode) *errorCode = ErrorCode::NoError;
|
||||
|
||||
QString script = QString("sudo docker exec -i %1 sh -c \"cat \'%2\'\"").
|
||||
arg(amnezia::server::getContainerName(container)).arg(path);
|
||||
arg(amnezia::containerToString(container)).arg(path);
|
||||
|
||||
qDebug().noquote() << "Copy file from container\n" << script;
|
||||
|
||||
|
@ -402,77 +342,151 @@ ErrorCode ServerController::removeContainer(const ServerCredentials &credentials
|
|||
|
||||
ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
ErrorCode e = runScript(sshParams(credentials),
|
||||
replaceVars(amnezia::scriptData(SharedScriptType::install_docker),
|
||||
genVarsForScript(credentials)));
|
||||
qDebug().noquote() << "ServerController::setupContainer" << containerToString(container);
|
||||
qDebug().noquote() << QJsonDocument(config).toJson();
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
|
||||
// e = runScript(sshParams(credentials),
|
||||
// replaceVars(amnezia::scriptData(SharedScriptType::install_docker),
|
||||
// genVarsForScript(credentials)));
|
||||
|
||||
// if (e) return e;
|
||||
|
||||
|
||||
e = prepareHostWorker(credentials, container, config);
|
||||
if (e) return e;
|
||||
|
||||
removeContainer(credentials, container);
|
||||
|
||||
e = buildContainerWorker(credentials, container, config);
|
||||
if (e) return e;
|
||||
|
||||
e = runContainerWorker(credentials, container, config);
|
||||
if (e) return e;
|
||||
|
||||
e = configureContainerWorker(credentials, container, config);
|
||||
if (e) return e;
|
||||
|
||||
return startupContainerWorker(credentials, container, config);
|
||||
|
||||
|
||||
|
||||
|
||||
// if (container == DockerContainer::OpenVpn) {
|
||||
// return setupOpenVpnServer(credentials, config);
|
||||
// }
|
||||
// else if (container == DockerContainer::OpenVpnOverShadowSocks) {
|
||||
// return setupShadowSocksServer(credentials, config);
|
||||
// }
|
||||
// else if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
// return setupOpenVpnOverCloakServer(credentials, config);
|
||||
// }
|
||||
|
||||
// return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &oldConfig, const QJsonObject &newConfig)
|
||||
{
|
||||
if (isReinstallContainerRequred(container, oldConfig, newConfig)) {
|
||||
return setupContainer(credentials, container, newConfig);
|
||||
}
|
||||
else {
|
||||
ErrorCode e = configureContainerWorker(credentials, container, newConfig);
|
||||
if (e) return e;
|
||||
|
||||
return startupContainerWorker(credentials, container, newConfig);
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerController::isReinstallContainerRequred(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig)
|
||||
{
|
||||
if (container == DockerContainer::OpenVpn) {
|
||||
return ErrorCode::NoError;
|
||||
//return setupOpenVpnServer(credentials, config);
|
||||
}
|
||||
else if (container == DockerContainer::ShadowSocksOverOpenVpn) {
|
||||
return setupShadowSocksServer(credentials, config);
|
||||
}
|
||||
else if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
return setupOpenVpnOverCloakServer(credentials, config);
|
||||
const QJsonObject &oldProtoConfig = oldConfig[config_key::openvpn].toObject();
|
||||
const QJsonObject &newProtoConfig = newConfig[config_key::openvpn].toObject();
|
||||
|
||||
if (oldProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) !=
|
||||
newProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto))
|
||||
return true;
|
||||
|
||||
if (oldProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort) !=
|
||||
newProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort))
|
||||
return true;
|
||||
}
|
||||
|
||||
return ErrorCode::NoError;
|
||||
if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
const QJsonObject &oldProtoConfig = oldConfig[config_key::cloak].toObject();
|
||||
const QJsonObject &newProtoConfig = newConfig[config_key::cloak].toObject();
|
||||
|
||||
if (oldProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort) !=
|
||||
newProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
{
|
||||
return ErrorCode::NotImplementedError;
|
||||
//ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
//{
|
||||
// return ErrorCode::NotImplementedError;
|
||||
//}
|
||||
|
||||
// QString scriptData;
|
||||
// QString scriptFileName = ":/server_scripts/setup_openvpn_server.sh";
|
||||
// QFile file(scriptFileName);
|
||||
// if (! file.open(QIODevice::ReadOnly)) return ErrorCode::InternalError;
|
||||
//ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
//{
|
||||
// ErrorCode e;
|
||||
// DockerContainer container = DockerContainer::OpenVpnOverCloak;
|
||||
|
||||
// scriptData = file.readAll();
|
||||
// if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||
|
||||
// QString stdOut;
|
||||
// auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
// stdOut += data + "\n";
|
||||
|
||||
// if (data.contains("Automatically restart Docker daemon?")) {
|
||||
// proc->write("yes\n");
|
||||
// }
|
||||
// };
|
||||
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
// stdOut += data + "\n";
|
||||
// };
|
||||
|
||||
// ErrorCode e = runScript(genVarsForScript(credentials, DockerContainer::OpenVpn), sshParams(credentials), scriptData, cbReadStdOut, cbReadStdErr);
|
||||
// e = prepareHostWorker(credentials, container, config);
|
||||
// if (e) return e;
|
||||
// QApplication::processEvents();
|
||||
|
||||
// if (stdOut.contains("port is already allocated")) return ErrorCode::ServerPortAlreadyAllocatedError;
|
||||
// if (stdOut.contains("Error response from daemon")) return ErrorCode::ServerCheckFailed;
|
||||
// removeContainer(credentials, container);
|
||||
|
||||
// return checkOpenVpnServer(DockerContainer::OpenVpn, credentials);
|
||||
// e = buildContainerWorker(credentials, container, config);
|
||||
// if (e) return e;
|
||||
|
||||
// e = runContainerWorker(credentials, container, config);
|
||||
// if (e) return e;
|
||||
|
||||
// e = configureContainerWorker(credentials, container, config);
|
||||
// if (e) return e;
|
||||
|
||||
// return startupContainerWorker(credentials, container, config);
|
||||
//}
|
||||
|
||||
ErrorCode ServerController::installDockerWorker(const ServerCredentials &credentials, DockerContainer container)
|
||||
{
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
stdOut += data + "\n";
|
||||
|
||||
if (data.contains("Automatically restart Docker daemon?")) {
|
||||
proc->write("yes\n");
|
||||
}
|
||||
};
|
||||
auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> ) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
|
||||
return runScript(sshParams(credentials),
|
||||
replaceVars(amnezia::scriptData(SharedScriptType::install_docker),
|
||||
genVarsForScript(credentials, container)),
|
||||
cbReadStdOut, cbReadStdErr);
|
||||
}
|
||||
|
||||
ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
ErrorCode e;
|
||||
DockerContainer container = DockerContainer::OpenVpnOverCloak;
|
||||
|
||||
// create folder on host
|
||||
e = runScript(sshParams(credentials),
|
||||
return runScript(sshParams(credentials),
|
||||
replaceVars(amnezia::scriptData(SharedScriptType::prepare_host),
|
||||
genVarsForScript(credentials, container)));
|
||||
if (e) return e;
|
||||
}
|
||||
|
||||
uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, DockerContainer::OpenVpnOverCloak).toUtf8(),
|
||||
ErrorCode ServerController::buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
ErrorCode e = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(),
|
||||
amnezia::server::getDockerfileFolder(container) + "/Dockerfile");
|
||||
|
||||
|
||||
QString scriptData = amnezia::scriptData(SharedScriptType::build_container);
|
||||
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||
if (e) return e;
|
||||
|
||||
// QString stdOut;
|
||||
// auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
|
@ -482,91 +496,118 @@ ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials
|
|||
// stdOut += data + "\n";
|
||||
// };
|
||||
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(scriptData,
|
||||
genVarsForScript(credentials, container)));
|
||||
if (e) return e;
|
||||
|
||||
|
||||
runScript(sshParams(credentials),
|
||||
replaceVars(amnezia::scriptData(ProtocolScriptType::configure_container, DockerContainer::OpenVpnOverCloak),
|
||||
genVarsForScript(credentials, container)));
|
||||
if (e) return e;
|
||||
|
||||
uploadTextFileToContainer(DockerContainer::OpenVpnOverCloak, credentials,
|
||||
replaceVars(amnezia::scriptData(ProtocolScriptType::container_startup, DockerContainer::OpenVpnOverCloak),
|
||||
genVarsForScript(credentials, container)),
|
||||
"/opt/amnezia/start.sh");
|
||||
|
||||
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)));
|
||||
if (e) return e;
|
||||
|
||||
return e;
|
||||
return runScript(sshParams(credentials),
|
||||
replaceVars(amnezia::scriptData(SharedScriptType::build_container),
|
||||
genVarsForScript(credentials, container, config)));
|
||||
}
|
||||
|
||||
ErrorCode ServerController::setupShadowSocksServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
return ErrorCode::NotImplementedError;
|
||||
// // Setup openvpn part
|
||||
// QString scriptData;
|
||||
// QString scriptFileName = ":/server_scripts/setup_shadowsocks_server.sh";
|
||||
// QFile file(scriptFileName);
|
||||
// if (! file.open(QIODevice::ReadOnly)) return ErrorCode::InternalError;
|
||||
|
||||
// scriptData = file.readAll();
|
||||
// if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||
|
||||
// QString stdOut;
|
||||
// auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
// stdOut += data + "\n";
|
||||
|
||||
// if (data.contains("Automatically restart Docker daemon?")) {
|
||||
// proc->write("yes\n");
|
||||
// }
|
||||
// };
|
||||
// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
// stdOut += data + "\n";
|
||||
// };
|
||||
|
||||
// ErrorCode e = runScript(genVarsForScript(credentials, DockerContainer::ShadowSocks), sshParams(credentials), scriptData, cbReadStdOut, cbReadStdErr);
|
||||
// if (e) return e;
|
||||
|
||||
// // Create ss config
|
||||
// QJsonObject ssConfig;
|
||||
// ssConfig.insert("server", "0.0.0.0");
|
||||
// ssConfig.insert("server_port", amnezia::protocols::shadowsocks::ssRemotePort());
|
||||
// ssConfig.insert("local_port", amnezia::protocols::shadowsocks::ssContainerPort());
|
||||
// ssConfig.insert("password", QString(QCryptographicHash::hash(credentials.password.toUtf8(), QCryptographicHash::Sha256).toHex()));
|
||||
// ssConfig.insert("timeout", 60);
|
||||
// ssConfig.insert("method", amnezia::protocols::shadowsocks::ssEncryption());
|
||||
// QString configData = QJsonDocument(ssConfig).toJson();
|
||||
// QString sSConfigPath = "/opt/amneziavpn_data/ssConfig.json";
|
||||
|
||||
// configData.replace("\"", "\\\"");
|
||||
// //qDebug().noquote() << configData;
|
||||
|
||||
// uploadTextFileToContainer(DockerContainer::ShadowSocks, credentials, configData, sSConfigPath);
|
||||
|
||||
// // Start ss
|
||||
// QString script = QString("sudo docker exec -d %1 sh -c \"ss-server -c %2\"").
|
||||
// arg(amnezia::server::getContainerName(DockerContainer::ShadowSocks)).arg(sSConfigPath);
|
||||
|
||||
// e = runScript(genVarsForScript(credentials, DockerContainer::ShadowSocks), sshParams(credentials), script);
|
||||
// return e;
|
||||
return runScript(sshParams(credentials),
|
||||
replaceVars(amnezia::scriptData(ProtocolScriptType::run_container, container),
|
||||
genVarsForScript(credentials, container, config)));
|
||||
}
|
||||
|
||||
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
return runScript(sshParams(credentials),
|
||||
replaceVars(amnezia::scriptData(ProtocolScriptType::configure_container, container),
|
||||
genVarsForScript(credentials, container, config)));
|
||||
}
|
||||
|
||||
ErrorCode ServerController::startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
ErrorCode e = uploadTextFileToContainer(container, credentials,
|
||||
replaceVars(amnezia::scriptData(ProtocolScriptType::container_startup, container),
|
||||
genVarsForScript(credentials, container, config)),
|
||||
"/opt/amnezia/start.sh");
|
||||
if (e) return e;
|
||||
|
||||
return 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, config)));
|
||||
}
|
||||
|
||||
//ErrorCode ServerController::setupShadowSocksServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
//{
|
||||
// return ErrorCode::NotImplementedError;
|
||||
//// // Setup openvpn part
|
||||
//// QString scriptData;
|
||||
//// QString scriptFileName = ":/server_scripts/setup_shadowsocks_server.sh";
|
||||
//// QFile file(scriptFileName);
|
||||
//// if (! file.open(QIODevice::ReadOnly)) return ErrorCode::InternalError;
|
||||
|
||||
//// scriptData = file.readAll();
|
||||
//// if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||
|
||||
//// QString stdOut;
|
||||
//// auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
//// stdOut += data + "\n";
|
||||
|
||||
//// if (data.contains("Automatically restart Docker daemon?")) {
|
||||
//// proc->write("yes\n");
|
||||
//// }
|
||||
//// };
|
||||
//// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
//// stdOut += data + "\n";
|
||||
//// };
|
||||
|
||||
//// ErrorCode e = runScript(genVarsForScript(credentials, DockerContainer::ShadowSocks), sshParams(credentials), scriptData, cbReadStdOut, cbReadStdErr);
|
||||
//// if (e) return e;
|
||||
|
||||
//// // Create ss config
|
||||
//// QJsonObject ssConfig;
|
||||
//// ssConfig.insert("server", "0.0.0.0");
|
||||
//// ssConfig.insert("server_port", amnezia::protocols::shadowsocks::ssRemotePort());
|
||||
//// ssConfig.insert("local_port", amnezia::protocols::shadowsocks::ssContainerPort());
|
||||
//// ssConfig.insert("password", QString(QCryptographicHash::hash(credentials.password.toUtf8(), QCryptographicHash::Sha256).toHex()));
|
||||
//// ssConfig.insert("timeout", 60);
|
||||
//// ssConfig.insert("method", amnezia::protocols::shadowsocks::ssEncryption());
|
||||
//// QString configData = QJsonDocument(ssConfig).toJson();
|
||||
//// QString sSConfigPath = "/opt/amneziavpn_data/ssConfig.json";
|
||||
|
||||
//// configData.replace("\"", "\\\"");
|
||||
//// //qDebug().noquote() << configData;
|
||||
|
||||
//// uploadTextFileToContainer(DockerContainer::ShadowSocks, credentials, configData, sSConfigPath);
|
||||
|
||||
//// // Start ss
|
||||
//// QString script = QString("sudo docker exec -d %1 sh -c \"ss-server -c %2\"").
|
||||
//// arg(amnezia::containerToString(DockerContainer::ShadowSocks)).arg(sSConfigPath);
|
||||
|
||||
//// e = runScript(genVarsForScript(credentials, DockerContainer::ShadowSocks), sshParams(credentials), script);
|
||||
// // return e;
|
||||
//}
|
||||
|
||||
ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
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();
|
||||
//
|
||||
|
||||
Vars vars;
|
||||
|
||||
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) }});
|
||||
// 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) }});
|
||||
vars.append({{"$VPN_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(amnezia::protocols::vpnDefaultSubnetMask) }});
|
||||
|
||||
vars.append({{"$CONTAINER_NAME", amnezia::server::getContainerName(container)}});
|
||||
vars.append({{"$DOCKERFILE_FOLDER", "/opt/amnezia/" + amnezia::server::getContainerName(container)}});
|
||||
vars.append({{"$OPENVPN_PORT", openvpnConfig.value(config_key::port).toString(amnezia::protocols::openvpn::defaultPort) }});
|
||||
vars.append({{"$OPENVPN_TRANSPORT_PROTO", openvpnConfig.value(config_key::transport_proto).toString(amnezia::protocols::openvpn::defaultTransportProto) }});
|
||||
|
||||
bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(amnezia::protocols::openvpn::defaultNcpDisable);
|
||||
vars.append({{"$OPENVPN_NCP_DISABLE", isNcpDisabled ? protocols::openvpn::ncpDisableString : "" }});
|
||||
vars.append({{"$OPENVPN_CIPHER", openvpnConfig.value(config_key::cipher).toString(amnezia::protocols::openvpn::defaultCipher) }});
|
||||
vars.append({{"$OPENVPN_HASH", openvpnConfig.value(config_key::hash).toString(amnezia::protocols::openvpn::defaultHash) }});
|
||||
|
||||
// ShadowSocks vars
|
||||
vars.append({{"$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(amnezia::protocols::shadowsocks::defaultPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_LOCAL_PORT", ssConfig.value(config_key::local_port).toString(amnezia::protocols::shadowsocks::defaultLocalProxyPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_CIPHER", ssConfig.value(config_key::cipher).toString(amnezia::protocols::shadowsocks::defaultCipher) }});
|
||||
|
||||
vars.append({{"$CONTAINER_NAME", amnezia::containerToString(container)}});
|
||||
vars.append({{"$DOCKERFILE_FOLDER", "/opt/amnezia/" + amnezia::containerToString(container)}});
|
||||
|
||||
QString serverIp = Utils::getIPAddress(credentials.hostName);
|
||||
if (!serverIp.isEmpty()) {
|
||||
|
@ -576,22 +617,19 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
|||
qWarning() << "ServerController::genVarsForScript unable to resolve address for credentials.hostName";
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
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({{"$DOCKER_PORT", nonEmpty(config.value(config_key::port).toString(), protocols::openvpn::openvpnDefaultPort) }});
|
||||
vars.append({{"$DOCKER_PORT", config.value(config_key::port).toString(protocols::openvpn::defaultPort) }});
|
||||
}
|
||||
else if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
vars.append({{"$DOCKER_PORT", nonEmpty(config.value(config_key::port).toString(), protocols::cloak::ckDefaultPort) }});
|
||||
vars.append({{"$DOCKER_PORT", config.value(config_key::port).toString(protocols::cloak::defaultPort) }});
|
||||
|
||||
vars.append({{"$FAKE_WEB_SITE_ADDRESS", nonEmpty(cloakConfig.value(config_key::site).toString(), protocols::cloak::ckDefaultRedirSite) }});
|
||||
vars.append({{"$FAKE_WEB_SITE_ADDRESS", cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) }});
|
||||
}
|
||||
else if (container == DockerContainer::ShadowSocksOverOpenVpn) {
|
||||
vars.append({{"$DOCKER_PORT", nonEmpty(config.value(config_key::port).toString(), protocols::shadowsocks::ssDefaultPort) }});
|
||||
else if (container == DockerContainer::OpenVpnOverShadowSocks) {
|
||||
vars.append({{"$DOCKER_PORT", config.value(config_key::port).toString(protocols::shadowsocks::defaultPort) }});
|
||||
}
|
||||
|
||||
return vars;
|
||||
|
@ -686,7 +724,7 @@ QString ServerController::replaceVars(const QString &script, const Vars &vars)
|
|||
{
|
||||
QString s = script;
|
||||
for (const QPair<QString, QString> &var : vars) {
|
||||
//qDebug() << "Replacing" << var << vars.value(var);
|
||||
//qDebug() << "Replacing" << var.first << var.second;
|
||||
s.replace(var.first, var.second);
|
||||
}
|
||||
return s;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "sshconnection.h"
|
||||
#include "sshremoteprocess.h"
|
||||
#include "defs.h"
|
||||
#include "protocols/protocols_defs.h""
|
||||
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
|
@ -26,6 +28,10 @@ public:
|
|||
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 updateContainer(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &oldConfig, const QJsonObject &newConfig = QJsonObject());
|
||||
|
||||
static bool isReinstallContainerRequred(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig);
|
||||
|
||||
static ErrorCode checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials);
|
||||
|
||||
|
@ -51,11 +57,18 @@ public:
|
|||
private:
|
||||
static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
||||
|
||||
static ErrorCode installDocker(const ServerCredentials &credentials);
|
||||
static ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
|
||||
|
||||
//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());
|
||||
|
||||
static ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
static ErrorCode buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
static ErrorCode runContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
static ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
static ErrorCode startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
|
||||
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
|
||||
|
|
|
@ -37,9 +37,13 @@ ErrorCode OpenVpnOverCloakProtocol::start()
|
|||
m_cloakCfgFile.close();
|
||||
|
||||
QStringList args = QStringList() << "-c" << m_cloakCfgFile.fileName()
|
||||
<< "-s" << m_cloakConfig.value("Remote").toString()
|
||||
<< "-p" << amnezia::protocols::cloak::ckDefaultPort
|
||||
<< "-l" << amnezia::protocols::openvpn::openvpnDefaultPort;
|
||||
<< "-s" << m_cloakConfig.value(config_key::remote).toString()
|
||||
<< "-p" << amnezia::protocols::cloak::defaultPort
|
||||
<< "-l" << amnezia::protocols::openvpn::defaultPort;
|
||||
|
||||
if (m_cloakConfig.value(config_key::transport_proto).toString() == protocols::UDP) {
|
||||
args << "-u";
|
||||
}
|
||||
|
||||
qDebug().noquote() << "OpenVpnOverCloakProtocol::start()"
|
||||
<< cloakExecPath() << args.join(" ");
|
||||
|
|
|
@ -4,78 +4,148 @@
|
|||
#include <QObject>
|
||||
|
||||
namespace amnezia {
|
||||
|
||||
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";
|
||||
constexpr char hostName[] = "hostName";
|
||||
constexpr char userName[] = "userName";
|
||||
constexpr char password[] = "password";
|
||||
constexpr char port[] = "port";
|
||||
constexpr char local_port[] = "local_port";
|
||||
|
||||
constexpr char description[] = "description";
|
||||
|
||||
|
||||
const char containers[] = "containers";
|
||||
const char container[] = "container";
|
||||
const char defaultContainer[] = "defaultContainer";
|
||||
constexpr char containers[] = "containers";
|
||||
constexpr char container[] = "container";
|
||||
constexpr char defaultContainer[] = "defaultContainer";
|
||||
|
||||
const char protocols[] = "protocols";
|
||||
const char protocol[] = "protocol";
|
||||
constexpr char protocols[] = "protocols";
|
||||
//constexpr char protocol[] = "protocol";
|
||||
|
||||
const char transport_protocol[] = "transport_protocol";
|
||||
const char cipher[] = "cipher";
|
||||
const char hash[] = "hash";
|
||||
constexpr char remote[] = "remote";
|
||||
constexpr char transport_proto[] = "transport_proto";
|
||||
constexpr char cipher[] = "cipher";
|
||||
constexpr char hash[] = "hash";
|
||||
constexpr char ncp_disable[] = "ncp_disable";
|
||||
|
||||
const char site[] = "site";
|
||||
constexpr char site[] = "site";
|
||||
constexpr char block_outside_dns[] = "block_outside_dns";
|
||||
|
||||
const char subnet_address[] = "subnet_address";
|
||||
const char subnet_mask[] = "subnet_mask";
|
||||
const char subnet_mask_val[] = "subnet_mask_val";
|
||||
constexpr char subnet_address[] = "subnet_address";
|
||||
constexpr char subnet_mask[] = "subnet_mask";
|
||||
constexpr char subnet_mask_val[] = "subnet_mask_val";
|
||||
|
||||
const char openvpn[] = "openvpn";
|
||||
const char shadowsocks[] = "shadowsocks";
|
||||
const char cloak[] = "cloak";
|
||||
// proto config keys
|
||||
constexpr char last_config[] = "last_config";
|
||||
|
||||
constexpr char openvpn[] = "openvpn";
|
||||
constexpr char shadowsocks[] = "shadowsocks";
|
||||
constexpr char cloak[] = "cloak";
|
||||
constexpr char wireguard[] = "wireguard";
|
||||
|
||||
// containers config keys
|
||||
constexpr char amnezia_openvpn[] = "amnezia-openvpn";
|
||||
constexpr char amnezia_shadowsocks[] = "amnezia-shadowsocks";
|
||||
constexpr char amnezia_openvpn_cloak[] = "amnezia-openvpn-cloak";
|
||||
constexpr char amnezia_wireguard[] = "amnezia-wireguard";
|
||||
}
|
||||
|
||||
namespace protocols {
|
||||
|
||||
const char vpnDefaultSubnetAddress[] = "10.8.0.0";
|
||||
const char vpnDefaultSubnetMask[] = "255.255.255.0";
|
||||
const char vpnDefaultSubnetMaskVal[] = "24";
|
||||
constexpr char vpnDefaultSubnetAddress[] = "10.8.0.0";
|
||||
constexpr char vpnDefaultSubnetMask[] = "255.255.255.0";
|
||||
constexpr char vpnDefaultSubnetMaskVal[] = "24";
|
||||
|
||||
constexpr char UDP[] = "udp"; // case sens
|
||||
constexpr char TCP[] = "tcp";
|
||||
|
||||
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;
|
||||
constexpr char caCertPath[] = "/opt/amnezia/openvpn/pki/ca.crt";
|
||||
constexpr char clientCertPath[] = "/opt/amnezia/openvpn/pki/issued";
|
||||
constexpr char taKeyPath[] = "/opt/amnezia/openvpn/ta.key";
|
||||
constexpr char clientsDirPath[] = "/opt/amnezia/openvpn/clients";
|
||||
constexpr char defaultPort[] = "1194";
|
||||
constexpr char defaultTransportProto[] = amnezia::protocols::UDP;
|
||||
constexpr char defaultCipher[] = "AES-256-GCM";
|
||||
constexpr char defaultHash[] = "SHA512";
|
||||
constexpr bool defaultBlockOutsideDns = true;
|
||||
constexpr bool defaultNcpDisable = false;
|
||||
constexpr char ncpDisableString[] = "ncp-disable";
|
||||
|
||||
}
|
||||
|
||||
namespace shadowsocks {
|
||||
const char ssDefaultPort[] = "6789";
|
||||
const char ssLocalProxyPort[] = "8585";
|
||||
const char ssDefaultCipher[] = "chacha20-ietf-poly1305";
|
||||
constexpr char ssKeyPath[] = "/opt/amnezia/shadowsocks/shadowsocks.key";
|
||||
constexpr char defaultPort[] = "6789";
|
||||
constexpr char defaultLocalProxyPort[] = "8585";
|
||||
constexpr char defaultCipher[] = "chacha20-ietf-poly1305";
|
||||
}
|
||||
|
||||
namespace cloak {
|
||||
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";
|
||||
constexpr char ckPublicKeyPath[] = "/opt/amnezia/cloak/cloak_public.key";
|
||||
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";
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace protocols
|
||||
|
||||
enum class Protocol {
|
||||
Any,
|
||||
OpenVpn,
|
||||
ShadowSocks,
|
||||
Cloak,
|
||||
WireGuard
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
OpenVpn,
|
||||
OpenVpnOverShadowSocks,
|
||||
OpenVpnOverCloak,
|
||||
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;
|
||||
}
|
||||
|
||||
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 "";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace amnezia
|
||||
|
||||
#endif // PROTOCOLS_DEFS_H
|
||||
|
|
|
@ -96,18 +96,6 @@ QString ShadowSocksVpnProtocol::shadowSocksExecPath()
|
|||
#endif
|
||||
}
|
||||
|
||||
QJsonObject ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container)
|
||||
{
|
||||
QJsonObject ssConfig;
|
||||
ssConfig.insert("server", credentials.hostName);
|
||||
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::ssDefaultCipher);
|
||||
return ssConfig;
|
||||
}
|
||||
|
||||
void ShadowSocksVpnProtocol::readShadowSocksConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
m_shadowSocksConfig = configuration.value(config::key_shadowsocks_config_data).toObject();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "openvpnprotocol.h"
|
||||
#include "QProcess"
|
||||
#include "protocols/protocols_defs.h""
|
||||
|
||||
class ShadowSocksVpnProtocol : public OpenVpnProtocol
|
||||
{
|
||||
|
@ -13,8 +14,6 @@ public:
|
|||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
static QJsonObject genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container = DockerContainer::ShadowSocksOverOpenVpn);
|
||||
|
||||
protected:
|
||||
void readShadowSocksConfiguration(const QJsonObject &configuration);
|
||||
|
||||
|
|
|
@ -34,11 +34,7 @@
|
|||
<file>images/server_settings.png</file>
|
||||
<file>images/share.png</file>
|
||||
<file>server_scripts/remove_container.sh</file>
|
||||
<file>server_scripts/setup_openvpn_server.sh</file>
|
||||
<file>server_scripts/template_openvpn.ovpn</file>
|
||||
<file>images/background_connected.png</file>
|
||||
<file>server_scripts/setup_shadowsocks_server.sh</file>
|
||||
<file>server_scripts/template_shadowsocks.ovpn</file>
|
||||
<file>server_scripts/setup_host_firewall.sh</file>
|
||||
<file>images/reload.png</file>
|
||||
<file>server_scripts/openvpn_cloak/Dockerfile</file>
|
||||
|
@ -54,5 +50,16 @@
|
|||
<file>images/plus.png</file>
|
||||
<file>server_scripts/check_connection.sh</file>
|
||||
<file>server_scripts/remove_all_containers.sh</file>
|
||||
<file>server_scripts/openvpn_cloak/run_container.sh</file>
|
||||
<file>server_scripts/openvpn/configure_container.sh</file>
|
||||
<file>server_scripts/openvpn/run_container.sh</file>
|
||||
<file>server_scripts/openvpn/template.ovpn</file>
|
||||
<file>server_scripts/openvpn/Dockerfile</file>
|
||||
<file>server_scripts/openvpn/start.sh</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/configure_container.sh</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/Dockerfile</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/run_container.sh</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/start.sh</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/template.ovpn</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
49
client/server_scripts/openvpn/Dockerfile
Normal file
49
client/server_scripts/openvpn/Dockerfile
Normal file
|
@ -0,0 +1,49 @@
|
|||
FROM alpine:latest
|
||||
|
||||
LABEL maintainer="AmneziaVPN"
|
||||
|
||||
#Install required packages
|
||||
RUN apk add --no-cache curl openvpn easy-rsa bash netcat-openbsd dumb-init rng-tools
|
||||
RUN apk --update upgrade --no-cache
|
||||
|
||||
ENV EASYRSA_BATCH 1
|
||||
ENV PATH="/usr/share/easy-rsa:${PATH}"
|
||||
|
||||
RUN mkdir -p /opt/amnezia
|
||||
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
|
||||
RUN chmod a+x /opt/amnezia/start.sh
|
||||
|
||||
# Tune network
|
||||
RUN echo -e " \n\
|
||||
fs.file-max = 51200 \n\
|
||||
\n\
|
||||
net.core.rmem_max = 67108864 \n\
|
||||
net.core.wmem_max = 67108864 \n\
|
||||
net.core.netdev_max_backlog = 250000 \n\
|
||||
net.core.somaxconn = 4096 \n\
|
||||
\n\
|
||||
net.ipv4.tcp_syncookies = 1 \n\
|
||||
net.ipv4.tcp_tw_reuse = 1 \n\
|
||||
net.ipv4.tcp_tw_recycle = 0 \n\
|
||||
net.ipv4.tcp_fin_timeout = 30 \n\
|
||||
net.ipv4.tcp_keepalive_time = 1200 \n\
|
||||
net.ipv4.ip_local_port_range = 10000 65000 \n\
|
||||
net.ipv4.tcp_max_syn_backlog = 8192 \n\
|
||||
net.ipv4.tcp_max_tw_buckets = 5000 \n\
|
||||
net.ipv4.tcp_fastopen = 3 \n\
|
||||
net.ipv4.tcp_mem = 25600 51200 102400 \n\
|
||||
net.ipv4.tcp_rmem = 4096 87380 67108864 \n\
|
||||
net.ipv4.tcp_wmem = 4096 65536 67108864 \n\
|
||||
net.ipv4.tcp_mtu_probing = 1 \n\
|
||||
net.ipv4.tcp_congestion_control = hybla \n\
|
||||
# for low-latency network, use cubic instead \n\
|
||||
# net.ipv4.tcp_congestion_control = cubic \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/sysctl.conf && \
|
||||
mkdir -p /etc/security && \
|
||||
echo -e " \n\
|
||||
* soft nofile 51200 \n\
|
||||
* hard nofile 51200 \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf
|
||||
|
||||
ENTRYPOINT [ "dumb-init", "/opt/amnezia/start.sh" ]
|
||||
CMD [ "" ]
|
27
client/server_scripts/openvpn/configure_container.sh
Normal file
27
client/server_scripts/openvpn/configure_container.sh
Normal file
|
@ -0,0 +1,27 @@
|
|||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
echo -e "\
|
||||
port $OPENVPN_PORT \\n\
|
||||
proto $OPENVPN_TRANSPORT_PROTO \\n\
|
||||
dev tun \\n\
|
||||
ca /opt/amnezia/openvpn/ca.crt \\n\
|
||||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key \\n\
|
||||
dh /opt/amnezia/openvpn/dh.pem \\n\
|
||||
server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
||||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
$OPENVPN_NCP_DISABLE \\n\
|
||||
cipher $OPENVPN_CIPHER \\n\
|
||||
data-ciphers $OPENVPN_CIPHER \\n\
|
||||
auth $OPENVPN_HASH \\n\
|
||||
user nobody \\n\
|
||||
group nobody \\n\
|
||||
persist-key \\n\
|
||||
persist-tun \\n\
|
||||
status openvpn-status.log \\n\
|
||||
verb 1 \\n\
|
||||
tls-server \\n\
|
||||
tls-version-min 1.2 \\n\
|
||||
tls-auth /opt/amnezia/openvpn/ta.key 0" >>/opt/amnezia/openvpn/server.conf'
|
||||
|
18
client/server_scripts/openvpn/run_container.sh
Normal file
18
client/server_scripts/openvpn/run_container.sh
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Run container
|
||||
sudo docker run -d --restart always --cap-add=NET_ADMIN -p $OPENVPN_PORT:$OPENVPN_PORT/$OPENVPN_TRANSPORT_PROTO --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'
|
||||
|
||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||
|
||||
# OpenVPN config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /opt/amnezia/openvpn/clients; \
|
||||
cd /opt/amnezia/openvpn && easyrsa init-pki; \
|
||||
cd /opt/amnezia/openvpn && easyrsa gen-dh; \
|
||||
cd /opt/amnezia/openvpn && cp pki/dh.pem /opt/amnezia/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req AmneziaReq nopass << EOF2 yes EOF2;\
|
||||
cd /opt/amnezia/openvpn && easyrsa sign-req server AmneziaReq << EOF3 yes EOF3;\
|
||||
cd /opt/amnezia/openvpn && openvpn --genkey --secret ta.key << EOF4;\
|
||||
cd /opt/amnezia/openvpn && cp pki/ca.crt pki/issued/AmneziaReq.crt pki/private/AmneziaReq.key /opt/amnezia/openvpn'
|
||||
|
26
client/server_scripts/openvpn/start.sh
Normal file
26
client/server_scripts/openvpn/start.sh
Normal file
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container startup"
|
||||
|
||||
if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net; mknod /dev/net/tun c 10 200; fi
|
||||
|
||||
# Allow traffic on the TUN interface.
|
||||
iptables -A INPUT -i tun0 -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -j ACCEPT
|
||||
iptables -A OUTPUT -o tun0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i tun0 -o eth0 -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -j ACCEPT
|
||||
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
iptables -t nat -A POSTROUTING -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
|
||||
# start daemons if configured
|
||||
if [ -f /opt/amnezia/openvpn/ca.crt ]; then (openvpn --config /opt/amnezia/openvpn/server.conf --daemon); fi
|
||||
|
||||
tail -f /dev/null
|
|
@ -1,12 +1,13 @@
|
|||
client
|
||||
dev tun
|
||||
proto $PROTO
|
||||
proto $OPENVPN_TRANSPORT_PROTO
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
cipher AES-256-GCM
|
||||
auth SHA512
|
||||
$OPENVPN_NCP_DISABLE
|
||||
cipher $OPENVPN_CIPHER
|
||||
auth $OPENVPN_HASH
|
||||
verb 3
|
||||
tls-client
|
||||
tls-version-min 1.2
|
||||
|
@ -21,14 +22,14 @@ block-outside-dns
|
|||
remote $REMOTE_HOST $REMOTE_PORT
|
||||
|
||||
<ca>
|
||||
$CA_CERT
|
||||
$OPENVPN_CA_CERT
|
||||
</ca>
|
||||
<cert>
|
||||
$CLIENT_CERT
|
||||
$OPENVPN_CLIENT_CERT
|
||||
</cert>
|
||||
<key>
|
||||
$PRIV_KEY
|
||||
$OPENVPN_PRIV_KEY
|
||||
</key>
|
||||
<tls-auth>
|
||||
$TA_KEY
|
||||
$OPENVPN_TA_KEY
|
||||
</tls-auth>
|
|
@ -1,35 +1,7 @@
|
|||
# CONTAINER_NAME=... this var will be set in ServerController
|
||||
# Don't run commands in background like sh -c "openvpn &"
|
||||
# SERVER_PORT=443
|
||||
|
||||
#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 $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 $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'
|
||||
|
||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||
|
||||
# OpenVPN config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /opt/amnezia/openvpn/clients; \
|
||||
cd /opt/amnezia/openvpn && easyrsa init-pki; \
|
||||
cd /opt/amnezia/openvpn && easyrsa gen-dh; \
|
||||
cd /opt/amnezia/openvpn && cp pki/dh.pem /opt/amnezia/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req AmneziaReq nopass << EOF2 yes EOF2;\
|
||||
cd /opt/amnezia/openvpn && easyrsa sign-req server AmneziaReq << EOF3 yes EOF3;\
|
||||
cd /opt/amnezia/openvpn && openvpn --genkey --secret ta.key << EOF4;\
|
||||
cd /opt/amnezia/openvpn && cp pki/ca.crt pki/issued/AmneziaReq.crt pki/private/AmneziaReq.key /opt/amnezia/openvpn'
|
||||
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
echo -e "\
|
||||
port 1194 \\n\
|
||||
proto tcp \\n\
|
||||
port $OPENVPN_PORT \\n\
|
||||
proto $OPENVPN_TRANSPORT_PROTO \\n\
|
||||
dev tun \\n\
|
||||
ca /opt/amnezia/openvpn/ca.crt \\n\
|
||||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
|
@ -39,9 +11,10 @@ server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
|||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
cipher AES-256-GCM \\n\
|
||||
ncp-ciphers AES-256-GCM:AES-256-CBC \\n\
|
||||
auth SHA512 \\n\
|
||||
$OPENVPN_NCP_DISABLE \\n\
|
||||
cipher $OPENVPN_CIPHER \\n\
|
||||
data-ciphers $OPENVPN_CIPHER \\n\
|
||||
auth $OPENVPN_HASH \\n\
|
||||
user nobody \\n\
|
||||
group nobody \\n\
|
||||
persist-key \\n\
|
||||
|
@ -52,8 +25,6 @@ tls-server \\n\
|
|||
tls-version-min 1.2 \\n\
|
||||
tls-auth /opt/amnezia/openvpn/ta.key 0" >>/opt/amnezia/openvpn/server.conf'
|
||||
|
||||
#sudo docker exec -d $CONTAINER_NAME sh -c "openvpn --config /opt/amnezia/openvpn/server.conf"
|
||||
|
||||
# Cloak config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
mkdir -p /opt/amnezia/cloak; \
|
||||
|
@ -66,8 +37,8 @@ echo $CLOAK_PRIVATE_KEY > /opt/amnezia/cloak/cloak_private.key; \
|
|||
echo -e "{\\n\
|
||||
\"ProxyBook\": {\\n\
|
||||
\"openvpn\": [\\n\
|
||||
\"tcp\",\\n\
|
||||
\"localhost:1194\"\\n\
|
||||
\"$OPENVPN_TRANSPORT_PROTO\",\\n\
|
||||
\"localhost:$OPENVPN_PORT\"\\n\
|
||||
]\\n\
|
||||
},\\n\
|
||||
\"BypassUID\": [\\n\
|
||||
|
@ -79,6 +50,4 @@ echo -e "{\\n\
|
|||
\"AdminUID\": \"$CLOAK_ADMIN_UID\",\\n\
|
||||
\"DatabasePath\": \"userinfo.db\",\\n\
|
||||
\"StreamTimeout\": 300\\n\
|
||||
}" >>/opt/amnezia/cloak/ck-config.json'
|
||||
|
||||
#sudo docker exec -d $CONTAINER_NAME sh -c "/usr/bin/ck-server -c /opt/amnezia/cloak/ck-config.json"
|
||||
}" >/opt/amnezia/cloak/ck-config.json'
|
||||
|
|
17
client/server_scripts/openvpn_cloak/run_container.sh
Normal file
17
client/server_scripts/openvpn_cloak/run_container.sh
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Run container
|
||||
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'
|
||||
|
||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||
|
||||
# OpenVPN config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /opt/amnezia/openvpn/clients; \
|
||||
cd /opt/amnezia/openvpn && easyrsa init-pki; \
|
||||
cd /opt/amnezia/openvpn && easyrsa gen-dh; \
|
||||
cd /opt/amnezia/openvpn && cp pki/dh.pem /opt/amnezia/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req AmneziaReq nopass << EOF2 yes EOF2;\
|
||||
cd /opt/amnezia/openvpn && easyrsa sign-req server AmneziaReq << EOF3 yes EOF3;\
|
||||
cd /opt/amnezia/openvpn && openvpn --genkey --secret ta.key << EOF4;\
|
||||
cd /opt/amnezia/openvpn && cp pki/ca.crt pki/issued/AmneziaReq.crt pki/private/AmneziaReq.key /opt/amnezia/openvpn'
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container Startup start"
|
||||
echo "Container startup"
|
||||
|
||||
if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net; mknod /dev/net/tun c 10 200; fi
|
||||
|
||||
|
@ -17,6 +17,11 @@ iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|||
|
||||
iptables -t nat -A POSTROUTING -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
killall -KILL ck-server
|
||||
|
||||
# start daemons if configured
|
||||
if [ -f /opt/amnezia/openvpn/ca.crt ]; then (openvpn --config /opt/amnezia/openvpn/server.conf --daemon); fi
|
||||
if [ -f /opt/amnezia/cloak/ck-config.json ]; then (ck-server -c /opt/amnezia/cloak/ck-config.json &); fi
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
client
|
||||
dev tun
|
||||
proto $PROTO
|
||||
proto $OPENVPN_TRANSPORT_PROTO
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
cipher AES-256-GCM
|
||||
auth SHA512
|
||||
$OPENVPN_NCP_DISABLE
|
||||
cipher $OPENVPN_CIPHER
|
||||
auth $OPENVPN_HASH
|
||||
verb 3
|
||||
tls-client
|
||||
tls-version-min 1.2
|
||||
|
@ -22,14 +23,14 @@ route $REMOTE_HOST 255.255.255.255 net_gateway
|
|||
remote 127.0.0.1 1194
|
||||
|
||||
<ca>
|
||||
$CA_CERT
|
||||
$OPENVPN_CA_CERT
|
||||
</ca>
|
||||
<cert>
|
||||
$CLIENT_CERT
|
||||
$OPENVPN_CLIENT_CERT
|
||||
</cert>
|
||||
<key>
|
||||
$PRIV_KEY
|
||||
$OPENVPN_PRIV_KEY
|
||||
</key>
|
||||
<tls-auth>
|
||||
$TA_KEY
|
||||
$OPENVPN_TA_KEY
|
||||
</tls-auth>
|
||||
|
|
53
client/server_scripts/openvpn_shadowsocks/Dockerfile
Normal file
53
client/server_scripts/openvpn_shadowsocks/Dockerfile
Normal file
|
@ -0,0 +1,53 @@
|
|||
FROM alpine:latest
|
||||
|
||||
LABEL maintainer="AmneziaVPN"
|
||||
|
||||
#Install required packages
|
||||
RUN apk add --no-cache curl openvpn easy-rsa bash netcat-openbsd dumb-init rng-tools xz
|
||||
RUN apk --update upgrade --no-cache
|
||||
|
||||
ENV EASYRSA_BATCH 1
|
||||
ENV PATH="/usr/share/easy-rsa:${PATH}"
|
||||
|
||||
RUN mkdir -p /opt/amnezia
|
||||
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
|
||||
RUN chmod a+x /opt/amnezia/start.sh
|
||||
|
||||
RUN curl -L https://github.com/shadowsocks/shadowsocks-rust/releases/download/v1.10.9/shadowsocks-v1.10.9.x86_64-unknown-linux-musl.tar.xz > /usr/bin/ss.tar.xz
|
||||
RUN tar -Jxvf /usr/bin/ss.tar.xz -C /usr/bin/
|
||||
RUN chmod a+x /usr/bin/ssserver
|
||||
|
||||
# Tune network
|
||||
RUN echo -e " \n\
|
||||
fs.file-max = 51200 \n\
|
||||
\n\
|
||||
net.core.rmem_max = 67108864 \n\
|
||||
net.core.wmem_max = 67108864 \n\
|
||||
net.core.netdev_max_backlog = 250000 \n\
|
||||
net.core.somaxconn = 4096 \n\
|
||||
\n\
|
||||
net.ipv4.tcp_syncookies = 1 \n\
|
||||
net.ipv4.tcp_tw_reuse = 1 \n\
|
||||
net.ipv4.tcp_tw_recycle = 0 \n\
|
||||
net.ipv4.tcp_fin_timeout = 30 \n\
|
||||
net.ipv4.tcp_keepalive_time = 1200 \n\
|
||||
net.ipv4.ip_local_port_range = 10000 65000 \n\
|
||||
net.ipv4.tcp_max_syn_backlog = 8192 \n\
|
||||
net.ipv4.tcp_max_tw_buckets = 5000 \n\
|
||||
net.ipv4.tcp_fastopen = 3 \n\
|
||||
net.ipv4.tcp_mem = 25600 51200 102400 \n\
|
||||
net.ipv4.tcp_rmem = 4096 87380 67108864 \n\
|
||||
net.ipv4.tcp_wmem = 4096 65536 67108864 \n\
|
||||
net.ipv4.tcp_mtu_probing = 1 \n\
|
||||
net.ipv4.tcp_congestion_control = hybla \n\
|
||||
# for low-latency network, use cubic instead \n\
|
||||
# net.ipv4.tcp_congestion_control = cubic \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/sysctl.conf && \
|
||||
mkdir -p /etc/security && \
|
||||
echo -e " \n\
|
||||
* soft nofile 51200 \n\
|
||||
* hard nofile 51200 \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf
|
||||
|
||||
ENTRYPOINT [ "dumb-init", "/opt/amnezia/start.sh" ]
|
||||
CMD [ "" ]
|
|
@ -0,0 +1,40 @@
|
|||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
echo -e "\
|
||||
port $OPENVPN_PORT \\n\
|
||||
proto tcp \\n\
|
||||
dev tun \\n\
|
||||
ca /opt/amnezia/openvpn/ca.crt \\n\
|
||||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key \\n\
|
||||
dh /opt/amnezia/openvpn/dh.pem \\n\
|
||||
server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
||||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
$OPENVPN_NCP_DISABLE \\n\
|
||||
cipher $OPENVPN_CIPHER \\n\
|
||||
data-ciphers $OPENVPN_CIPHER \\n\
|
||||
auth $OPENVPN_HASH \\n\
|
||||
user nobody \\n\
|
||||
group nobody \\n\
|
||||
persist-key \\n\
|
||||
persist-tun \\n\
|
||||
status openvpn-status.log \\n\
|
||||
verb 1 \\n\
|
||||
tls-server \\n\
|
||||
tls-version-min 1.2 \\n\
|
||||
tls-auth /opt/amnezia/openvpn/ta.key 0" >>/opt/amnezia/openvpn/server.conf'
|
||||
|
||||
# Cloak config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
mkdir -p /opt/amnezia/shadowsocks; \
|
||||
cd /opt/amnezia/shadowsocks || exit 1; \
|
||||
SHADOWSOCKS_PASSWORD=$(openssl rand -base64 32 | tr "=" "A" | tr "+" "A" | tr "/" "A") && echo $SHADOWSOCKS_PASSWORD > /opt/amnezia/shadowsocks/shadowsocks.key; \
|
||||
echo -e "{\\n\
|
||||
\"local_port\": 8585,\\n\
|
||||
\"method\": \"$SHADOWSOCKS_CIPHER\",\\n\
|
||||
\"password\": \"$SHADOWSOCKS_PASSWORD\",\\n\
|
||||
\"server\": \"0.0.0.0\",\\n\
|
||||
\"server_port\": $SHADOWSOCKS_SERVER_PORT,\\n\
|
||||
\"timeout\": 60\\n\
|
||||
}" >/opt/amnezia/shadowsocks/ss-config.json'
|
17
client/server_scripts/openvpn_shadowsocks/run_container.sh
Normal file
17
client/server_scripts/openvpn_shadowsocks/run_container.sh
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Run container
|
||||
sudo docker run -d --restart always --cap-add=NET_ADMIN -p $SHADOWSOCKS_SERVER_PORT:$SHADOWSOCKS_SERVER_PORT/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'
|
||||
|
||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||
|
||||
# OpenVPN config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /opt/amnezia/openvpn/clients; \
|
||||
cd /opt/amnezia/openvpn && easyrsa init-pki; \
|
||||
cd /opt/amnezia/openvpn && easyrsa gen-dh; \
|
||||
cd /opt/amnezia/openvpn && cp pki/dh.pem /opt/amnezia/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req AmneziaReq nopass << EOF2 yes EOF2;\
|
||||
cd /opt/amnezia/openvpn && easyrsa sign-req server AmneziaReq << EOF3 yes EOF3;\
|
||||
cd /opt/amnezia/openvpn && openvpn --genkey --secret ta.key << EOF4;\
|
||||
cd /opt/amnezia/openvpn && cp pki/ca.crt pki/issued/AmneziaReq.crt pki/private/AmneziaReq.key /opt/amnezia/openvpn'
|
27
client/server_scripts/openvpn_shadowsocks/start.sh
Normal file
27
client/server_scripts/openvpn_shadowsocks/start.sh
Normal file
|
@ -0,0 +1,27 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container startup"
|
||||
|
||||
if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net; mknod /dev/net/tun c 10 200; fi
|
||||
|
||||
# Allow traffic on the TUN interface.
|
||||
iptables -A INPUT -i tun0 -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -j ACCEPT
|
||||
iptables -A OUTPUT -o tun0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i tun0 -o eth0 -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -j ACCEPT
|
||||
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
iptables -t nat -A POSTROUTING -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
killall -KILL ssserver
|
||||
|
||||
# start daemons if configured
|
||||
if [ -f /opt/amnezia/openvpn/ca.crt ]; then (openvpn --config /opt/amnezia/openvpn/server.conf --daemon); fi
|
||||
if [ -f /opt/amnezia/shadowsocks/ss-config.json ]; then (ssserver -c /opt/amnezia/shadowsocks/ss-config.json &); fi
|
||||
tail -f /dev/null
|
|
@ -1,12 +1,13 @@
|
|||
client
|
||||
dev tun
|
||||
proto $PROTO
|
||||
proto tcp
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
cipher AES-256-GCM
|
||||
auth SHA512
|
||||
$OPENVPN_NCP_DISABLE
|
||||
cipher $OPENVPN_CIPHER
|
||||
auth $OPENVPN_HASH
|
||||
verb 3
|
||||
tls-client
|
||||
tls-version-min 1.2
|
||||
|
@ -18,19 +19,19 @@ dhcp-option DNS $PRIMARY_DNS
|
|||
dhcp-option DNS $SECONDARY_DNS
|
||||
block-outside-dns
|
||||
|
||||
socks-proxy 127.0.0.1 $LOCAL_PROXY_PORT
|
||||
socks-proxy 127.0.0.1 $SHADOWSOCKS_LOCAL_PORT
|
||||
route $REMOTE_HOST 255.255.255.255 net_gateway
|
||||
remote $REMOTE_HOST $REMOTE_PORT
|
||||
|
||||
<ca>
|
||||
$CA_CERT
|
||||
$OPENVPN_CA_CERT
|
||||
</ca>
|
||||
<cert>
|
||||
$CLIENT_CERT
|
||||
$OPENVPN_CLIENT_CERT
|
||||
</cert>
|
||||
<key>
|
||||
$PRIV_KEY
|
||||
$OPENVPN_PRIV_KEY
|
||||
</key>
|
||||
<tls-auth>
|
||||
$TA_KEY
|
||||
$OPENVPN_TA_KEY
|
||||
</tls-auth>
|
|
@ -1,3 +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
|
||||
sudo docker images -a | grep amnezia | awk '{print $3}' | xargs sudo docker rmi
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
# CONTAINER_NAME=... this var will be set in ServerController
|
||||
# Don't run commands in background like sh -c "openvpn &"
|
||||
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi
|
||||
sudo iptables -P FORWARD ACCEPT
|
||||
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; sudo $pm update -y -q
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; sudo $pm install -y -q curl
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then sudo export DEBIAN_FRONTEND=noninteractive; sudo $pm_apt install -y -q docker.io; else sudo $pm_yum install -y -q docker; fi
|
||||
sudo systemctl start docker
|
||||
|
||||
sudo docker stop $CONTAINER_NAME
|
||||
sudo docker rm -f $CONTAINER_NAME
|
||||
sudo docker pull amneziavpn/openvpn:latest
|
||||
sudo docker run -d --restart always --cap-add=NET_ADMIN -p 1194:1194/udp --name $CONTAINER_NAME amneziavpn/openvpn:latest
|
||||
|
||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "mkdir -p /opt/amneziavpn_data/clients"
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa init-pki"
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa gen-dh"
|
||||
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && cp pki/dh.pem /etc/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req MyReq nopass << EOF2 yes EOF2"
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa sign-req server MyReq << EOF3 yes EOF3"
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && openvpn --genkey --secret ta.key << EOF4"
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && cp pki/ca.crt pki/issued/MyReq.crt pki/private/MyReq.key ta.key /etc/openvpn"
|
||||
sudo docker exec -d $CONTAINER_NAME sh -c "openvpn --config /etc/openvpn/server.conf"
|
|
@ -1,29 +0,0 @@
|
|||
# CONTAINER_NAME=... this var will be set in ServerController
|
||||
# Don't run commands in background like sh -c "openvpn &"
|
||||
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi
|
||||
sudo iptables -P FORWARD ACCEPT
|
||||
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; sudo $pm update -y -q
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; sudo $pm install -y -q curl
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then sudo export DEBIAN_FRONTEND=noninteractive; sudo $pm_apt install -y -q docker.io; else sudo $pm_yum install -y -q docker; fi
|
||||
sudo systemctl start docker
|
||||
|
||||
sudo docker stop $CONTAINER_NAME
|
||||
sudo docker rm -f $CONTAINER_NAME
|
||||
sudo docker pull amneziavpn/shadowsocks:latest
|
||||
sudo docker run -d --restart always --cap-add=NET_ADMIN -p 6789:6789/tcp --name $CONTAINER_NAME amneziavpn/shadowsocks:latest
|
||||
|
||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||
|
||||
# OpenVpn
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /opt/amneziavpn_data/clients;\
|
||||
cd /opt/amneziavpn_data && easyrsa init-pki;\
|
||||
cd /opt/amneziavpn_data && easyrsa gen-dh;\
|
||||
cd /opt/amneziavpn_data && cp pki/dh.pem /etc/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req MyReq nopass << EOF2 yes EOF2;\
|
||||
cd /opt/amneziavpn_data && easyrsa sign-req server MyReq << EOF3 yes EOF3;\
|
||||
cd /opt/amneziavpn_data && openvpn --genkey --secret ta.key << EOF4;\
|
||||
cd /opt/amneziavpn_data && cp pki/ca.crt pki/issued/MyReq.crt pki/private/MyReq.key ta.key /etc/openvpn'
|
||||
|
||||
sudo docker exec -d $CONTAINER_NAME sh -c "openvpn --config /etc/openvpn/server.conf"
|
|
@ -88,33 +88,112 @@ QString Settings::defaultContainerName(int serverIndex) const
|
|||
else return name;
|
||||
}
|
||||
|
||||
QMap<DockerContainer, QJsonObject> Settings::containers(int serverIndex) const
|
||||
{
|
||||
const QJsonArray &containers = server(serverIndex).value(config_key::containers).toArray();
|
||||
|
||||
QMap<DockerContainer, QJsonObject> containersMap;
|
||||
for (const QJsonValue &val : containers) {
|
||||
containersMap.insert(containerFromString(val.toObject().value(config_key::container).toString()), val.toObject());
|
||||
}
|
||||
|
||||
return containersMap;
|
||||
}
|
||||
|
||||
void Settings::setContainers(int serverIndex, const QMap<DockerContainer, QJsonObject> &containers)
|
||||
{
|
||||
QJsonObject s = server(serverIndex);
|
||||
QJsonArray c;
|
||||
for (const QJsonObject &o: containers) {
|
||||
c.append(o);
|
||||
}
|
||||
s.insert(config_key::containers, c);
|
||||
editServer(serverIndex, s);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
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;
|
||||
|
||||
auto c = containers(serverIndex);
|
||||
c[container] = config;
|
||||
c[container][config_key::container] = containerToString(container);
|
||||
setContainers(serverIndex, c);
|
||||
}
|
||||
|
||||
void Settings::removeContainerConfig(int serverIndex, DockerContainer container)
|
||||
{
|
||||
if (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);
|
||||
return c.value(protoToString(proto)).toObject();
|
||||
}
|
||||
|
||||
switch (proto) {
|
||||
case Protocol::OpenVpn:
|
||||
return c.value(config_key::openvpn).toObject();
|
||||
case Protocol::ShadowSocks:
|
||||
return c.value(config_key::shadowsocks).toObject();
|
||||
case Protocol::Cloak:
|
||||
return c.value(config_key::cloak).toObject();
|
||||
default:
|
||||
return QJsonObject();
|
||||
void Settings::setProtocolConfig(int serverIndex, DockerContainer container, Protocol proto, const QJsonObject &config)
|
||||
{
|
||||
QJsonObject c = containerConfig(serverIndex, container);
|
||||
c.insert(protoToString(proto), config);
|
||||
|
||||
setContainerConfig(serverIndex, container, c);
|
||||
}
|
||||
|
||||
void Settings::clearLastConnectionConfig(int serverIndex, DockerContainer container, Protocol proto)
|
||||
{
|
||||
if (proto == Protocol::Any) {
|
||||
for (Protocol p: { Protocol::OpenVpn, Protocol::ShadowSocks, Protocol::Cloak, Protocol::WireGuard}) {
|
||||
clearLastConnectionConfig(serverIndex, container, p);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonObject c = protocolConfig(serverIndex, container, proto);
|
||||
c.remove(config_key::last_config);
|
||||
setProtocolConfig(serverIndex, container, proto, c);
|
||||
qDebug() << "Settings::clearLastConnectionConfig for" << protoToString(proto);
|
||||
}
|
||||
|
||||
bool Settings::haveAuthData() const
|
||||
|
@ -127,7 +206,6 @@ bool Settings::haveAuthData() const
|
|||
QString Settings::nextAvailableServerName() const
|
||||
{
|
||||
int i = 0;
|
||||
//bool found = false;
|
||||
bool nameExist = false;
|
||||
|
||||
do {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <QJsonObject>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
|
@ -57,8 +58,17 @@ public:
|
|||
DockerContainer defaultContainer(int serverIndex) const;
|
||||
QString defaultContainerName(int serverIndex) const;
|
||||
|
||||
QMap<DockerContainer, QJsonObject> containers(int serverIndex) const;
|
||||
void setContainers(int serverIndex, const QMap<DockerContainer, QJsonObject> &containers);
|
||||
|
||||
QJsonObject containerConfig(int serverIndex, DockerContainer container);
|
||||
void setContainerConfig(int serverIndex, DockerContainer container, const QJsonObject &config);
|
||||
void removeContainerConfig(int serverIndex, DockerContainer container);
|
||||
|
||||
QJsonObject protocolConfig(int serverIndex, DockerContainer container, Protocol proto);
|
||||
void setProtocolConfig(int serverIndex, DockerContainer container, Protocol proto, const QJsonObject &config);
|
||||
|
||||
void clearLastConnectionConfig(int serverIndex, DockerContainer container, Protocol proto = Protocol::Any);
|
||||
|
||||
bool haveAuthData() const;
|
||||
QString nextAvailableServerName() const;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QHBoxLayout>
|
||||
#include <QJsonDocument>
|
||||
|
@ -115,11 +116,14 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
|
||||
m_ipAddressValidator.setRegExp(Utils::ipAddressRegExp());
|
||||
m_ipAddressPortValidator.setRegExp(Utils::ipAddressPortRegExp());
|
||||
m_ipNetwok24Validator.setRegExp(Utils::ipNetwork24RegExp());
|
||||
|
||||
ui->lineEdit_new_server_ip->setValidator(&m_ipAddressPortValidator);
|
||||
ui->lineEdit_network_settings_dns1->setValidator(&m_ipAddressValidator);
|
||||
ui->lineEdit_network_settings_dns2->setValidator(&m_ipAddressValidator);
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -148,40 +152,28 @@ void MainWindow::goToPage(Page page, bool reset, bool slide)
|
|||
qDebug() << "goToPage" << page;
|
||||
if (reset) {
|
||||
if (page == Page::ServerSettings) {
|
||||
updateSettings();
|
||||
|
||||
ui->label_server_settings_wait_info->hide();
|
||||
ui->label_server_settings_wait_info->clear();
|
||||
|
||||
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());
|
||||
updateServerPage();
|
||||
}
|
||||
if (page == Page::ShareConnection) {
|
||||
QJsonObject ssConfig = ShadowSocksVpnProtocol::genShadowSocksConfig(m_settings.defaultServerCredentials());
|
||||
// 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()));
|
||||
// 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);
|
||||
// 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());
|
||||
// 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) {
|
||||
updateServersPage();
|
||||
updateServersListPage();
|
||||
}
|
||||
if (page == Page::Start) {
|
||||
ui->label_new_server_wait_info->hide();
|
||||
|
@ -200,14 +192,26 @@ void MainWindow::goToPage(Page page, bool reset, bool slide)
|
|||
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_cloak_port->setText(amnezia::protocols::cloak::defaultPort);
|
||||
ui->lineEdit_new_server_cloak_site->setText(amnezia::protocols::cloak::defaultRedirSite);
|
||||
|
||||
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_ss_port->setText(amnezia::protocols::shadowsocks::defaultPort);
|
||||
ui->comboBox_new_server_ss_cipher->setCurrentText(amnezia::protocols::shadowsocks::defaultCipher);
|
||||
|
||||
ui->lineEdit_new_server_openvpn_port->setText(amnezia::protocols::openvpn::openvpnDefaultPort);
|
||||
ui->comboBox_new_server_openvpn_proto->setCurrentText(amnezia::protocols::openvpn::openvpnDefaultProto);
|
||||
ui->lineEdit_new_server_openvpn_port->setText(amnezia::protocols::openvpn::defaultPort);
|
||||
ui->comboBox_new_server_openvpn_proto->setCurrentText(amnezia::protocols::openvpn::defaultTransportProto);
|
||||
}
|
||||
if (page == Page::ServerVpnProtocols) {
|
||||
updateProtocolsPage();
|
||||
}
|
||||
if (page == Page::AppSettings) {
|
||||
updateAppSettingsPage();
|
||||
}
|
||||
if (page == Page::Sites) {
|
||||
updateSitesPage();
|
||||
}
|
||||
if (page == Page::Vpn) {
|
||||
updateVpnPage();
|
||||
}
|
||||
|
||||
ui->pushButton_new_server_connect_key->setChecked(false);
|
||||
|
@ -424,23 +428,23 @@ 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::container, amnezia::containerToString(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::container, amnezia::containerToString(DockerContainer::OpenVpnOverShadowSocks) },
|
||||
{ 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::container, amnezia::containerToString(DockerContainer::OpenVpn) },
|
||||
{ config_key::openvpn, QJsonObject {
|
||||
{ config_key::transport_protocol, ui->comboBox_new_server_openvpn_proto->currentText() }}
|
||||
{ config_key::transport_proto, ui->comboBox_new_server_openvpn_proto->currentText() }}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -454,20 +458,20 @@ void MainWindow::onPushButtonNewServerConnectConfigure(bool)
|
|||
|
||||
if (ui->checkBox_new_server_ss->isChecked()) {
|
||||
containerConfigs.append(ssConfig);
|
||||
containers.append(DockerContainer::ShadowSocksOverOpenVpn);
|
||||
containers.append(DockerContainer::OpenVpnOverShadowSocks);
|
||||
}
|
||||
|
||||
if (ui->checkBox_new_server_openvpn->isChecked()) {
|
||||
containerConfigs.append(openVpnConfig);
|
||||
containers.append(DockerContainer::ShadowSocksOverOpenVpn);
|
||||
containers.append(DockerContainer::OpenVpnOverShadowSocks);
|
||||
}
|
||||
|
||||
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);
|
||||
// bool ok = true;
|
||||
bool ok = installServer(installCredentials, containers, containerConfigs,
|
||||
ui->page_new_server_2,
|
||||
ui->progressBar_new_server_connection,
|
||||
ui->pushButton_new_server_connect,
|
||||
ui->label_new_server_wait_info);
|
||||
|
||||
if (ok) {
|
||||
QJsonObject server;
|
||||
|
@ -587,6 +591,69 @@ bool MainWindow::installServer(ServerCredentials credentials,
|
|||
return true;
|
||||
}
|
||||
|
||||
ErrorCode MainWindow::doInstallAction(const std::function<ErrorCode()> &action, QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info)
|
||||
{
|
||||
progress->show();
|
||||
if (page) page->setEnabled(false);
|
||||
if (button) button->setVisible(false);
|
||||
|
||||
if (info) info->setVisible(true);
|
||||
if (info) 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 = action();
|
||||
qDebug() << "doInstallAction finished with code" << e;
|
||||
|
||||
if (e) {
|
||||
if (page) page->setEnabled(true);
|
||||
if (button) button->setVisible(true);
|
||||
if (info) info->setVisible(false);
|
||||
|
||||
QMessageBox::warning(this, APPLICATION_NAME,
|
||||
tr("Error occurred while configuring server.") + "\n" +
|
||||
errorString(e));
|
||||
|
||||
progress->hide();
|
||||
return e;
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
progress->hide();
|
||||
if (button) button->show();
|
||||
if (page) page->setEnabled(true);
|
||||
if (info) info->setText(tr("Operation finished"));
|
||||
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
void MainWindow::onPushButtonReinstallServer(bool)
|
||||
{
|
||||
// onDisconnect();
|
||||
|
@ -606,7 +673,7 @@ void MainWindow::onPushButtonClearServer(bool)
|
|||
onDisconnect();
|
||||
}
|
||||
|
||||
ErrorCode e = ServerController::removeContainer(m_settings.serverCredentials(selectedServerIndex), DockerContainer::None);
|
||||
ErrorCode e = ServerController::removeAllContainers(m_settings.serverCredentials(selectedServerIndex));
|
||||
ServerController::disconnectFromHost(m_settings.serverCredentials(selectedServerIndex));
|
||||
if (e) {
|
||||
QMessageBox::warning(this, APPLICATION_NAME,
|
||||
|
@ -630,9 +697,10 @@ void MainWindow::onPushButtonForgetServer(bool)
|
|||
onDisconnect();
|
||||
}
|
||||
m_settings.removeServer(selectedServerIndex);
|
||||
m_settings.setDefaultServer(0);
|
||||
|
||||
closePage();
|
||||
updateServersPage();
|
||||
updateServersListPage();
|
||||
}
|
||||
|
||||
void MainWindow::onBytesChanged(quint64 receivedData, quint64 sentData)
|
||||
|
@ -877,7 +945,7 @@ void MainWindow::setupUiConnections()
|
|||
QJsonObject server = m_settings.server(selectedServerIndex);
|
||||
server.insert(config_key::description, newText);
|
||||
m_settings.editServer(selectedServerIndex, server);
|
||||
updateServersPage();
|
||||
updateServersListPage();
|
||||
});
|
||||
|
||||
connect(ui->lineEdit_server_settings_description, &QLineEdit::returnPressed, this, [this](){
|
||||
|
@ -890,32 +958,128 @@ void MainWindow::setupUiConnections()
|
|||
void MainWindow::setupProtocolsPageConnections()
|
||||
{
|
||||
QJsonObject openvpnConfig;
|
||||
|
||||
// default buttons
|
||||
QList<DockerContainer> containers {
|
||||
DockerContainer::OpenVpn,
|
||||
DockerContainer::OpenVpnOverShadowSocks,
|
||||
DockerContainer::OpenVpnOverCloak
|
||||
};
|
||||
|
||||
// default buttons
|
||||
QList<QPushButton *> defaultButtons {
|
||||
ui->pushButton_proto_openvpn_cont_default,
|
||||
ui->pushButton_proto_ss_openvpn_cont_default,
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default
|
||||
};
|
||||
|
||||
for (int i = 0; i < containers.size(); ++i) {
|
||||
connect(defaultButtons.at(i), &QPushButton::clicked, this, [this, containers, i](){
|
||||
m_settings.setDefaultContainer(selectedServerIndex, containers.at(i));
|
||||
updateProtocolsPage();
|
||||
});
|
||||
}
|
||||
|
||||
// install buttons
|
||||
QList<QPushButton *> installButtons {
|
||||
ui->pushButton_proto_openvpn_cont_install,
|
||||
ui->pushButton_proto_ss_openvpn_cont_install,
|
||||
ui->pushButton_proto_cloak_openvpn_cont_install
|
||||
};
|
||||
|
||||
for (int i = 0; i < containers.size(); ++i) {
|
||||
QPushButton *button = installButtons.at(i);
|
||||
DockerContainer container = containers.at(i);
|
||||
|
||||
connect(button, &QPushButton::clicked, this, [this, container, button](bool checked){
|
||||
if (checked) {
|
||||
ErrorCode e = doInstallAction([this, container](){
|
||||
return ServerController::setupContainer(m_settings.serverCredentials(selectedServerIndex), container);
|
||||
},
|
||||
ui->page_server_protocols, ui->progressBar_protocols_container_reinstall,
|
||||
nullptr, nullptr);
|
||||
|
||||
if (!e) {
|
||||
m_settings.setContainerConfig(selectedServerIndex, container, QJsonObject());
|
||||
}
|
||||
}
|
||||
else {
|
||||
button->setEnabled(false);
|
||||
ErrorCode e = ServerController::removeContainer(m_settings.serverCredentials(selectedServerIndex), container);
|
||||
m_settings.removeContainerConfig(selectedServerIndex, container);
|
||||
button->setEnabled(true);
|
||||
}
|
||||
|
||||
updateProtocolsPage();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// settings buttons
|
||||
|
||||
// settings openvpn container
|
||||
connect(ui->pushButton_proto_openvpn_cont_openvpn_config, &QPushButton::clicked, this, [this](){
|
||||
//updateOpenVpnPage(m_settings.server(selectedServerIndex).value());
|
||||
updateOpenVpnPage(m_settings.protocolConfig(selectedServerIndex, DockerContainer::OpenVpn, Protocol::OpenVpn));
|
||||
selectedDockerContainer = DockerContainer::OpenVpn;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
goToPage(Page::OpenVpnSettings);
|
||||
});
|
||||
|
||||
connect(ui->pushButton_proto_cloak_openvpn_cont_default, &QPushButton::clicked, this, [this](){
|
||||
m_settings.setDefaultContainer(selectedServerIndex, DockerContainer::OpenVpnOverCloak);
|
||||
updateSettings();
|
||||
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;
|
||||
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;
|
||||
goToPage(Page::CloakSettings);
|
||||
});
|
||||
|
||||
connect(ui->pushButton_proto_ss_openvpn_cont_default, &QPushButton::clicked, this, [this](){
|
||||
m_settings.setDefaultContainer(selectedServerIndex, DockerContainer::ShadowSocksOverOpenVpn);
|
||||
updateSettings();
|
||||
///
|
||||
// Protocols pages
|
||||
connect(ui->checkBox_proto_openvpn_auto_encryption, &QCheckBox::stateChanged, this, [this](){
|
||||
ui->comboBox_proto_openvpn_cipher->setDisabled(ui->checkBox_proto_openvpn_auto_encryption->isChecked());
|
||||
ui->comboBox_proto_openvpn_hash->setDisabled(ui->checkBox_proto_openvpn_auto_encryption->isChecked());
|
||||
});
|
||||
|
||||
connect(ui->pushButton_proto_openvpn_cont_default, &QPushButton::clicked, this, [this](){
|
||||
m_settings.setDefaultContainer(selectedServerIndex, DockerContainer::OpenVpn);
|
||||
updateSettings();
|
||||
});
|
||||
connect(ui->pushButton_proto_openvpn_save, &QPushButton::clicked, this, [this](){
|
||||
QJsonObject protocolConfig = m_settings.protocolConfig(selectedServerIndex, selectedDockerContainer, Protocol::OpenVpn);
|
||||
protocolConfig = getOpenVpnConfigFromPage(protocolConfig);
|
||||
|
||||
QJsonObject containerConfig = m_settings.containerConfig(selectedServerIndex, selectedDockerContainer);
|
||||
QJsonObject newContainerConfig = containerConfig;
|
||||
newContainerConfig.insert(config_key::openvpn, protocolConfig);
|
||||
|
||||
ErrorCode e = doInstallAction([this, containerConfig, newContainerConfig](){
|
||||
return ServerController::updateContainer(m_settings.serverCredentials(selectedServerIndex), selectedDockerContainer, containerConfig, newContainerConfig);
|
||||
},
|
||||
ui->page_proto_openvpn, ui->progressBar_proto_openvpn_reset,
|
||||
ui->pushButton_proto_openvpn_save, ui->label_proto_openvpn_info);
|
||||
|
||||
if (!e) {
|
||||
m_settings.setContainerConfig(selectedServerIndex, selectedDockerContainer, newContainerConfig);
|
||||
m_settings.clearLastConnectionConfig(selectedServerIndex, selectedDockerContainer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::setupNewServerPageConnections()
|
||||
|
@ -1019,15 +1183,23 @@ void MainWindow::onTrayActivated(QSystemTrayIcon::ActivationReason reason)
|
|||
}
|
||||
|
||||
void MainWindow::onConnect()
|
||||
{
|
||||
|
||||
int serverIndex = m_settings.defaultServerIndex();
|
||||
ServerCredentials credentials = m_settings.serverCredentials(serverIndex);
|
||||
DockerContainer container = m_settings.defaultContainer(serverIndex);
|
||||
const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container);
|
||||
|
||||
onConnectWorker(serverIndex, credentials, container, containerConfig);
|
||||
}
|
||||
|
||||
void MainWindow::onConnectWorker(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig)
|
||||
{
|
||||
ui->label_error_text->clear();
|
||||
ui->pushButton_connect->setChecked(true);
|
||||
qApp->processEvents();
|
||||
|
||||
// TODO: Call connectToVpn with restricted server account
|
||||
ServerCredentials credentials = m_settings.defaultServerCredentials();
|
||||
|
||||
ErrorCode errorCode = m_vpnConnection->connectToVpn(credentials);
|
||||
ErrorCode errorCode = m_vpnConnection->connectToVpn(serverIndex, credentials, container, containerConfig);
|
||||
if (errorCode) {
|
||||
//ui->pushButton_connect->setChecked(false);
|
||||
QMessageBox::critical(this, APPLICATION_NAME, errorString(errorCode));
|
||||
|
@ -1121,34 +1293,56 @@ void MainWindow::onPushButtonDeleteCustomSiteClicked(const QString &siteToDelete
|
|||
}
|
||||
|
||||
void MainWindow::updateSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::updateSitesPage()
|
||||
{
|
||||
ui->listWidget_sites->clear();
|
||||
for (const QString &site : m_settings.customSites()) {
|
||||
makeSitesListItem(ui->listWidget_sites, site);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateVpnPage()
|
||||
{
|
||||
ui->radioButton_mode_selected_sites->setChecked(m_settings.customRouting());
|
||||
ui->pushButton_vpn_add_site->setEnabled(m_settings.customRouting());
|
||||
}
|
||||
|
||||
void MainWindow::updateAppSettingsPage()
|
||||
{
|
||||
ui->checkBox_autostart->setChecked(Autostart::isAutostart());
|
||||
ui->checkBox_autoconnect->setChecked(m_settings.isAutoConnect());
|
||||
|
||||
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);
|
||||
}
|
||||
void MainWindow::updateServerPage()
|
||||
{
|
||||
ui->label_server_settings_wait_info->hide();
|
||||
ui->label_server_settings_wait_info->clear();
|
||||
|
||||
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());
|
||||
|
||||
QJsonObject selectedServer = m_settings.server(selectedServerIndex);
|
||||
QString selectedContainerName = m_settings.defaultContainerName(selectedServerIndex);
|
||||
|
||||
ui->label_server_settings_current_vpn_protocol->setText(tr("Protocol: ") + selectedContainerName);
|
||||
|
||||
qDebug() << "DefaultContainer(selectedServerIndex)" << selectedServerIndex << m_settings.defaultContainer(selectedServerIndex);
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default->setChecked(m_settings.defaultContainer(selectedServerIndex) == DockerContainer::OpenVpnOverCloak);
|
||||
ui->pushButton_proto_ss_openvpn_cont_default->setChecked(m_settings.defaultContainer(selectedServerIndex) == DockerContainer::ShadowSocksOverOpenVpn);
|
||||
ui->pushButton_proto_openvpn_cont_default->setChecked(m_settings.defaultContainer(selectedServerIndex) == DockerContainer::OpenVpn);
|
||||
//qDebug() << "DefaultContainer(selectedServerIndex)" << selectedServerIndex << containerToString(m_settings.defaultContainer(selectedServerIndex));
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::updateServersPage()
|
||||
void MainWindow::updateServersListPage()
|
||||
{
|
||||
ui->listWidget_servers->clear();
|
||||
const QJsonArray &servers = m_settings.serversArray();
|
||||
|
@ -1161,6 +1355,34 @@ void MainWindow::updateServersPage()
|
|||
ui->listWidget_servers->setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::updateProtocolsPage()
|
||||
{
|
||||
ui->progressBar_protocols_container_reinstall->hide();
|
||||
|
||||
auto containers = m_settings.containers(selectedServerIndex);
|
||||
|
||||
DockerContainer defaultContainer = m_settings.defaultContainer(selectedServerIndex);
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default->setChecked(defaultContainer == DockerContainer::OpenVpnOverCloak);
|
||||
ui->pushButton_proto_ss_openvpn_cont_default->setChecked(defaultContainer == DockerContainer::OpenVpnOverShadowSocks);
|
||||
ui->pushButton_proto_openvpn_cont_default->setChecked(defaultContainer == DockerContainer::OpenVpn);
|
||||
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default->setVisible(containers.contains(DockerContainer::OpenVpnOverCloak));
|
||||
ui->pushButton_proto_ss_openvpn_cont_default->setVisible(containers.contains(DockerContainer::OpenVpnOverShadowSocks));
|
||||
ui->pushButton_proto_openvpn_cont_default->setVisible(containers.contains(DockerContainer::OpenVpn));
|
||||
|
||||
ui->pushButton_proto_cloak_openvpn_cont_share->setVisible(containers.contains(DockerContainer::OpenVpnOverCloak));
|
||||
ui->pushButton_proto_ss_openvpn_cont_share->setVisible(containers.contains(DockerContainer::OpenVpnOverShadowSocks));
|
||||
ui->pushButton_proto_openvpn_cont_share->setVisible(containers.contains(DockerContainer::OpenVpn));
|
||||
|
||||
ui->pushButton_proto_cloak_openvpn_cont_install->setChecked(containers.contains(DockerContainer::OpenVpnOverCloak));
|
||||
ui->pushButton_proto_ss_openvpn_cont_install->setChecked(containers.contains(DockerContainer::OpenVpnOverShadowSocks));
|
||||
ui->pushButton_proto_openvpn_cont_install->setChecked(containers.contains(DockerContainer::OpenVpn));
|
||||
|
||||
ui->frame_openvpn_ss_cloak_settings->setVisible(containers.contains(DockerContainer::OpenVpnOverCloak));
|
||||
ui->frame_openvpn_ss_settings->setVisible(containers.contains(DockerContainer::OpenVpnOverShadowSocks));
|
||||
ui->frame_openvpn_settings->setVisible(containers.contains(DockerContainer::OpenVpn));
|
||||
}
|
||||
|
||||
void MainWindow::updateShareCodePage()
|
||||
{
|
||||
// QJsonObject o;
|
||||
|
@ -1175,22 +1397,37 @@ void MainWindow::updateShareCodePage()
|
|||
//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));
|
||||
void MainWindow::updateOpenVpnPage(const QJsonObject &openvpnConfig, DockerContainer container)
|
||||
{
|
||||
ui->radioButton_proto_openvpn_udp->setEnabled(true);
|
||||
ui->radioButton_proto_openvpn_tcp->setEnabled(true);
|
||||
|
||||
QString trasnsport = nonEmpty(openvpnConfig.value(config_key::transport_protocol).toString(),
|
||||
protocols::openvpn::openvpnDefaultProto);
|
||||
ui->lineEdit_proto_openvpn_subnet->setText(openvpnConfig.value(config_key::subnet_address).
|
||||
toString(protocols::vpnDefaultSubnetAddress));
|
||||
|
||||
ui->radioButton_proto_openvpn_udp->setChecked(trasnsport == protocols::openvpn::openvpnDefaultProto);
|
||||
ui->radioButton_proto_openvpn_tcp->setChecked(trasnsport != protocols::openvpn::openvpnDefaultProto);
|
||||
QString trasnsport = openvpnConfig.value(config_key::transport_proto).
|
||||
toString(protocols::openvpn::defaultTransportProto);
|
||||
|
||||
ui->comboBox_proto_openvpn_cipher->setCurrentText(nonEmpty(openvpnConfig.value(config_key::cipher).toString(),
|
||||
protocols::openvpn::openvpnDefaultCipher));
|
||||
ui->radioButton_proto_openvpn_udp->setChecked(trasnsport == protocols::openvpn::defaultTransportProto);
|
||||
ui->radioButton_proto_openvpn_tcp->setChecked(trasnsport != protocols::openvpn::defaultTransportProto);
|
||||
|
||||
ui->comboBox_proto_openvpn_cipher->setCurrentText(nonEmpty(openvpnConfig.value(config_key::hash).toString(),
|
||||
protocols::openvpn::openvpnDefaultHash));
|
||||
ui->comboBox_proto_openvpn_cipher->setCurrentText(openvpnConfig.value(config_key::cipher).
|
||||
toString(protocols::openvpn::defaultCipher));
|
||||
|
||||
ui->comboBox_proto_openvpn_hash->setCurrentText(openvpnConfig.value(config_key::hash).
|
||||
toString(protocols::openvpn::defaultHash));
|
||||
|
||||
bool blockOutsideDns = openvpnConfig.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns);
|
||||
ui->checkBox_proto_openvpn_block_dns->setChecked(blockOutsideDns);
|
||||
|
||||
bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable);
|
||||
ui->checkBox_proto_openvpn_auto_encryption->setChecked(!isNcpDisabled);
|
||||
|
||||
if (container == DockerContainer::OpenVpnOverShadowSocks) {
|
||||
ui->radioButton_proto_openvpn_udp->setEnabled(false);
|
||||
ui->radioButton_proto_openvpn_tcp->setEnabled(false);
|
||||
ui->radioButton_proto_openvpn_tcp->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::makeSitesListItem(QListWidget *listWidget, const QString &address)
|
||||
|
@ -1232,7 +1469,7 @@ void MainWindow::makeServersListItem(QListWidget *listWidget, const QJsonObject
|
|||
connect(widget->ui->pushButton_default, &QPushButton::clicked, this, [this, index](){
|
||||
m_settings.setDefaultServer(index);
|
||||
updateSettings();
|
||||
updateServersPage();
|
||||
updateServersListPage();
|
||||
});
|
||||
|
||||
connect(widget->ui->pushButton_share, &QPushButton::clicked, this, [this, index](){
|
||||
|
@ -1275,3 +1512,15 @@ void MainWindow::updateQRCodeImage(const QString &text, QLabel *label)
|
|||
|
||||
label->setPixmap(QPixmap::fromImage(encodeImage.scaledToWidth(label->width())));
|
||||
}
|
||||
|
||||
QJsonObject MainWindow::getOpenVpnConfigFromPage(QJsonObject oldConfig)
|
||||
{
|
||||
oldConfig.insert(config_key::subnet_address, ui->lineEdit_proto_openvpn_subnet->text());
|
||||
oldConfig.insert(config_key::transport_proto, ui->radioButton_proto_openvpn_udp->isChecked() ? protocols::UDP : protocols::TCP);
|
||||
oldConfig.insert(config_key::ncp_disable, ! ui->checkBox_proto_openvpn_auto_encryption->isChecked());
|
||||
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());
|
||||
|
||||
return oldConfig;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ private slots:
|
|||
void onTrayActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
|
||||
void onConnect();
|
||||
void onConnectWorker(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
void onDisconnect();
|
||||
|
||||
|
||||
|
@ -81,6 +82,8 @@ private:
|
|||
bool installServer(ServerCredentials credentials, QList<DockerContainer> containers, QJsonArray configs,
|
||||
QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info);
|
||||
|
||||
ErrorCode doInstallAction(const std::function<ErrorCode()> &action, QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info);
|
||||
|
||||
void setupTray();
|
||||
void setTrayIcon(const QString &iconPath);
|
||||
|
||||
|
@ -89,15 +92,23 @@ private:
|
|||
void setupNewServerPageConnections();
|
||||
|
||||
void updateSettings();
|
||||
void updateServersPage();
|
||||
|
||||
void updateSitesPage();
|
||||
void updateVpnPage();
|
||||
void updateAppSettingsPage();
|
||||
void updateServerPage();
|
||||
void updateServersListPage();
|
||||
void updateProtocolsPage();
|
||||
void updateShareCodePage();
|
||||
void updateOpenVpnPage(const QJsonObject &openvpnConfig);
|
||||
void updateOpenVpnPage(const QJsonObject &openvpnConfig, DockerContainer container = DockerContainer::None);
|
||||
|
||||
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);
|
||||
|
||||
QJsonObject getOpenVpnConfigFromPage(QJsonObject oldConfig);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
VpnConnection* m_vpnConnection;
|
||||
|
@ -111,6 +122,7 @@ private:
|
|||
|
||||
QRegExpValidator m_ipAddressValidator;
|
||||
QRegExpValidator m_ipAddressPortValidator;
|
||||
QRegExpValidator m_ipNetwok24Validator;
|
||||
|
||||
CQR_Encode m_qrEncode;
|
||||
|
||||
|
@ -129,6 +141,7 @@ private:
|
|||
|
||||
QStack<Page> pagesStack;
|
||||
int selectedServerIndex = -1; // server index to use when proto settings page opened
|
||||
DockerContainer selectedDockerContainer; // same
|
||||
ServerCredentials installCredentials; // used to save cred between pages new_server and new_server_2
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,6 +27,9 @@ public:
|
|||
static QRegExp ipAddressPortRegExp() { return QRegExp("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}"
|
||||
"(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\\:[0-9]{1,5}){0,1}$"); }
|
||||
|
||||
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 bool processIsRunning(const QString& fileName);
|
||||
static void killProcessByName(const QString &name);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <configurators/openvpn_configurator.h>
|
||||
#include <configurators/cloak_configurator.h>
|
||||
#include <configurators/shadowsocks_configurator.h>
|
||||
#include <core/servercontroller.h>
|
||||
|
||||
#include "ipc.h"
|
||||
|
@ -80,11 +81,78 @@ ErrorCode VpnConnection::lastError() const
|
|||
return m_vpnProtocol.data()->lastError();
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::createVpnConfiguration(const ServerCredentials &credentials, DockerContainer container)
|
||||
QMap<Protocol, QString> VpnConnection::getLastVpnConfig(const QJsonObject &containerConfig)
|
||||
{
|
||||
QMap<Protocol, QString> configs;
|
||||
for (Protocol proto: { Protocol::OpenVpn,
|
||||
Protocol::ShadowSocks,
|
||||
Protocol::Cloak,
|
||||
Protocol::WireGuard}) {
|
||||
|
||||
QString cfg = containerConfig.value(protoToString(proto)).toObject().value(config_key::last_config).toString();
|
||||
|
||||
if (!cfg.isEmpty()) configs.insert(proto, cfg);
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
|
||||
QString VpnConnection::createVpnConfigurationForProto(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, Protocol proto,
|
||||
ErrorCode *errorCode)
|
||||
{
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
auto lastVpnConfig = getLastVpnConfig(containerConfig);
|
||||
|
||||
QString configData;
|
||||
if (lastVpnConfig.contains(proto)) {
|
||||
configData = lastVpnConfig.value(proto);
|
||||
qDebug() << "VpnConnection::createVpnConfiguration using saved config for " << protoToString(proto);
|
||||
}
|
||||
else {
|
||||
if (proto == Protocol::OpenVpn) {
|
||||
configData = OpenVpnConfigurator::genOpenVpnConfig(credentials,
|
||||
container, containerConfig, &e);
|
||||
}
|
||||
else if (proto == Protocol::Cloak) {
|
||||
configData = CloakConfigurator::genCloakConfig(credentials,
|
||||
container, containerConfig, &e);
|
||||
}
|
||||
else if (proto == Protocol::ShadowSocks) {
|
||||
configData = ShadowSocksConfigurator::genShadowSocksConfig(credentials,
|
||||
container, containerConfig, &e);
|
||||
}
|
||||
|
||||
if (errorCode && e) {
|
||||
*errorCode = e;
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
if (serverIndex >= 0) {
|
||||
QJsonObject protoObject = m_settings.protocolConfig(serverIndex, container, proto);
|
||||
protoObject.insert(config_key::last_config, configData);
|
||||
m_settings.setProtocolConfig(serverIndex, container, proto, protoObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorCode) *errorCode = e;
|
||||
return configData;
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::createVpnConfiguration(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig)
|
||||
{
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocksOverOpenVpn || container == DockerContainer::OpenVpnOverCloak) {
|
||||
QString openVpnConfigData = OpenVpnConfigurator::genOpenVpnConfig(credentials, container, &errorCode);
|
||||
|
||||
if (container == DockerContainer::OpenVpn ||
|
||||
container == DockerContainer::OpenVpnOverShadowSocks ||
|
||||
container == DockerContainer::OpenVpnOverCloak) {
|
||||
|
||||
QString openVpnConfigData =
|
||||
createVpnConfigurationForProto(
|
||||
serverIndex, credentials, container, containerConfig, Protocol::OpenVpn, &errorCode);
|
||||
|
||||
|
||||
m_vpnConfiguration.insert(config::key_openvpn_config_data, openVpnConfigData);
|
||||
if (errorCode) {
|
||||
return errorCode;
|
||||
|
@ -101,13 +169,21 @@ ErrorCode VpnConnection::createVpnConfiguration(const ServerCredentials &credent
|
|||
}
|
||||
}
|
||||
|
||||
if (container == DockerContainer::ShadowSocksOverOpenVpn) {
|
||||
QJsonObject ssConfigData = ShadowSocksVpnProtocol::genShadowSocksConfig(credentials);
|
||||
if (container == DockerContainer::OpenVpnOverShadowSocks) {
|
||||
QJsonObject ssConfigData = QJsonDocument::fromJson(
|
||||
createVpnConfigurationForProto(
|
||||
serverIndex, credentials, container, containerConfig, Protocol::ShadowSocks, &errorCode).toUtf8()).
|
||||
object();
|
||||
|
||||
m_vpnConfiguration.insert(config::key_shadowsocks_config_data, ssConfigData);
|
||||
}
|
||||
|
||||
if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
QJsonObject cloakConfigData = CloakConfigurator::genCloakConfig(credentials, DockerContainer::OpenVpnOverCloak, &errorCode);
|
||||
QJsonObject cloakConfigData = QJsonDocument::fromJson(
|
||||
createVpnConfigurationForProto(
|
||||
serverIndex, credentials, container, containerConfig, Protocol::Cloak, &errorCode).toUtf8()).
|
||||
object();
|
||||
|
||||
m_vpnConfiguration.insert(config::key_cloak_config_data, cloakConfigData);
|
||||
}
|
||||
|
||||
|
@ -115,17 +191,9 @@ ErrorCode VpnConnection::createVpnConfiguration(const ServerCredentials &credent
|
|||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, DockerContainer container)
|
||||
ErrorCode VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig)
|
||||
{
|
||||
qDebug() << "connectToVpn, CustomRouting is" << m_settings.customRouting();
|
||||
// qDebug() << "Cred" << m_settings.serverCredentials().hostName <<
|
||||
// m_settings.serverCredentials().password;
|
||||
//protocol = Protocol::ShadowSocks;
|
||||
container = DockerContainer::OpenVpnOverCloak;
|
||||
|
||||
// TODO: Try protocols one by one in case of Protocol::Any
|
||||
// TODO: Implement some behavior in case if connection not stable
|
||||
qDebug() << "Connect to VPN";
|
||||
qDebug() << "СonnectToVpn, CustomRouting is" << m_settings.customRouting();
|
||||
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Connecting);
|
||||
|
||||
|
@ -133,13 +201,10 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Dock
|
|||
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
m_vpnProtocol->stop();
|
||||
m_vpnProtocol.reset();
|
||||
//m_vpnProtocol->deleteLater();
|
||||
}
|
||||
|
||||
//qApp->processEvents();
|
||||
|
||||
if (container == DockerContainer::None || container == DockerContainer::OpenVpn) {
|
||||
ErrorCode e = createVpnConfiguration(credentials, DockerContainer::OpenVpn);
|
||||
ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::OpenVpn, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
return e;
|
||||
|
@ -152,8 +217,8 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Dock
|
|||
return e;
|
||||
}
|
||||
}
|
||||
else if (container == DockerContainer::ShadowSocksOverOpenVpn) {
|
||||
ErrorCode e = createVpnConfiguration(credentials, DockerContainer::ShadowSocksOverOpenVpn);
|
||||
else if (container == DockerContainer::OpenVpnOverShadowSocks) {
|
||||
ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::OpenVpnOverShadowSocks, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
return e;
|
||||
|
@ -167,7 +232,7 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Dock
|
|||
}
|
||||
}
|
||||
else if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
ErrorCode e = createVpnConfiguration(credentials, DockerContainer::OpenVpnOverCloak);
|
||||
ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::OpenVpnOverCloak, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
return e;
|
||||
|
|
|
@ -24,9 +24,16 @@ public:
|
|||
static QString bytesPerSecToText(quint64 bytes);
|
||||
|
||||
ErrorCode lastError() const;
|
||||
ErrorCode createVpnConfiguration(const ServerCredentials &credentials, DockerContainer container);
|
||||
|
||||
ErrorCode connectToVpn(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None);
|
||||
static QMap<Protocol, QString> getLastVpnConfig(const QJsonObject &containerConfig);
|
||||
QString createVpnConfigurationForProto(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, Protocol proto,
|
||||
ErrorCode *errorCode = nullptr);
|
||||
|
||||
ErrorCode createVpnConfiguration(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
|
||||
ErrorCode connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
void disconnectFromVpn();
|
||||
|
||||
bool isConnected() const;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue