Compare commits
19 commits
dev
...
feature/v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44018ec94c | ||
|
|
89577651d6 | ||
|
|
3b2d3a0b34 | ||
|
|
fe3228ed74 | ||
|
|
917942be94 | ||
|
|
6a3875ec7f | ||
|
|
e121ca9b53 | ||
|
|
c23c8e8462 | ||
|
|
36fae9152f | ||
|
|
2b0ba2aff9 | ||
|
|
68830021d6 | ||
|
|
6a903792ab | ||
|
|
d2d9c33837 | ||
|
|
7d51cb7d58 | ||
|
|
7df3600a62 | ||
|
|
634ca6cbe8 | ||
|
|
8032e55d7c | ||
|
|
dc2a1467c7 | ||
|
|
67c36f5b30 |
56 changed files with 998 additions and 192 deletions
|
|
@ -235,6 +235,7 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
|||
${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/v2rayprotocol.h
|
||||
)
|
||||
|
||||
set(SOURCES ${SOURCES}
|
||||
|
|
@ -245,6 +246,7 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
|||
${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/v2rayprotocol.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
@ -558,7 +560,7 @@ if(WIN32)
|
|||
set(DEPLOY_ARTIFACT_PATH "windows/x32")
|
||||
endif()
|
||||
elseif(LINUX)
|
||||
set(DEPLOY_ARTIFACT_PATH "linux/client")
|
||||
set(DEPLOY_ARTIFACT_PATH "linux/client/bin")
|
||||
elseif(APPLE AND NOT IOS)
|
||||
set(DEPLOY_ARTIFACT_PATH "macos")
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -7,24 +7,24 @@
|
|||
#include "core/servercontroller.h"
|
||||
#include "containers/containers_defs.h"
|
||||
|
||||
CloakConfigurator::CloakConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
||||
ConfiguratorBase(settings, parent)
|
||||
CloakConfigurator::CloakConfigurator(std::shared_ptr<Settings> settings,
|
||||
QObject *parent): ConfiguratorBase(settings, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
ServerController serverController(m_settings);
|
||||
|
||||
|
||||
QString cloakPublicKey = serverController.getTextFileFromContainer(container, credentials,
|
||||
amnezia::protocols::cloak::ckPublicKeyPath, &e);
|
||||
amnezia::protocols::cloak::ckPublicKeyPath, &e);
|
||||
cloakPublicKey.replace("\n", "");
|
||||
|
||||
QString cloakBypassUid = serverController.getTextFileFromContainer(container, credentials,
|
||||
amnezia::protocols::cloak::ckBypassUidKeyPath, &e);
|
||||
amnezia::protocols::cloak::ckBypassUidKeyPath, &e);
|
||||
cloakBypassUid.replace("\n", "");
|
||||
|
||||
if (e) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public:
|
|||
CloakConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
QString genCloakConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
||||
#endif // CLOAK_CONFIGURATOR_H
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#include "configurator_base.h"
|
||||
|
||||
ConfiguratorBase::ConfiguratorBase(std::shared_ptr<Settings> settings, QObject *parent)
|
||||
: QObject{parent},
|
||||
m_settings(settings)
|
||||
ConfiguratorBase::ConfiguratorBase(std::shared_ptr<Settings> settings,
|
||||
QObject *parent): QObject{parent}, m_settings(settings)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "ikev2_configurator.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
|
|
@ -15,14 +16,13 @@
|
|||
#include "core/servercontroller.h"
|
||||
|
||||
|
||||
Ikev2Configurator::Ikev2Configurator(std::shared_ptr<Settings> settings, QObject *parent):
|
||||
ConfiguratorBase(settings, parent)
|
||||
Ikev2Configurator::Ikev2Configurator(std::shared_ptr<Settings> settings,
|
||||
QObject *parent): ConfiguratorBase(settings, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode)
|
||||
DockerContainer container, ErrorCode *errorCode)
|
||||
{
|
||||
Ikev2Configurator::ConnectionData connData;
|
||||
connData.host = credentials.hostName;
|
||||
|
|
@ -33,21 +33,18 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
|
|||
QString certFileName = "/opt/amnezia/ikev2/clients/" + connData.clientId + ".p12";
|
||||
|
||||
QString scriptCreateCert = QString("certutil -z <(head -c 1024 /dev/urandom) "\
|
||||
"-S -c \"IKEv2 VPN CA\" -n \"%1\" "\
|
||||
"-s \"O=IKEv2 VPN,CN=%1\" "\
|
||||
"-k rsa -g 3072 -v 120 "\
|
||||
"-d sql:/etc/ipsec.d -t \",,\" "\
|
||||
"--keyUsage digitalSignature,keyEncipherment "\
|
||||
"--extKeyUsage serverAuth,clientAuth -8 \"%1\"")
|
||||
.arg(connData.clientId);
|
||||
"-S -c \"IKEv2 VPN CA\" -n \"%1\" "\
|
||||
"-s \"O=IKEv2 VPN,CN=%1\" "\
|
||||
"-k rsa -g 3072 -v 120 "\
|
||||
"-d sql:/etc/ipsec.d -t \",,\" "\
|
||||
"--keyUsage digitalSignature,keyEncipherment "\
|
||||
"--extKeyUsage serverAuth,clientAuth -8 \"%1\"").arg(connData.clientId);
|
||||
|
||||
ServerController serverController(m_settings);
|
||||
ErrorCode e = serverController.runContainerScript(credentials, container, scriptCreateCert);
|
||||
|
||||
QString scriptExportCert = QString("pk12util -W \"%1\" -d sql:/etc/ipsec.d -n \"%2\" -o \"%3\"")
|
||||
.arg(connData.password)
|
||||
.arg(connData.clientId)
|
||||
.arg(certFileName);
|
||||
.arg(connData.password, connData.clientId, certFileName);
|
||||
e = serverController.runContainerScript(credentials, container, scriptExportCert);
|
||||
|
||||
connData.clientCert = serverController.getTextFileFromContainer(container, credentials, certFileName, &e);
|
||||
|
|
@ -59,8 +56,8 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
|
|||
return connData;
|
||||
}
|
||||
|
||||
QString Ikev2Configurator::genIkev2Config(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
QString Ikev2Configurator::genIkev2Config(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
Q_UNUSED(containerConfig)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ public:
|
|||
};
|
||||
|
||||
QString genIkev2Config(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
QString genIkev2Config(const ConnectionData &connData);
|
||||
QString genMobileConfig(const ConnectionData &connData);
|
||||
QString genStrongSwanConfig(const ConnectionData &connData);
|
||||
|
||||
ConnectionData prepareIkev2Config(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode = nullptr);
|
||||
ConnectionData prepareIkev2Config(const ServerCredentials &credentials, DockerContainer container,
|
||||
ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
||||
#endif // IKEV2_CONFIGURATOR_H
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "openvpn_configurator.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
|
|
@ -19,14 +20,13 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
||||
ConfiguratorBase(settings, parent)
|
||||
OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> settings,
|
||||
QObject *parent): ConfiguratorBase(settings, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode)
|
||||
DockerContainer container, ErrorCode *errorCode)
|
||||
{
|
||||
OpenVpnConfigurator::ConnectionData connData = OpenVpnConfigurator::createCertRequest();
|
||||
connData.host = credentials.hostName;
|
||||
|
|
@ -36,9 +36,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
|||
return connData;
|
||||
}
|
||||
|
||||
QString reqFileName = QString("%1/%2.req").
|
||||
arg(amnezia::protocols::openvpn::clientsDirPath).
|
||||
arg(connData.clientId);
|
||||
QString reqFileName = QString("%1/%2.req").arg(amnezia::protocols::openvpn::clientsDirPath, connData.clientId);
|
||||
|
||||
ServerController serverController(m_settings);
|
||||
ErrorCode e = serverController.uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
|
||||
|
|
@ -53,9 +51,11 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
|||
return connData;
|
||||
}
|
||||
|
||||
connData.caCert = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::caCertPath, &e);
|
||||
connData.caCert = serverController.getTextFileFromContainer(container, credentials,
|
||||
amnezia::protocols::openvpn::caCertPath, &e);
|
||||
connData.clientCert = serverController.getTextFileFromContainer(container, credentials,
|
||||
QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), &e);
|
||||
QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath, connData.clientId),
|
||||
&e);
|
||||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
|
|
@ -71,12 +71,12 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
|||
return connData;
|
||||
}
|
||||
|
||||
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
ServerController serverController(m_settings);
|
||||
QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
|
||||
serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode);
|
||||
if (errorCode && *errorCode) {
|
||||
|
|
@ -89,8 +89,7 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
|
|||
|
||||
if (config.contains("$OPENVPN_TA_KEY")) {
|
||||
config.replace("$OPENVPN_TA_KEY", connData.taKey);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
config.replace("<tls-auth>", "");
|
||||
config.replace("</tls-auth>", "");
|
||||
}
|
||||
|
|
@ -112,8 +111,7 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig)
|
|||
|
||||
if (m_settings->routeMode() != Settings::VpnAllSites) {
|
||||
config.replace("redirect-gateway def1 bypass-dhcp", "");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if(!config.contains("redirect-gateway def1 bypass-dhcp")) {
|
||||
config.append("redirect-gateway def1 bypass-dhcp\n");
|
||||
}
|
||||
|
|
@ -151,23 +149,22 @@ QString OpenVpnConfigurator::processConfigWithExportSettings(QString jsonConfig)
|
|||
return QJsonDocument(json).toJson();
|
||||
}
|
||||
|
||||
ErrorCode OpenVpnConfigurator::signCert(DockerContainer container,
|
||||
const ServerCredentials &credentials, QString clientId)
|
||||
ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId)
|
||||
{
|
||||
QString script_import = QString("sudo docker exec -i %1 bash -c \"cd /opt/amnezia/openvpn && "
|
||||
"easyrsa import-req %2/%3.req %3\"")
|
||||
.arg(ContainerProps::containerToString(container))
|
||||
.arg(amnezia::protocols::openvpn::clientsDirPath)
|
||||
.arg(clientId);
|
||||
"easyrsa import-req %2/%3.req %3\"")
|
||||
.arg(ContainerProps::containerToString(container),
|
||||
amnezia::protocols::openvpn::clientsDirPath,
|
||||
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(ContainerProps::containerToString(container))
|
||||
.arg(clientId);
|
||||
"easyrsa sign-req client %2\"")
|
||||
.arg(ContainerProps::containerToString(container), clientId);
|
||||
|
||||
ServerController serverController(m_settings);
|
||||
QStringList scriptList {script_import, script_sign};
|
||||
QString script = serverController.replaceVars(scriptList.join("\n"), serverController.genVarsForScript(credentials, container));
|
||||
QString script = serverController.replaceVars(scriptList.join("\n"),
|
||||
serverController.genVarsForScript(credentials, container));
|
||||
|
||||
return serverController.runScript(credentials, script);
|
||||
}
|
||||
|
|
@ -177,8 +174,8 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
|
|||
ConnectionData connData;
|
||||
connData.clientId = Utils::getRandomString(32);
|
||||
|
||||
int ret = 0;
|
||||
int nVersion = 1;
|
||||
int ret = 0;
|
||||
int nVersion = 1;
|
||||
|
||||
QByteArray clientIdUtf8 = connData.clientId.toUtf8();
|
||||
|
||||
|
|
@ -211,7 +208,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
|
|||
|
||||
// 4. set public key of x509 req
|
||||
ret = X509_REQ_set_pubkey(x509_req, pKey);
|
||||
if (ret != 1){
|
||||
if (ret != 1) {
|
||||
qWarning() << "Could not set pubkey!";
|
||||
X509_REQ_free(x509_req);
|
||||
EVP_PKEY_free(pKey);
|
||||
|
|
@ -220,7 +217,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
|
|||
|
||||
// 5. set sign key of x509 req
|
||||
ret = X509_REQ_sign(x509_req, pKey, EVP_sha256()); // return x509_req->signature->length
|
||||
if (ret <= 0){
|
||||
if (ret <= 0) {
|
||||
qWarning() << "Could not sign request!";
|
||||
X509_REQ_free(x509_req);
|
||||
EVP_PKEY_free(pKey);
|
||||
|
|
@ -230,8 +227,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
|
|||
// save private key
|
||||
BIO * bp_private = BIO_new(BIO_s_mem());
|
||||
q_check_ptr(bp_private);
|
||||
if (PEM_write_bio_PrivateKey(bp_private, pKey, nullptr, nullptr, 0, nullptr, nullptr) != 1)
|
||||
{
|
||||
if (PEM_write_bio_PrivateKey(bp_private, pKey, nullptr, nullptr, 0, nullptr, nullptr) != 1) {
|
||||
qFatal("PEM_write_bio_PrivateKey");
|
||||
EVP_PKEY_free(pKey);
|
||||
BIO_free_all(bp_private);
|
||||
|
|
|
|||
|
|
@ -24,20 +24,18 @@ public:
|
|||
};
|
||||
|
||||
QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
QString processConfigWithLocalSettings(QString jsonConfig);
|
||||
QString processConfigWithExportSettings(QString jsonConfig);
|
||||
|
||||
ErrorCode signCert(DockerContainer container,
|
||||
const ServerCredentials &credentials, QString clientId);
|
||||
ErrorCode signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId);
|
||||
|
||||
private:
|
||||
ConnectionData createCertRequest();
|
||||
|
||||
ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode = nullptr);
|
||||
|
||||
ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
||||
#endif // OPENVPN_CONFIGURATOR_H
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@
|
|||
#include <QJsonDocument>
|
||||
|
||||
#include "containers/containers_defs.h"
|
||||
#include "core/scripts_registry.h"
|
||||
#include "core/servercontroller.h"
|
||||
|
||||
ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
||||
ConfiguratorBase(settings, parent)
|
||||
ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr<Settings> settings,
|
||||
QObject *parent): ConfiguratorBase(settings, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
ServerController serverController(m_settings);
|
||||
|
|
@ -28,18 +28,12 @@ QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &c
|
|||
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 ssClientConfig = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::shadowsocks_client_template, container),
|
||||
serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
|
||||
QString textCfg = serverController.replaceVars(QJsonDocument(config).toJson(),
|
||||
serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
ssClientConfig.replace("$SHADOWSOCKS_PASSWORD", ssKey);
|
||||
ssClientConfig = serverController.replaceVars(ssClientConfig, serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
//qDebug().noquote() << textCfg;
|
||||
return textCfg;
|
||||
return ssClientConfig;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public:
|
|||
ShadowSocksConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
QString genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
||||
#endif // SHADOWSOCKS_CONFIGURATOR_H
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "ssh_configurator.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
|
|
@ -14,11 +15,9 @@
|
|||
#include "core/server_defs.h"
|
||||
#include "utilities.h"
|
||||
|
||||
|
||||
SshConfigurator::SshConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
||||
ConfiguratorBase(settings, parent)
|
||||
SshConfigurator::SshConfigurator(std::shared_ptr<Settings> settings,
|
||||
QObject *parent): ConfiguratorBase(settings, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString SshConfigurator::convertOpenSShKey(const QString &key)
|
||||
|
|
@ -73,10 +72,8 @@ void SshConfigurator::openSshTerminal(const ServerCredentials &credentials)
|
|||
// todo: connect by key
|
||||
// p->setNativeArguments(QString("%1@%2")
|
||||
// .arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
||||
}
|
||||
else {
|
||||
p->setNativeArguments(QString("%1@%2 -pw %3")
|
||||
.arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
||||
} else {
|
||||
p->setNativeArguments(QString("%1@%2 -pw %3").arg(credentials.userName).arg(credentials.hostName, credentials.password));
|
||||
}
|
||||
#else
|
||||
p->setProgram("/bin/bash");
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ public:
|
|||
QProcessEnvironment prepareEnv();
|
||||
QString convertOpenSShKey(const QString &key);
|
||||
void openSshTerminal(const ServerCredentials &credentials);
|
||||
|
||||
};
|
||||
|
||||
#endif // SSH_CONFIGURATOR_H
|
||||
|
|
|
|||
46
client/configurators/v2ray_configurator.cpp
Normal file
46
client/configurators/v2ray_configurator.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#include "v2ray_configurator.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QPair>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "core/servercontroller.h"
|
||||
#include "core/scripts_registry.h"
|
||||
#include "containers/containers_defs.h"
|
||||
|
||||
V2RayConfigurator::V2RayConfigurator(std::shared_ptr<Settings> settings,
|
||||
QObject *parent) : ConfiguratorBase(settings, parent)
|
||||
{
|
||||
}
|
||||
|
||||
QString V2RayConfigurator::genV2RayConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
|
||||
ServerController serverController(m_settings);
|
||||
QString v2RayVmessClientUuid = serverController.getTextFileFromContainer(container, credentials,
|
||||
amnezia::protocols::v2ray::v2rayKeyPath, &e);
|
||||
if (v2RayVmessClientUuid.isEmpty()) {
|
||||
if (errorCode) *errorCode = ErrorCode::V2RayKeyMissing;
|
||||
return "";
|
||||
}
|
||||
|
||||
v2RayVmessClientUuid.replace("\n", "");
|
||||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return "";
|
||||
}
|
||||
|
||||
QString v2RayClientConfig = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::v2ray_client_template, container),
|
||||
serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
v2RayClientConfig.replace("$V2RAY_VMESS_CLIENT_UUID", v2RayVmessClientUuid);
|
||||
v2RayClientConfig = serverController.replaceVars(v2RayClientConfig,
|
||||
serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
return v2RayClientConfig;
|
||||
}
|
||||
20
client/configurators/v2ray_configurator.h
Normal file
20
client/configurators/v2ray_configurator.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef V2RAYCONFIGURATOR_H
|
||||
#define V2RAYCONFIGURATOR_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "configurator_base.h"
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
class V2RayConfigurator : ConfiguratorBase
|
||||
{
|
||||
public:
|
||||
V2RayConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
QString genV2RayConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
||||
#endif // V2RAYCONFIGURATOR_H
|
||||
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include "wireguard_configurator.h"
|
||||
#include "ikev2_configurator.h"
|
||||
#include "ssh_configurator.h"
|
||||
#include "v2ray_configurator.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonObject>
|
||||
|
|
@ -14,8 +15,8 @@
|
|||
#include "utilities.h"
|
||||
#include "settings.h"
|
||||
|
||||
VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
||||
ConfiguratorBase(settings, parent)
|
||||
VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings,
|
||||
QObject *parent) : ConfiguratorBase(settings, parent)
|
||||
{
|
||||
openVpnConfigurator = std::shared_ptr<OpenVpnConfigurator>(new OpenVpnConfigurator(settings, this));
|
||||
shadowSocksConfigurator = std::shared_ptr<ShadowSocksConfigurator>(new ShadowSocksConfigurator(settings, this));
|
||||
|
|
@ -25,25 +26,22 @@ VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings, QObject *pa
|
|||
sshConfigurator = std::shared_ptr<SshConfigurator>(new SshConfigurator(settings, this));
|
||||
}
|
||||
|
||||
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
|
||||
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
|
||||
{
|
||||
switch (proto) {
|
||||
case Proto::OpenVpn:
|
||||
return openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
case Proto::ShadowSocks:
|
||||
return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
case Proto::Cloak:
|
||||
return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
case Proto::WireGuard:
|
||||
return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
case Proto::Ikev2:
|
||||
return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
|
||||
|
||||
case Proto::V2Ray:
|
||||
return v2RayConfigurator->genV2RayConfig(credentials, container, containerConfig, errorCode);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
@ -62,8 +60,7 @@ QPair<QString, QString> VpnConfigurator::getDnsForConfig(int serverIndex)
|
|||
if (dns.first.isEmpty() || !Utils::checkIPv4Format(dns.first)) {
|
||||
if (useAmneziaDns && m_settings->containers(serverIndex).contains(DockerContainer::Dns)) {
|
||||
dns.first = protocols::dns::amneziaDnsIp;
|
||||
}
|
||||
else dns.first = m_settings->primaryDns();
|
||||
} else dns.first = m_settings->primaryDns();
|
||||
}
|
||||
if (dns.second.isEmpty() || !Utils::checkIPv4Format(dns.second)) {
|
||||
dns.second = m_settings->secondaryDns();
|
||||
|
|
@ -73,8 +70,7 @@ QPair<QString, QString> VpnConfigurator::getDnsForConfig(int serverIndex)
|
|||
return dns;
|
||||
}
|
||||
|
||||
QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container,
|
||||
Proto proto, QString &config)
|
||||
QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config)
|
||||
{
|
||||
auto dns = getDnsForConfig(serverIndex);
|
||||
|
||||
|
|
@ -84,8 +80,7 @@ QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerCo
|
|||
return config;
|
||||
}
|
||||
|
||||
QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container,
|
||||
Proto proto, QString &config)
|
||||
QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto, QString &config)
|
||||
{
|
||||
processConfigWithDnsSettings(serverIndex, container, proto, config);
|
||||
|
||||
|
|
@ -95,8 +90,7 @@ QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, Docker
|
|||
return config;
|
||||
}
|
||||
|
||||
QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container,
|
||||
Proto proto, QString &config)
|
||||
QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config)
|
||||
{
|
||||
processConfigWithDnsSettings(serverIndex, container, proto, config);
|
||||
|
||||
|
|
@ -107,7 +101,7 @@ QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, Docke
|
|||
}
|
||||
|
||||
void VpnConfigurator::updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig,
|
||||
const QString &stdOut)
|
||||
const QString &stdOut)
|
||||
{
|
||||
Proto mainProto = ContainerProps::defaultProtocol(container);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class CloakConfigurator;
|
|||
class WireguardConfigurator;
|
||||
class Ikev2Configurator;
|
||||
class SshConfigurator;
|
||||
class V2RayConfigurator;
|
||||
|
||||
// Retrieve connection settings from server
|
||||
class VpnConfigurator : ConfiguratorBase
|
||||
|
|
@ -22,7 +23,7 @@ public:
|
|||
VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr);
|
||||
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr);
|
||||
|
||||
QPair<QString, QString> getDnsForConfig(int serverIndex);
|
||||
QString &processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
|
||||
|
|
@ -31,8 +32,7 @@ public:
|
|||
QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
|
||||
|
||||
// workaround for containers which is not support normal configaration
|
||||
void updateContainerConfigAfterInstallation(DockerContainer container,
|
||||
QJsonObject &containerConfig, const QString &stdOut);
|
||||
void updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig, const QString &stdOut);
|
||||
|
||||
std::shared_ptr<OpenVpnConfigurator> openVpnConfigurator;
|
||||
std::shared_ptr<ShadowSocksConfigurator> shadowSocksConfigurator;
|
||||
|
|
@ -40,6 +40,7 @@ public:
|
|||
std::shared_ptr<WireguardConfigurator> wireguardConfigurator;
|
||||
std::shared_ptr<Ikev2Configurator> ikev2Configurator;
|
||||
std::shared_ptr<SshConfigurator> sshConfigurator;
|
||||
std::shared_ptr<V2RayConfigurator> v2RayConfigurator;
|
||||
};
|
||||
|
||||
#endif // VPN_CONFIGURATOR_H
|
||||
|
|
|
|||
|
|
@ -7,13 +7,11 @@
|
|||
#include <QTemporaryFile>
|
||||
#include <QJsonDocument>
|
||||
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
|
||||
#include "containers/containers_defs.h"
|
||||
#include "core/server_defs.h"
|
||||
#include "core/scripts_registry.h"
|
||||
|
|
@ -21,10 +19,9 @@
|
|||
#include "core/servercontroller.h"
|
||||
#include "settings.h"
|
||||
|
||||
WireguardConfigurator::WireguardConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
||||
ConfiguratorBase(settings, parent)
|
||||
WireguardConfigurator::WireguardConfigurator(std::shared_ptr<Settings> settings,
|
||||
QObject *parent): ConfiguratorBase(settings, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
||||
|
|
@ -59,7 +56,9 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
|||
}
|
||||
|
||||
WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
DockerContainer container,
|
||||
const QJsonObject &containerConfig,
|
||||
ErrorCode *errorCode)
|
||||
{
|
||||
WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys();
|
||||
connData.host = credentials.hostName;
|
||||
|
|
@ -95,8 +94,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
// Calc next IP address
|
||||
if (ips.isEmpty()) {
|
||||
nextIpNumber = "2";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int next = ips.last().split(".").last().toInt() + 1;
|
||||
if (next > 254) {
|
||||
if (errorCode) *errorCode = ErrorCode::AddressPoolError;
|
||||
|
|
@ -120,14 +118,16 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
}
|
||||
|
||||
// Get keys
|
||||
connData.serverPubKey = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPublicKeyPath, &e);
|
||||
connData.serverPubKey = serverController.getTextFileFromContainer(container, credentials,
|
||||
amnezia::protocols::wireguard::serverPublicKeyPath, &e);
|
||||
connData.serverPubKey.replace("\n", "");
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return connData;
|
||||
}
|
||||
|
||||
connData.pskKey = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPskKeyPath, &e);
|
||||
connData.pskKey = serverController.getTextFileFromContainer(container, credentials,
|
||||
amnezia::protocols::wireguard::serverPskKeyPath, &e);
|
||||
connData.pskKey.replace("\n", "");
|
||||
|
||||
if (e) {
|
||||
|
|
@ -136,32 +136,29 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
}
|
||||
|
||||
// Add client to config
|
||||
QString configPart = QString(
|
||||
"[Peer]\n"
|
||||
"PublicKey = %1\n"
|
||||
"PresharedKey = %2\n"
|
||||
"AllowedIPs = %3/32\n\n").
|
||||
arg(connData.clientPubKey).
|
||||
arg(connData.pskKey).
|
||||
arg(connData.clientIP);
|
||||
QString configPart = QString("[Peer]\n"
|
||||
"PublicKey = %1\n"
|
||||
"PresharedKey = %2\n"
|
||||
"AllowedIPs = %3/32\n\n").arg(connData.clientPubKey, connData.pskKey, connData.clientIP);
|
||||
|
||||
e = serverController.uploadTextFileToContainer(container, credentials, configPart,
|
||||
protocols::wireguard::serverConfigPath, libssh::SftpOverwriteMode::SftpAppendToExisting);
|
||||
protocols::wireguard::serverConfigPath,
|
||||
libssh::SftpOverwriteMode::SftpAppendToExisting);
|
||||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return connData;
|
||||
}
|
||||
|
||||
QString script = "sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip /opt/amnezia/wireguard/wg0.conf)'";
|
||||
e = serverController.runScript(credentials,
|
||||
serverController.replaceVars("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip /opt/amnezia/wireguard/wg0.conf)'",
|
||||
serverController.genVarsForScript(credentials, container)));
|
||||
serverController.replaceVars(script, serverController.genVarsForScript(credentials, container)));
|
||||
|
||||
return connData;
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
ServerController serverController(m_settings);
|
||||
QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container),
|
||||
|
|
|
|||
|
|
@ -23,15 +23,14 @@ public:
|
|||
};
|
||||
|
||||
QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
QString processConfigWithLocalSettings(QString config);
|
||||
QString processConfigWithExportSettings(QString config);
|
||||
|
||||
|
||||
private:
|
||||
ConnectionData prepareWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
ConnectionData genClientKeys();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ QVector<amnezia::Proto> ContainerProps::protocolsForContainer(amnezia::DockerCon
|
|||
case DockerContainer::Ipsec:
|
||||
return { Proto::Ikev2 /*, Protocol::L2tp */};
|
||||
|
||||
case DockerContainer::V2Ray:
|
||||
return { Proto::OpenVpn, Proto::V2Ray };
|
||||
|
||||
case DockerContainer::Dns:
|
||||
return { };
|
||||
|
||||
|
|
@ -86,6 +89,7 @@ QMap<DockerContainer, QString> ContainerProps::containerHumanNames()
|
|||
{DockerContainer::Cloak, "OpenVpn over Cloak"},
|
||||
{DockerContainer::WireGuard, "WireGuard"},
|
||||
{DockerContainer::Ipsec, QObject::tr("IPsec")},
|
||||
{DockerContainer::V2Ray, "V2Ray"},
|
||||
|
||||
{DockerContainer::TorWebSite, QObject::tr("Web site in Tor network")},
|
||||
{DockerContainer::Dns, QObject::tr("DNS Service")},
|
||||
|
|
@ -103,6 +107,7 @@ QMap<DockerContainer, QString> ContainerProps::containerDescriptions()
|
|||
"configured with traffic masking by Cloak plugin")},
|
||||
{DockerContainer::WireGuard, QObject::tr("WireGuard container")},
|
||||
{DockerContainer::Ipsec, QObject::tr("IPsec container")},
|
||||
{DockerContainer::V2Ray, QObject::tr("V2Ray container")},
|
||||
|
||||
{DockerContainer::TorWebSite, QObject::tr("Web site in Tor network")},
|
||||
{DockerContainer::Dns, QObject::tr("DNS Service")},
|
||||
|
|
@ -120,6 +125,8 @@ amnezia::ServiceType ContainerProps::containerService(DockerContainer c)
|
|||
case DockerContainer::ShadowSocks : return ServiceType::Vpn;
|
||||
case DockerContainer::WireGuard : return ServiceType::Vpn;
|
||||
case DockerContainer::Ipsec : return ServiceType::Vpn;
|
||||
case DockerContainer::V2Ray : return ServiceType::Vpn;
|
||||
|
||||
case DockerContainer::TorWebSite : return ServiceType::Other;
|
||||
case DockerContainer::Dns : return ServiceType::Other;
|
||||
//case DockerContainer::FileShare : return ServiceType::Other;
|
||||
|
|
@ -137,6 +144,7 @@ Proto ContainerProps::defaultProtocol(DockerContainer c)
|
|||
case DockerContainer::ShadowSocks : return Proto::ShadowSocks;
|
||||
case DockerContainer::WireGuard : return Proto::WireGuard;
|
||||
case DockerContainer::Ipsec : return Proto::Ikev2;
|
||||
case DockerContainer::V2Ray : return Proto::V2Ray;
|
||||
|
||||
case DockerContainer::TorWebSite : return Proto::TorWebSite;
|
||||
case DockerContainer::Dns : return Proto::Dns;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ enum DockerContainer {
|
|||
Cloak,
|
||||
WireGuard,
|
||||
Ipsec,
|
||||
V2Ray,
|
||||
|
||||
//non-vpn
|
||||
TorWebSite,
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ enum ErrorCode
|
|||
ShadowSocksExecutableMissing,
|
||||
CloakExecutableMissing,
|
||||
AmneziaServiceConnectionFailed,
|
||||
V2RayExecutableMissing,
|
||||
ExecutableMissing,
|
||||
|
||||
// VPN errors
|
||||
|
|
@ -67,7 +68,9 @@ enum ErrorCode
|
|||
OpenSslFailed,
|
||||
OpenVpnExecutableCrashed,
|
||||
ShadowSocksExecutableCrashed,
|
||||
CloakExecutableCrashed
|
||||
CloakExecutableCrashed,
|
||||
V2RayExecutableCrashed,
|
||||
V2RayKeyMissing
|
||||
};
|
||||
|
||||
} // namespace amnezia
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ QString errorString(ErrorCode code){
|
|||
case (AmneziaServiceConnectionFailed): return QObject::tr("Amnezia helper service error");
|
||||
case (OpenSslFailed): return QObject::tr("OpenSSL failed");
|
||||
|
||||
// V2Ray errors
|
||||
case (V2RayExecutableMissing): return QObject::tr("V2Ray (v2ray) executable missing");
|
||||
case (V2RayKeyMissing): return QObject::tr("V2Ray key missing");
|
||||
|
||||
// VPN errors
|
||||
case (OpenVpnAdaptersInUseError): return QObject::tr("Can't connect: another VPN connection is active");
|
||||
case (OpenVpnTapAdapterError): return QObject::tr("Can't setup OpenVPN TAP network adapter");
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ QString amnezia::scriptFolder(amnezia::DockerContainer container)
|
|||
case DockerContainer::ShadowSocks: return QLatin1String("openvpn_shadowsocks");
|
||||
case DockerContainer::WireGuard: return QLatin1String("wireguard");
|
||||
case DockerContainer::Ipsec: return QLatin1String("ipsec");
|
||||
case DockerContainer::V2Ray: return QLatin1String("openvpn_v2ray_vmess");
|
||||
|
||||
case DockerContainer::TorWebSite: return QLatin1String("website_tor");
|
||||
case DockerContainer::Dns: return QLatin1String("dns");
|
||||
|
|
@ -44,6 +45,8 @@ QString amnezia::scriptName(ProtocolScriptType type)
|
|||
case ProtocolScriptType::container_startup: return QLatin1String("start.sh");
|
||||
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
|
||||
case ProtocolScriptType::wireguard_template: return QLatin1String("template.conf");
|
||||
case ProtocolScriptType::v2ray_client_template: return QLatin1String("template_v2ray_client.json");
|
||||
case ProtocolScriptType::shadowsocks_client_template: return QLatin1String("template_ss_client.json");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ enum ProtocolScriptType {
|
|||
configure_container,
|
||||
container_startup,
|
||||
openvpn_template,
|
||||
wireguard_template
|
||||
wireguard_template,
|
||||
v2ray_client_template,
|
||||
shadowsocks_client_template
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -516,6 +516,7 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
|||
const QJsonObject &ssConfig = config.value(ProtocolProps::protoToString(Proto::ShadowSocks)).toObject();
|
||||
const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject();
|
||||
const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject();
|
||||
const QJsonObject &v2RayConfig = config.value(ProtocolProps::protoToString(Proto::V2Ray)).toObject();
|
||||
//
|
||||
|
||||
Vars vars;
|
||||
|
|
@ -567,6 +568,10 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
|||
|
||||
vars.append({{"$WIREGUARD_SERVER_PORT", wireguarConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) }});
|
||||
|
||||
// V2Ray vars
|
||||
vars.append({{"$V2RAY_VMESS_PORT", v2RayConfig.value(config_key::port).toString(protocols::v2ray::defaultServerPort) }});
|
||||
vars.append({{"$V2RAY_SOCKS_LOCAL_PORT", v2RayConfig.value(config_key::local_port).toString(protocols::v2ray::defaultLocalPort) }});
|
||||
|
||||
// IPsec vars
|
||||
vars.append({{"$IPSEC_VPN_L2TP_NET", "192.168.42.0/24"}});
|
||||
vars.append({{"$IPSEC_VPN_L2TP_POOL", "192.168.42.10-192.168.42.250"}});
|
||||
|
|
|
|||
|
|
@ -52,26 +52,25 @@ ErrorCode OpenVpnOverCloakProtocol::start()
|
|||
args << "-u";
|
||||
}
|
||||
|
||||
qDebug().noquote() << "OpenVpnOverCloakProtocol::start()"
|
||||
<< cloakExecPath() << args.join(" ");
|
||||
qDebug().noquote() << "OpenVpnOverCloakProtocol::start()" << cloakExecPath() << args.join(" ");
|
||||
|
||||
m_ckProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
m_ckProcess.setProgram(cloakExecPath());
|
||||
m_ckProcess.setArguments(args);
|
||||
|
||||
connect(&m_ckProcess, &QProcess::readyReadStandardOutput, this, [this](){
|
||||
connect(&m_ckProcess, &QProcess::readyReadStandardOutput, this, [this]() {
|
||||
qDebug().noquote() << "ck-client:" << m_ckProcess.readAllStandardOutput();
|
||||
});
|
||||
|
||||
m_errorHandlerConnection = connect(&m_ckProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus){
|
||||
m_errorHandlerConnection = connect(&m_ckProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
qDebug().noquote() << "OpenVpnOverCloakProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
|
||||
setConnectionState(VpnProtocol::Disconnected);
|
||||
if (exitStatus != QProcess::NormalExit){
|
||||
if (exitStatus != QProcess::NormalExit) {
|
||||
emit protocolError(amnezia::ErrorCode::CloakExecutableCrashed);
|
||||
stop();
|
||||
}
|
||||
if (exitCode !=0 ){
|
||||
if (exitCode !=0 ) {
|
||||
emit protocolError(amnezia::ErrorCode::InternalError);
|
||||
stop();
|
||||
}
|
||||
|
|
@ -84,8 +83,9 @@ ErrorCode OpenVpnOverCloakProtocol::start()
|
|||
setConnectionState(VpnConnectionState::Connecting);
|
||||
|
||||
return OpenVpnProtocol::start();
|
||||
} else {
|
||||
return ErrorCode::CloakExecutableMissing;
|
||||
}
|
||||
else return ErrorCode::CloakExecutableMissing;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ QMap<amnezia::Proto, QString> ProtocolProps::protocolHumanNames()
|
|||
{Proto::WireGuard, "WireGuard"},
|
||||
{Proto::Ikev2, "IKEv2"},
|
||||
{Proto::L2tp, "L2TP"},
|
||||
{Proto::V2Ray, "V2Ray"},
|
||||
|
||||
{Proto::TorWebSite, "Web site in Tor network"},
|
||||
{Proto::Dns, "DNS Service"},
|
||||
|
|
@ -96,10 +97,12 @@ amnezia::ServiceType ProtocolProps::protocolService(Proto p)
|
|||
case Proto::Cloak : return ServiceType::Vpn;
|
||||
case Proto::ShadowSocks : return ServiceType::Vpn;
|
||||
case Proto::WireGuard : return ServiceType::Vpn;
|
||||
case Proto::TorWebSite : return ServiceType::Other;
|
||||
case Proto::V2Ray : return ServiceType::Vpn;
|
||||
|
||||
case Proto::TorWebSite : return ServiceType::Other;
|
||||
case Proto::Dns : return ServiceType::Other;
|
||||
case Proto::FileShare : return ServiceType::Other;
|
||||
default: return ServiceType::Other;
|
||||
default: return ServiceType::Other;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,12 +116,13 @@ int ProtocolProps::defaultPort(Proto p)
|
|||
case Proto::WireGuard : return 51820;
|
||||
case Proto::Ikev2 : return -1;
|
||||
case Proto::L2tp : return -1;
|
||||
case Proto::V2Ray : return 10086;
|
||||
|
||||
case Proto::TorWebSite : return -1;
|
||||
case Proto::Dns : return 53;
|
||||
case Proto::FileShare : return 139;
|
||||
case Proto::Sftp : return 222;
|
||||
default: return -1;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,12 +136,13 @@ bool ProtocolProps::defaultPortChangeable(Proto p)
|
|||
case Proto::WireGuard : return true;
|
||||
case Proto::Ikev2 : return false;
|
||||
case Proto::L2tp : return false;
|
||||
case Proto::V2Ray : return true;
|
||||
|
||||
|
||||
case Proto::TorWebSite : return true;
|
||||
case Proto::Dns : return false;
|
||||
case Proto::FileShare : return false;
|
||||
default: return -1;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,6 +156,7 @@ TransportProto ProtocolProps::defaultTransportProto(Proto p)
|
|||
case Proto::WireGuard : return TransportProto::Udp;
|
||||
case Proto::Ikev2 : return TransportProto::Udp;
|
||||
case Proto::L2tp : return TransportProto::Udp;
|
||||
case Proto::V2Ray : return TransportProto::Tcp;
|
||||
// non-vpn
|
||||
case Proto::TorWebSite : return TransportProto::Tcp;
|
||||
case Proto::Dns : return TransportProto::Udp;
|
||||
|
|
@ -169,12 +175,13 @@ bool ProtocolProps::defaultTransportProtoChangeable(Proto p)
|
|||
case Proto::WireGuard : return false;
|
||||
case Proto::Ikev2 : return false;
|
||||
case Proto::L2tp : return false;
|
||||
case Proto::V2Ray : return false;
|
||||
// non-vpn
|
||||
case Proto::TorWebSite : return false;
|
||||
case Proto::Dns : return false;
|
||||
case Proto::FileShare : return false;
|
||||
case Proto::Sftp : return false;
|
||||
default: return false;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,6 +124,12 @@ constexpr char serverPskKeyPath[] = "/opt/amnezia/wireguard/wireguard_psk.key";
|
|||
|
||||
}
|
||||
|
||||
namespace v2ray {
|
||||
constexpr char v2rayKeyPath[] = "/opt/amnezia/v2ray/v2ray.key";
|
||||
constexpr char defaultLocalPort[] = "1080";
|
||||
constexpr char defaultServerPort[] = "10086";
|
||||
}
|
||||
|
||||
namespace sftp {
|
||||
constexpr char defaultUserName[] = "sftp_user";
|
||||
|
||||
|
|
@ -148,6 +154,7 @@ enum Proto {
|
|||
WireGuard,
|
||||
Ikev2,
|
||||
L2tp,
|
||||
V2Ray,
|
||||
|
||||
// non-vpn
|
||||
TorWebSite,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <QJsonObject>
|
||||
|
||||
ShadowSocksVpnProtocol::ShadowSocksVpnProtocol(const QJsonObject &configuration, QObject *parent):
|
||||
OpenVpnProtocol(configuration, parent)
|
||||
OpenVpnProtocol(configuration, parent)
|
||||
{
|
||||
readShadowSocksConfiguration(configuration);
|
||||
}
|
||||
|
|
@ -32,7 +32,6 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
|||
return lastError();
|
||||
}
|
||||
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
if (Utils::processIsRunning(Utils::executable("ss-local", false))) {
|
||||
Utils::killProcessByName(Utils::executable("ss-local", false));
|
||||
|
|
@ -48,30 +47,28 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
|||
#ifdef Q_OS_LINUX
|
||||
QStringList args = QStringList() << "-c" << m_shadowSocksCfgFile.fileName();
|
||||
#else
|
||||
QStringList args = QStringList() << "-c" << m_shadowSocksCfgFile.fileName()
|
||||
<< "--no-delay";
|
||||
QStringList args = QStringList() << "-c" << m_shadowSocksCfgFile.fileName() << "--no-delay";
|
||||
#endif
|
||||
|
||||
qDebug().noquote() << "ShadowSocksVpnProtocol::start()"
|
||||
<< shadowSocksExecPath() << args.join(" ");
|
||||
qDebug().noquote() << "ShadowSocksVpnProtocol::start()" << shadowSocksExecPath() << args.join(" ");
|
||||
|
||||
m_ssProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
m_ssProcess.setProgram(shadowSocksExecPath());
|
||||
m_ssProcess.setArguments(args);
|
||||
|
||||
connect(&m_ssProcess, &QProcess::readyReadStandardOutput, this, [this](){
|
||||
connect(&m_ssProcess, &QProcess::readyReadStandardOutput, this, [this]() {
|
||||
qDebug().noquote() << "ss-local:" << m_ssProcess.readAllStandardOutput();
|
||||
});
|
||||
|
||||
connect(&m_ssProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus){
|
||||
connect(&m_ssProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
qDebug().noquote() << "ShadowSocksVpnProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
|
||||
setConnectionState(VpnProtocol::Disconnected);
|
||||
if (exitStatus != QProcess::NormalExit){
|
||||
if (exitStatus != QProcess::NormalExit) {
|
||||
emit protocolError(amnezia::ErrorCode::ShadowSocksExecutableCrashed);
|
||||
stop();
|
||||
}
|
||||
if (exitCode !=0 ){
|
||||
if (exitCode !=0 ) {
|
||||
emit protocolError(amnezia::ErrorCode::InternalError);
|
||||
stop();
|
||||
}
|
||||
|
|
@ -84,8 +81,9 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
|||
setConnectionState(VpnConnectionState::Connecting);
|
||||
|
||||
return OpenVpnProtocol::start();
|
||||
} else {
|
||||
return ErrorCode::ShadowSocksExecutableMissing;
|
||||
}
|
||||
else return ErrorCode::ShadowSocksExecutableMissing;
|
||||
#else
|
||||
return ErrorCode::NotImplementedError;
|
||||
#endif
|
||||
|
|
@ -116,17 +114,5 @@ QString ShadowSocksVpnProtocol::shadowSocksExecPath()
|
|||
|
||||
void ShadowSocksVpnProtocol::readShadowSocksConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
QJsonObject shadowSocksConfig = configuration.value(ProtocolProps::key_proto_config_data(Proto::ShadowSocks)).toObject();
|
||||
bool isLocalPortConvertOk = false;
|
||||
bool isServerPortConvertOk = false;
|
||||
int localPort = shadowSocksConfig.value("local_port").toString().toInt(&isLocalPortConvertOk);
|
||||
int serverPort = shadowSocksConfig.value("server_port").toString().toInt(&isServerPortConvertOk);
|
||||
if (!isLocalPortConvertOk) {
|
||||
qDebug() << "Error when converting local_port field in ShadowSocks config";
|
||||
} else if (!isServerPortConvertOk) {
|
||||
qDebug() << "Error when converting server_port field in ShadowSocks config";
|
||||
}
|
||||
shadowSocksConfig["local_port"] = localPort;
|
||||
shadowSocksConfig["server_port"] = serverPort;
|
||||
m_shadowSocksConfig = shadowSocksConfig;
|
||||
m_shadowSocksConfig = configuration.value(ProtocolProps::key_proto_config_data(Proto::ShadowSocks)).toObject();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef SHADOWSOCKSVPNPROTOCOL_H
|
||||
#define SHADOWSOCKSVPNPROTOCOL_H
|
||||
|
||||
#include "openvpnprotocol.h"
|
||||
#include "QProcess"
|
||||
#include "containers/containers_defs.h"
|
||||
|
||||
#include "openvpnprotocol.h"
|
||||
|
||||
class ShadowSocksVpnProtocol : public OpenVpnProtocol
|
||||
{
|
||||
|
|
@ -14,20 +14,18 @@ public:
|
|||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
protected:
|
||||
void readShadowSocksConfiguration(const QJsonObject &configuration);
|
||||
|
||||
protected:
|
||||
QJsonObject m_shadowSocksConfig;
|
||||
|
||||
private:
|
||||
static QString shadowSocksExecPath();
|
||||
void readShadowSocksConfiguration(const QJsonObject &configuration);
|
||||
|
||||
private:
|
||||
#ifndef Q_OS_IOS
|
||||
QProcess m_ssProcess;
|
||||
#endif
|
||||
QTemporaryFile m_shadowSocksCfgFile;
|
||||
|
||||
static QString shadowSocksExecPath();
|
||||
};
|
||||
|
||||
#endif // SHADOWSOCKSVPNPROTOCOL_H
|
||||
|
|
|
|||
108
client/protocols/v2rayprotocol.cpp
Normal file
108
client/protocols/v2rayprotocol.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#include "v2rayprotocol.h"
|
||||
|
||||
#include <QThread>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
V2RayProtocol::V2RayProtocol(const QJsonObject &configuration, QObject *parent) : OpenVpnProtocol(configuration, parent)
|
||||
{
|
||||
writeV2RayConfiguration(configuration);
|
||||
}
|
||||
|
||||
V2RayProtocol::~V2RayProtocol()
|
||||
{
|
||||
qDebug() << "V2RayProtocol::~V2RayProtocol";
|
||||
V2RayProtocol::stop();
|
||||
QThread::msleep(200);
|
||||
}
|
||||
|
||||
ErrorCode V2RayProtocol::start()
|
||||
{
|
||||
#ifndef Q_OS_IOS
|
||||
if (!QFileInfo::exists(v2RayExecPath())) {
|
||||
setLastError(ErrorCode::V2RayExecutableMissing);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
if (Utils::processIsRunning(Utils::executable("v2ray", false))) {
|
||||
Utils::killProcessByName(Utils::executable("v2ray", false));
|
||||
}
|
||||
|
||||
QStringList args = QStringList() << "-c" << m_v2RayConfigFile.fileName();
|
||||
|
||||
qDebug().noquote() << "V2RayProtocol::start()" << v2RayExecPath() << args.join(" ");
|
||||
|
||||
m_v2RayProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
m_v2RayProcess.setProgram(v2RayExecPath());
|
||||
m_v2RayProcess.setArguments(args);
|
||||
|
||||
connect(&m_v2RayProcess, &QProcess::readyReadStandardOutput, this, [this]() {
|
||||
qDebug().noquote() << "V2Ray:" << m_v2RayProcess.readAllStandardOutput();
|
||||
});
|
||||
|
||||
connect(&m_v2RayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
qDebug().noquote() << "V2RayProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
|
||||
setConnectionState(VpnProtocol::Disconnected);
|
||||
if (exitStatus != QProcess::NormalExit) {
|
||||
emit protocolError(amnezia::ErrorCode::V2RayExecutableCrashed);
|
||||
stop();
|
||||
}
|
||||
if (exitCode != 0 ) {
|
||||
emit protocolError(amnezia::ErrorCode::InternalError);
|
||||
stop();
|
||||
}
|
||||
});
|
||||
|
||||
m_v2RayProcess.start();
|
||||
m_v2RayProcess.waitForStarted();
|
||||
|
||||
if (m_v2RayProcess.state() == QProcess::ProcessState::Running) {
|
||||
setConnectionState(VpnConnectionState::Connecting);
|
||||
|
||||
return OpenVpnProtocol::start();
|
||||
} else {
|
||||
return ErrorCode::V2RayExecutableMissing;
|
||||
}
|
||||
#else
|
||||
return ErrorCode::NotImplementedError;
|
||||
#endif
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
void V2RayProtocol::stop()
|
||||
{
|
||||
OpenVpnProtocol::stop();
|
||||
|
||||
qDebug() << "V2RayProtocol::stop()";
|
||||
#ifndef Q_OS_IOS
|
||||
m_v2RayProcess.terminate();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
Utils::signalCtrl(m_v2RayProcess.processId(), CTRL_C_EVENT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void V2RayProtocol::writeV2RayConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
m_v2RayConfig = configuration.value(ProtocolProps::key_proto_config_data(Proto::V2Ray)).toObject();
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
m_v2RayConfigFile.setAutoRemove(false);
|
||||
#endif
|
||||
m_v2RayConfigFile.open();
|
||||
m_v2RayConfigFile.write(QJsonDocument(m_v2RayConfig).toJson());
|
||||
m_v2RayConfigFile.close();
|
||||
}
|
||||
|
||||
const QString V2RayProtocol::v2RayExecPath() const
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return Utils::executable(QString("v2ray/v2ray"), true);
|
||||
#else
|
||||
return Utils::executable(QString("v2ray"), true);
|
||||
#endif
|
||||
}
|
||||
30
client/protocols/v2rayprotocol.h
Normal file
30
client/protocols/v2rayprotocol.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef V2RAYPROTOCOL_H
|
||||
#define V2RAYPROTOCOL_H
|
||||
|
||||
#include "QProcess"
|
||||
#include "QTemporaryFile"
|
||||
|
||||
#include "openvpnprotocol.h"
|
||||
|
||||
class V2RayProtocol : public OpenVpnProtocol
|
||||
{
|
||||
public:
|
||||
V2RayProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
virtual ~V2RayProtocol() override;
|
||||
|
||||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
private:
|
||||
QJsonObject m_v2RayConfig;
|
||||
QTemporaryFile m_v2RayConfigFile;
|
||||
#ifndef Q_OS_IOS
|
||||
QProcess m_v2RayProcess;
|
||||
#endif
|
||||
|
||||
void writeV2RayConfiguration(const QJsonObject &configuration);
|
||||
|
||||
const QString v2RayExecPath() const;
|
||||
};
|
||||
|
||||
#endif // V2RAYPROTOCOL_H
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#include "shadowsocksvpnprotocol.h"
|
||||
#include "openvpnovercloakprotocol.h"
|
||||
#include "wireguardprotocol.h"
|
||||
#include "v2rayprotocol.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
|
@ -114,6 +115,7 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject&
|
|||
case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration);
|
||||
case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration);
|
||||
case DockerContainer::WireGuard: return new WireguardProtocol(configuration);
|
||||
case DockerContainer::V2Ray: return new V2RayProtocol(configuration);
|
||||
#endif
|
||||
default: return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,5 +166,13 @@
|
|||
<file>ui/qml/Pages/PageAdvancedServerSettings.qml</file>
|
||||
<file>ui/qml/Controls/PopupWarning.qml</file>
|
||||
<file>ui/qml/Controls/PopupWithTextField.qml</file>
|
||||
<file>ui/qml/Pages/Protocols/PageProtoV2Ray.qml</file>
|
||||
<file>server_scripts/openvpn_v2ray_vmess/configure_container.sh</file>
|
||||
<file>server_scripts/openvpn_v2ray_vmess/Dockerfile</file>
|
||||
<file>server_scripts/openvpn_v2ray_vmess/run_container.sh</file>
|
||||
<file>server_scripts/openvpn_v2ray_vmess/start.sh</file>
|
||||
<file>server_scripts/openvpn_v2ray_vmess/template.ovpn</file>
|
||||
<file>server_scripts/openvpn_v2ray_vmess/template_v2ray_client.json</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/template_ss_client.json</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
sudo docker build -t $CONTAINER_NAME $DOCKERFILE_FOLDER --build-arg SERVER_ARCH=$(uname -m)
|
||||
sudo docker build --network host -t $CONTAINER_NAME $DOCKERFILE_FOLDER --build-arg SERVER_ARCH=$(uname -m)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"local_port": $SHADOWSOCKS_LOCAL_PORT,
|
||||
"method": "$SHADOWSOCKS_CIPHER",
|
||||
"password": "$SHADOWSOCKS_PASSWORD",
|
||||
"server": "$REMOTE_HOST",
|
||||
"server_port": $SHADOWSOCKS_SERVER_PORT,
|
||||
"timeout": 60
|
||||
}
|
||||
51
client/server_scripts/openvpn_v2ray_vmess/Dockerfile
Normal file
51
client/server_scripts/openvpn_v2ray_vmess/Dockerfile
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
FROM alpine:3.15
|
||||
|
||||
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
|
||||
|
||||
RUN apk add --no-cache v2ray
|
||||
|
||||
# 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,70 @@
|
|||
cat > /opt/amnezia/openvpn/server.conf <<EOF
|
||||
port $OPENVPN_PORT
|
||||
proto $OPENVPN_TRANSPORT_PROTO
|
||||
dev tun
|
||||
ca /opt/amnezia/openvpn/ca.crt
|
||||
cert /opt/amnezia/openvpn/AmneziaReq.crt
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key
|
||||
dh /opt/amnezia/openvpn/dh.pem
|
||||
server $OPENVPN_SUBNET_IP $OPENVPN_SUBNET_MASK
|
||||
ifconfig-pool-persist ipp.txt
|
||||
duplicate-cn
|
||||
keepalive 10 120
|
||||
$OPENVPN_NCP_DISABLE
|
||||
cipher $OPENVPN_CIPHER
|
||||
data-ciphers $OPENVPN_CIPHER
|
||||
auth $OPENVPN_HASH
|
||||
user nobody
|
||||
group nobody
|
||||
persist-key
|
||||
persist-tun
|
||||
status openvpn-status.log
|
||||
verb 1
|
||||
tls-server
|
||||
tls-version-min 1.2
|
||||
$OPENVPN_TLS_AUTH
|
||||
$OPENVPN_ADDITIONAL_SERVER_CONFIG
|
||||
EOF
|
||||
|
||||
# V2RAY_VMESS_PORT port for v2ray listening, for example 10086.
|
||||
# V2RAY_VMESS_CLIENT_UUID client's id and secret as UUID.
|
||||
# UUID is 32 hexadecimal digits /([0-9a-f]-?){32}/ (128 bit value).
|
||||
|
||||
mkdir -p /opt/amnezia/v2ray
|
||||
cd /opt/amnezia/v2ray
|
||||
V2RAY_VMESS_CLIENT_UUID=$(cat /proc/sys/kernel/random/uuid)
|
||||
echo $V2RAY_VMESS_CLIENT_UUID > /opt/amnezia/v2ray/v2ray.key
|
||||
|
||||
cat > /opt/amnezia/v2ray/v2ray-server.json <<EOF
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "None"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"port": $V2RAY_VMESS_PORT,
|
||||
"protocol": "vmess",
|
||||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "$V2RAY_VMESS_CLIENT_UUID",
|
||||
"level": 1,
|
||||
"alterId": 64
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "freedom",
|
||||
"settings": {}
|
||||
}
|
||||
],
|
||||
"policy": {
|
||||
"levels": {
|
||||
"0": {"uplinkOnly": 0}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
24
client/server_scripts/openvpn_v2ray_vmess/run_container.sh
Normal file
24
client/server_scripts/openvpn_v2ray_vmess/run_container.sh
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Run container
|
||||
sudo docker run -d \
|
||||
--log-driver none \
|
||||
--restart always \
|
||||
--cap-add=NET_ADMIN \
|
||||
-p $V2RAY_VMESS_PORT:$V2RAY_VMESS_PORT/tcp \
|
||||
--name $CONTAINER_NAME $CONTAINER_NAME
|
||||
|
||||
sudo docker network connect amnezia-dns-net $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'
|
||||
31
client/server_scripts/openvpn_v2ray_vmess/start.sh
Normal file
31
client/server_scripts/openvpn_v2ray_vmess/start.sh
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container startup"
|
||||
ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
||||
|
||||
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 $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -o eth1 -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -j ACCEPT
|
||||
|
||||
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth1 -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
|
||||
if [ -f /opt/amnezia/v2ray/v2ray-server.json ]; then (v2ray -config /opt/amnezia/v2ray/v2ray-server.json &); fi
|
||||
|
||||
tail -f /dev/null
|
||||
39
client/server_scripts/openvpn_v2ray_vmess/template.ovpn
Normal file
39
client/server_scripts/openvpn_v2ray_vmess/template.ovpn
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
client
|
||||
dev tun
|
||||
proto $OPENVPN_TRANSPORT_PROTO
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
$OPENVPN_NCP_DISABLE
|
||||
cipher $OPENVPN_CIPHER
|
||||
auth $OPENVPN_HASH
|
||||
verb 3
|
||||
tls-client
|
||||
tls-version-min 1.2
|
||||
key-direction 1
|
||||
remote-cert-tls server
|
||||
redirect-gateway def1 bypass-dhcp
|
||||
|
||||
dhcp-option DNS $PRIMARY_DNS
|
||||
dhcp-option DNS $SECONDARY_DNS
|
||||
block-outside-dns
|
||||
|
||||
socks-proxy 127.0.0.1 $V2RAY_SOCKS_LOCAL_PORT
|
||||
route $REMOTE_HOST 255.255.255.255 net_gateway
|
||||
remote 127.0.0.1 $OPENVPN_PORT
|
||||
|
||||
$OPENVPN_ADDITIONAL_CLIENT_CONFIG
|
||||
|
||||
<ca>
|
||||
$OPENVPN_CA_CERT
|
||||
</ca>
|
||||
<cert>
|
||||
$OPENVPN_CLIENT_CERT
|
||||
</cert>
|
||||
<key>
|
||||
$OPENVPN_PRIV_KEY
|
||||
</key>
|
||||
<tls-auth>
|
||||
$OPENVPN_TA_KEY
|
||||
</tls-auth>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"inbounds": [
|
||||
{
|
||||
"listen": "127.0.0.1",
|
||||
"port": $V2RAY_SOCKS_LOCAL_PORT,
|
||||
"protocol": "socks",
|
||||
"settings": {
|
||||
"auth": "noauth",
|
||||
"udp": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "vmess",
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "$REMOTE_HOST",
|
||||
"port": $V2RAY_VMESS_PORT,
|
||||
"users": [
|
||||
{
|
||||
"id": "$V2RAY_VMESS_CLIENT_UUID"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@ public:
|
|||
friend class ShadowSocksLogic;
|
||||
friend class CloakLogic;
|
||||
friend class UiLogic;
|
||||
friend class V2RayLogic;
|
||||
|
||||
void onUpdatePage() override;
|
||||
ErrorCode doInstallAction(const std::function<ErrorCode()> &action);
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ void OpenVpnLogic::onPushButtonSaveClicked()
|
|||
auto installAction = [this, containerConfig, &newContainerConfig]() {
|
||||
ServerController serverController(m_settings);
|
||||
return serverController.updateContainer(m_settings->serverCredentials(uiLogic()->m_selectedServerIndex),
|
||||
uiLogic()->m_selectedDockerContainer, containerConfig, newContainerConfig);
|
||||
uiLogic()->m_selectedDockerContainer, containerConfig, newContainerConfig);
|
||||
};
|
||||
|
||||
ErrorCode e = uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->doInstallAction(installAction, pageFunc, progressBarFunc,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ QJsonObject ShadowSocksLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
|
|||
void ShadowSocksLogic::onPushButtonSaveClicked()
|
||||
{
|
||||
QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer, Proto::ShadowSocks);
|
||||
protocolConfig = getProtocolConfigFromPage(protocolConfig);
|
||||
|
||||
QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer);
|
||||
QJsonObject newContainerConfig = containerConfig;
|
||||
|
|
@ -108,7 +109,7 @@ void ShadowSocksLogic::onPushButtonSaveClicked()
|
|||
auto installAction = [this, containerConfig, &newContainerConfig]() {
|
||||
ServerController serverController(m_settings);
|
||||
return serverController.updateContainer(m_settings->serverCredentials(uiLogic()->m_selectedServerIndex),
|
||||
uiLogic()->m_selectedDockerContainer, containerConfig, newContainerConfig);
|
||||
uiLogic()->m_selectedDockerContainer, containerConfig, newContainerConfig);
|
||||
};
|
||||
ErrorCode e = uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->doInstallAction(installAction, pageFunc, progressBarFunc,
|
||||
saveButtonFunc, waitInfoFunc,
|
||||
|
|
|
|||
128
client/ui/pages_logic/protocols/V2RayLogic.cpp
Normal file
128
client/ui/pages_logic/protocols/V2RayLogic.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#include "V2RayLogic.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "core/servercontroller.h"
|
||||
#include "ui/pages_logic/ServerConfiguringProgressLogic.h"
|
||||
#include "ui/uilogic.h"
|
||||
|
||||
using namespace amnezia;
|
||||
using namespace PageEnumNS;
|
||||
|
||||
V2RayLogic::V2RayLogic(UiLogic *logic, QObject *parent):
|
||||
PageProtocolLogicBase(logic, parent),
|
||||
m_lineEditServerPortText{},
|
||||
m_pushButtonSaveVisible{false},
|
||||
m_progressBarResetVisible{false},
|
||||
m_lineEditServerPortEnabled{false},
|
||||
m_labelInfoVisible{true},
|
||||
m_labelInfoText{},
|
||||
m_progressBarResetValue{0},
|
||||
m_progressBarResetMaximium{100},
|
||||
m_lineEditLocalPortEnabled{false},
|
||||
m_lineEditLocalPortText{}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void V2RayLogic::updateProtocolPage(const QJsonObject &v2RayConfig, DockerContainer container, bool haveAuthData)
|
||||
{
|
||||
set_pageEnabled(haveAuthData);
|
||||
set_pushButtonSaveVisible(haveAuthData);
|
||||
set_progressBarResetVisible(haveAuthData);
|
||||
|
||||
set_lineEditServerPortText(v2RayConfig.value(config_key::port).toString(protocols::v2ray::defaultServerPort));
|
||||
set_lineEditServerPortEnabled(container == DockerContainer::V2Ray);
|
||||
|
||||
set_lineEditLocalPortText(v2RayConfig.value(config_key::local_port).toString(protocols::v2ray::defaultLocalPort));
|
||||
set_lineEditLocalPortEnabled(container == DockerContainer::V2Ray);
|
||||
|
||||
}
|
||||
|
||||
QJsonObject V2RayLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
|
||||
{
|
||||
oldConfig.insert(config_key::port, lineEditServerPortText());
|
||||
oldConfig.insert(config_key::local_port, lineEditLocalPortText());
|
||||
return oldConfig;
|
||||
}
|
||||
|
||||
void V2RayLogic::onPushButtonSaveClicked()
|
||||
{
|
||||
QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer, Proto::V2Ray);
|
||||
protocolConfig = getProtocolConfigFromPage(protocolConfig);
|
||||
|
||||
QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer);
|
||||
QJsonObject newContainerConfig = containerConfig;
|
||||
newContainerConfig.insert(ProtocolProps::protoToString(Proto::V2Ray), protocolConfig);
|
||||
ServerConfiguringProgressLogic::PageFunc pageFunc;
|
||||
pageFunc.setEnabledFunc = [this] (bool enabled) -> void {
|
||||
set_pageEnabled(enabled);
|
||||
};
|
||||
ServerConfiguringProgressLogic::ButtonFunc saveButtonFunc;
|
||||
saveButtonFunc.setVisibleFunc = [this] (bool visible) -> void {
|
||||
set_pushButtonSaveVisible(visible);
|
||||
};
|
||||
ServerConfiguringProgressLogic::LabelFunc waitInfoFunc;
|
||||
waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void {
|
||||
set_labelInfoVisible(visible);
|
||||
};
|
||||
waitInfoFunc.setTextFunc = [this] (const QString& text) -> void {
|
||||
set_labelInfoText(text);
|
||||
};
|
||||
ServerConfiguringProgressLogic::ProgressFunc progressBarFunc;
|
||||
progressBarFunc.setVisibleFunc = [this] (bool visible) -> void {
|
||||
set_progressBarResetVisible(visible);
|
||||
};
|
||||
progressBarFunc.setValueFunc = [this] (int value) -> void {
|
||||
set_progressBarResetValue(value);
|
||||
};
|
||||
progressBarFunc.getValueFunc = [this] (void) -> int {
|
||||
return progressBarResetValue();
|
||||
};
|
||||
progressBarFunc.getMaximiumFunc = [this] (void) -> int {
|
||||
return progressBarResetMaximium();
|
||||
};
|
||||
progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void {
|
||||
set_progressBarTextVisible(visible);
|
||||
};
|
||||
progressBarFunc.setTextFunc = [this] (const QString& text) -> void {
|
||||
set_progressBarText(text);
|
||||
};
|
||||
|
||||
ServerConfiguringProgressLogic::LabelFunc busyInfoFuncy;
|
||||
busyInfoFuncy.setTextFunc = [this] (const QString& text) -> void {
|
||||
set_labelServerBusyText(text);
|
||||
};
|
||||
busyInfoFuncy.setVisibleFunc = [this] (bool visible) -> void {
|
||||
set_labelServerBusyVisible(visible);
|
||||
};
|
||||
|
||||
ServerConfiguringProgressLogic::ButtonFunc cancelButtonFunc;
|
||||
cancelButtonFunc.setVisibleFunc = [this] (bool visible) -> void {
|
||||
set_pushButtonCancelVisible(visible);
|
||||
};
|
||||
|
||||
progressBarFunc.setTextVisibleFunc(true);
|
||||
progressBarFunc.setTextFunc(QString("Configuring..."));
|
||||
|
||||
auto installAction = [this, containerConfig, &newContainerConfig]() {
|
||||
ServerController serverController(m_settings);
|
||||
return serverController.updateContainer(m_settings->serverCredentials(uiLogic()->m_selectedServerIndex),
|
||||
uiLogic()->m_selectedDockerContainer, containerConfig, newContainerConfig);
|
||||
};
|
||||
|
||||
ErrorCode e = uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->doInstallAction(installAction, pageFunc, progressBarFunc,
|
||||
saveButtonFunc, waitInfoFunc,
|
||||
busyInfoFuncy, cancelButtonFunc);
|
||||
|
||||
if (!e) {
|
||||
m_settings->setContainerConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer, newContainerConfig);
|
||||
m_settings->clearLastConnectionConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer);
|
||||
}
|
||||
qDebug() << "Protocol saved with code:" << e << "for" << uiLogic()->m_selectedServerIndex << uiLogic()->m_selectedDockerContainer;
|
||||
}
|
||||
|
||||
void V2RayLogic::onPushButtonCancelClicked()
|
||||
{
|
||||
emit uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->cancelDoInstallAction(true);
|
||||
}
|
||||
50
client/ui/pages_logic/protocols/V2RayLogic.h
Normal file
50
client/ui/pages_logic/protocols/V2RayLogic.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef V2RAYLOGIC_H
|
||||
#define V2RAYLOGIC_H
|
||||
|
||||
#include "PageProtocolLogicBase.h"
|
||||
|
||||
class UiLogic;
|
||||
|
||||
class V2RayLogic : public PageProtocolLogicBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
AUTO_PROPERTY(bool, lineEditServerPortEnabled)
|
||||
AUTO_PROPERTY(QString, lineEditServerPortText)
|
||||
|
||||
AUTO_PROPERTY(bool, lineEditLocalPortEnabled)
|
||||
AUTO_PROPERTY(QString, lineEditLocalPortText)
|
||||
|
||||
AUTO_PROPERTY(bool, labelInfoVisible)
|
||||
AUTO_PROPERTY(QString, labelInfoText)
|
||||
|
||||
AUTO_PROPERTY(int, progressBarResetValue)
|
||||
AUTO_PROPERTY(int, progressBarResetMaximium)
|
||||
AUTO_PROPERTY(bool, progressBarResetVisible)
|
||||
AUTO_PROPERTY(bool, progressBarTextVisible)
|
||||
AUTO_PROPERTY(QString, progressBarText)
|
||||
|
||||
AUTO_PROPERTY(bool, labelServerBusyVisible)
|
||||
AUTO_PROPERTY(QString, labelServerBusyText)
|
||||
|
||||
AUTO_PROPERTY(bool, pushButtonSaveVisible)
|
||||
AUTO_PROPERTY(bool, pushButtonCancelVisible)
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void onPushButtonSaveClicked();
|
||||
Q_INVOKABLE void onPushButtonCancelClicked();
|
||||
|
||||
public:
|
||||
explicit V2RayLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||
~V2RayLogic() = default;
|
||||
|
||||
void updateProtocolPage(const QJsonObject &v2rayConfig, DockerContainer container, bool haveAuthData) override;
|
||||
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
|
||||
|
||||
private:
|
||||
UiLogic *m_uiLogic;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // V2RAYLOGIC_H
|
||||
158
client/ui/qml/Pages/Protocols/PageProtoV2Ray.qml
Normal file
158
client/ui/qml/Pages/Protocols/PageProtoV2Ray.qml
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import ProtocolEnum 1.0
|
||||
import "../"
|
||||
import "../../Controls"
|
||||
import "../../Config"
|
||||
|
||||
PageProtocolBase {
|
||||
id: root
|
||||
protocol: ProtocolEnum.V2Ray
|
||||
logic: UiLogic.protocolLogic(protocol)
|
||||
|
||||
BackButton {
|
||||
id: back
|
||||
enabled: !logic.pushButtonCancelVisible
|
||||
}
|
||||
|
||||
Caption {
|
||||
id: caption
|
||||
text: qsTr("V2Ray Settings")
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
enabled: logic.pageEnabled
|
||||
anchors.top: caption.bottom
|
||||
anchors.left: root.left
|
||||
anchors.right: root.right
|
||||
anchors.bottom: pb_save.top
|
||||
anchors.margins: 20
|
||||
anchors.topMargin: 10
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
LabelType {
|
||||
Layout.preferredWidth: 0.3 * root.width - 10
|
||||
height: 31
|
||||
text: qsTr("Port")
|
||||
}
|
||||
|
||||
TextFieldType {
|
||||
Layout.fillWidth: true
|
||||
height: 31
|
||||
text: logic.lineEditServerPortText
|
||||
onEditingFinished: {
|
||||
logic.lineEditServerPortText = text
|
||||
}
|
||||
enabled: logic.lineEditServerPortEnabled
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
LabelType {
|
||||
Layout.preferredWidth: 0.3 * root.width - 10
|
||||
height: 31
|
||||
text: qsTr("Local port")
|
||||
}
|
||||
|
||||
TextFieldType {
|
||||
Layout.fillWidth: true
|
||||
height: 31
|
||||
text: logic.lineEditLocalPortText
|
||||
onEditingFinished: {
|
||||
logic.lineEditLocalPortText = text
|
||||
}
|
||||
enabled: logic.lineEditLocalPortEnabled
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
LabelType {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.fillWidth: true
|
||||
visible: logic.labelServerBusyVisible
|
||||
text: logic.labelServerBusyText
|
||||
}
|
||||
|
||||
LabelType {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.fillWidth: true
|
||||
visible: logic.labelInfoVisible
|
||||
text: logic.labelInfoText
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: progressBar_reset
|
||||
anchors.fill: pb_save
|
||||
from: 0
|
||||
to: logic.progressBarResetMaximium
|
||||
value: logic.progressBarResetValue
|
||||
visible: logic.progressBarResetVisible
|
||||
background: Rectangle {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
color: "#100A44"
|
||||
radius: 4
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
Rectangle {
|
||||
width: progressBar_reset.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: 4
|
||||
color: Qt.rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
}
|
||||
LabelType {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: logic.progressBarText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.family: "Lato"
|
||||
font.styleName: "normal"
|
||||
font.pixelSize: 16
|
||||
color: "#D4D4D4"
|
||||
visible: logic.progressBarTextVisible
|
||||
}
|
||||
}
|
||||
|
||||
BlueButtonType {
|
||||
id: pb_save
|
||||
enabled: logic.pageEnabled
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: root.bottom
|
||||
anchors.bottomMargin: 20
|
||||
width: root.width - 60
|
||||
height: 40
|
||||
text: qsTr("Save and restart VPN")
|
||||
visible: logic.pushButtonSaveVisible
|
||||
onClicked: {
|
||||
logic.onPushButtonSaveClicked()
|
||||
}
|
||||
}
|
||||
|
||||
BlueButtonType {
|
||||
anchors.fill: pb_save
|
||||
text: qsTr("Cancel")
|
||||
visible: logic.pushButtonCancelVisible
|
||||
enabled: logic.pushButtonCancelVisible
|
||||
onClicked: {
|
||||
logic.onPushButtonCancelClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,6 +72,7 @@
|
|||
#include "pages_logic/protocols/ShadowSocksLogic.h"
|
||||
#include "pages_logic/protocols/OtherProtocolsLogic.h"
|
||||
#include "pages_logic/protocols/WireGuardLogic.h"
|
||||
#include "pages_logic/protocols/V2RayLogic.h"
|
||||
|
||||
using namespace amnezia;
|
||||
using namespace PageEnumNS;
|
||||
|
|
@ -93,6 +94,7 @@ UiLogic::UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigur
|
|||
m_protocolLogicMap.insert(Proto::ShadowSocks, new ShadowSocksLogic(this));
|
||||
m_protocolLogicMap.insert(Proto::Cloak, new CloakLogic(this));
|
||||
m_protocolLogicMap.insert(Proto::WireGuard, new WireGuardLogic(this));
|
||||
m_protocolLogicMap.insert(Proto::V2Ray, new V2RayLogic(this));
|
||||
|
||||
m_protocolLogicMap.insert(Proto::Dns, new OtherProtocolsLogic(this));
|
||||
m_protocolLogicMap.insert(Proto::Sftp, new OtherProtocolsLogic(this));
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ class PageProtocolLogicBase;
|
|||
class OpenVpnLogic;
|
||||
class ShadowSocksLogic;
|
||||
class CloakLogic;
|
||||
class V2RayLogic;
|
||||
|
||||
class OtherProtocolsLogic;
|
||||
|
||||
|
|
@ -94,6 +95,7 @@ public:
|
|||
friend class OpenVpnLogic;
|
||||
friend class ShadowSocksLogic;
|
||||
friend class CloakLogic;
|
||||
friend class V2RayLogic;
|
||||
|
||||
friend class OtherProtocolsLogic;
|
||||
|
||||
|
|
|
|||
BIN
deploy/data/linux/client/bin/v2ctl
Executable file
BIN
deploy/data/linux/client/bin/v2ctl
Executable file
Binary file not shown.
BIN
deploy/data/linux/client/bin/v2ray
Executable file
BIN
deploy/data/linux/client/bin/v2ray
Executable file
Binary file not shown.
BIN
deploy/data/macos/v2ctl
Executable file
BIN
deploy/data/macos/v2ctl
Executable file
Binary file not shown.
BIN
deploy/data/macos/v2ray
Executable file
BIN
deploy/data/macos/v2ray
Executable file
Binary file not shown.
BIN
deploy/data/windows/x64/v2ray/v2ctl.exe
Normal file
BIN
deploy/data/windows/x64/v2ray/v2ctl.exe
Normal file
Binary file not shown.
BIN
deploy/data/windows/x64/v2ray/v2ray.exe
Normal file
BIN
deploy/data/windows/x64/v2ray/v2ray.exe
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue