mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-02 00:29:04 +02:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 44018ec94c | |||
| 89577651d6 | |||
| 3b2d3a0b34 | |||
| fe3228ed74 | |||
| 917942be94 | |||
| 6a3875ec7f | |||
| e121ca9b53 | |||
| c23c8e8462 | |||
| 36fae9152f | |||
| 2b0ba2aff9 | |||
| 68830021d6 | |||
| 6a903792ab | |||
| d2d9c33837 | |||
| 7d51cb7d58 | |||
| 7df3600a62 | |||
| 634ca6cbe8 | |||
| 8032e55d7c | |||
| dc2a1467c7 | |||
| 67c36f5b30 |
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
+4
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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'
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user