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/openvpnovercloakprotocol.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.h
|
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.h
|
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/protocols/v2rayprotocol.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES ${SOURCES}
|
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/openvpnovercloakprotocol.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.cpp
|
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.cpp
|
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/protocols/v2rayprotocol.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
@ -558,7 +560,7 @@ if(WIN32)
|
||||||
set(DEPLOY_ARTIFACT_PATH "windows/x32")
|
set(DEPLOY_ARTIFACT_PATH "windows/x32")
|
||||||
endif()
|
endif()
|
||||||
elseif(LINUX)
|
elseif(LINUX)
|
||||||
set(DEPLOY_ARTIFACT_PATH "linux/client")
|
set(DEPLOY_ARTIFACT_PATH "linux/client/bin")
|
||||||
elseif(APPLE AND NOT IOS)
|
elseif(APPLE AND NOT IOS)
|
||||||
set(DEPLOY_ARTIFACT_PATH "macos")
|
set(DEPLOY_ARTIFACT_PATH "macos")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -7,18 +7,18 @@
|
||||||
#include "core/servercontroller.h"
|
#include "core/servercontroller.h"
|
||||||
#include "containers/containers_defs.h"
|
#include "containers/containers_defs.h"
|
||||||
|
|
||||||
CloakConfigurator::CloakConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
CloakConfigurator::CloakConfigurator(std::shared_ptr<Settings> settings,
|
||||||
ConfiguratorBase(settings, parent)
|
QObject *parent): ConfiguratorBase(settings, parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials,
|
QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
ErrorCode e = ErrorCode::NoError;
|
ErrorCode e = ErrorCode::NoError;
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
|
|
||||||
|
|
||||||
QString cloakPublicKey = serverController.getTextFileFromContainer(container, credentials,
|
QString cloakPublicKey = serverController.getTextFileFromContainer(container, credentials,
|
||||||
amnezia::protocols::cloak::ckPublicKeyPath, &e);
|
amnezia::protocols::cloak::ckPublicKeyPath, &e);
|
||||||
cloakPublicKey.replace("\n", "");
|
cloakPublicKey.replace("\n", "");
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#include "configurator_base.h"
|
#include "configurator_base.h"
|
||||||
|
|
||||||
ConfiguratorBase::ConfiguratorBase(std::shared_ptr<Settings> settings, QObject *parent)
|
ConfiguratorBase::ConfiguratorBase(std::shared_ptr<Settings> settings,
|
||||||
: QObject{parent},
|
QObject *parent): QObject{parent}, m_settings(settings)
|
||||||
m_settings(settings)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "ikev2_configurator.h"
|
#include "ikev2_configurator.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
@ -15,10 +16,9 @@
|
||||||
#include "core/servercontroller.h"
|
#include "core/servercontroller.h"
|
||||||
|
|
||||||
|
|
||||||
Ikev2Configurator::Ikev2Configurator(std::shared_ptr<Settings> settings, QObject *parent):
|
Ikev2Configurator::Ikev2Configurator(std::shared_ptr<Settings> settings,
|
||||||
ConfiguratorBase(settings, parent)
|
QObject *parent): ConfiguratorBase(settings, parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials,
|
Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials,
|
||||||
|
|
@ -38,16 +38,13 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
|
||||||
"-k rsa -g 3072 -v 120 "\
|
"-k rsa -g 3072 -v 120 "\
|
||||||
"-d sql:/etc/ipsec.d -t \",,\" "\
|
"-d sql:/etc/ipsec.d -t \",,\" "\
|
||||||
"--keyUsage digitalSignature,keyEncipherment "\
|
"--keyUsage digitalSignature,keyEncipherment "\
|
||||||
"--extKeyUsage serverAuth,clientAuth -8 \"%1\"")
|
"--extKeyUsage serverAuth,clientAuth -8 \"%1\"").arg(connData.clientId);
|
||||||
.arg(connData.clientId);
|
|
||||||
|
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
ErrorCode e = serverController.runContainerScript(credentials, container, scriptCreateCert);
|
ErrorCode e = serverController.runContainerScript(credentials, container, scriptCreateCert);
|
||||||
|
|
||||||
QString scriptExportCert = QString("pk12util -W \"%1\" -d sql:/etc/ipsec.d -n \"%2\" -o \"%3\"")
|
QString scriptExportCert = QString("pk12util -W \"%1\" -d sql:/etc/ipsec.d -n \"%2\" -o \"%3\"")
|
||||||
.arg(connData.password)
|
.arg(connData.password, connData.clientId, certFileName);
|
||||||
.arg(connData.clientId)
|
|
||||||
.arg(certFileName);
|
|
||||||
e = serverController.runContainerScript(credentials, container, scriptExportCert);
|
e = serverController.runContainerScript(credentials, container, scriptExportCert);
|
||||||
|
|
||||||
connData.clientCert = serverController.getTextFileFromContainer(container, credentials, certFileName, &e);
|
connData.clientCert = serverController.getTextFileFromContainer(container, credentials, certFileName, &e);
|
||||||
|
|
@ -59,8 +56,8 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Ikev2Configurator::genIkev2Config(const ServerCredentials &credentials,
|
QString Ikev2Configurator::genIkev2Config(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
Q_UNUSED(containerConfig)
|
Q_UNUSED(containerConfig)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ public:
|
||||||
QString genMobileConfig(const ConnectionData &connData);
|
QString genMobileConfig(const ConnectionData &connData);
|
||||||
QString genStrongSwanConfig(const ConnectionData &connData);
|
QString genStrongSwanConfig(const ConnectionData &connData);
|
||||||
|
|
||||||
ConnectionData prepareIkev2Config(const ServerCredentials &credentials,
|
ConnectionData prepareIkev2Config(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, ErrorCode *errorCode = nullptr);
|
ErrorCode *errorCode = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IKEV2_CONFIGURATOR_H
|
#endif // IKEV2_CONFIGURATOR_H
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "openvpn_configurator.h"
|
#include "openvpn_configurator.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
@ -19,10 +20,9 @@
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> settings,
|
||||||
ConfiguratorBase(settings, parent)
|
QObject *parent): ConfiguratorBase(settings, parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials,
|
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials,
|
||||||
|
|
@ -36,9 +36,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString reqFileName = QString("%1/%2.req").
|
QString reqFileName = QString("%1/%2.req").arg(amnezia::protocols::openvpn::clientsDirPath, connData.clientId);
|
||||||
arg(amnezia::protocols::openvpn::clientsDirPath).
|
|
||||||
arg(connData.clientId);
|
|
||||||
|
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
ErrorCode e = serverController.uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
|
ErrorCode e = serverController.uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
|
||||||
|
|
@ -53,9 +51,11 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
||||||
return connData;
|
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,
|
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 (e) {
|
||||||
if (errorCode) *errorCode = e;
|
if (errorCode) *errorCode = e;
|
||||||
|
|
@ -71,8 +71,8 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials,
|
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
|
QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container),
|
||||||
|
|
@ -89,8 +89,7 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
|
||||||
|
|
||||||
if (config.contains("$OPENVPN_TA_KEY")) {
|
if (config.contains("$OPENVPN_TA_KEY")) {
|
||||||
config.replace("$OPENVPN_TA_KEY", connData.taKey);
|
config.replace("$OPENVPN_TA_KEY", connData.taKey);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
config.replace("<tls-auth>", "");
|
config.replace("<tls-auth>", "");
|
||||||
config.replace("</tls-auth>", "");
|
config.replace("</tls-auth>", "");
|
||||||
}
|
}
|
||||||
|
|
@ -112,8 +111,7 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig)
|
||||||
|
|
||||||
if (m_settings->routeMode() != Settings::VpnAllSites) {
|
if (m_settings->routeMode() != Settings::VpnAllSites) {
|
||||||
config.replace("redirect-gateway def1 bypass-dhcp", "");
|
config.replace("redirect-gateway def1 bypass-dhcp", "");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if(!config.contains("redirect-gateway def1 bypass-dhcp")) {
|
if(!config.contains("redirect-gateway def1 bypass-dhcp")) {
|
||||||
config.append("redirect-gateway def1 bypass-dhcp\n");
|
config.append("redirect-gateway def1 bypass-dhcp\n");
|
||||||
}
|
}
|
||||||
|
|
@ -151,23 +149,22 @@ QString OpenVpnConfigurator::processConfigWithExportSettings(QString jsonConfig)
|
||||||
return QJsonDocument(json).toJson();
|
return QJsonDocument(json).toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode OpenVpnConfigurator::signCert(DockerContainer container,
|
ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId)
|
||||||
const ServerCredentials &credentials, QString clientId)
|
|
||||||
{
|
{
|
||||||
QString script_import = QString("sudo docker exec -i %1 bash -c \"cd /opt/amnezia/openvpn && "
|
QString script_import = QString("sudo docker exec -i %1 bash -c \"cd /opt/amnezia/openvpn && "
|
||||||
"easyrsa import-req %2/%3.req %3\"")
|
"easyrsa import-req %2/%3.req %3\"")
|
||||||
.arg(ContainerProps::containerToString(container))
|
.arg(ContainerProps::containerToString(container),
|
||||||
.arg(amnezia::protocols::openvpn::clientsDirPath)
|
amnezia::protocols::openvpn::clientsDirPath,
|
||||||
.arg(clientId);
|
clientId);
|
||||||
|
|
||||||
QString script_sign = QString("sudo docker exec -i %1 bash -c \"export EASYRSA_BATCH=1; cd /opt/amnezia/openvpn && "
|
QString script_sign = QString("sudo docker exec -i %1 bash -c \"export EASYRSA_BATCH=1; cd /opt/amnezia/openvpn && "
|
||||||
"easyrsa sign-req client %2\"")
|
"easyrsa sign-req client %2\"")
|
||||||
.arg(ContainerProps::containerToString(container))
|
.arg(ContainerProps::containerToString(container), clientId);
|
||||||
.arg(clientId);
|
|
||||||
|
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
QStringList scriptList {script_import, script_sign};
|
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);
|
return serverController.runScript(credentials, script);
|
||||||
}
|
}
|
||||||
|
|
@ -230,8 +227,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
|
||||||
// save private key
|
// save private key
|
||||||
BIO * bp_private = BIO_new(BIO_s_mem());
|
BIO * bp_private = BIO_new(BIO_s_mem());
|
||||||
q_check_ptr(bp_private);
|
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");
|
qFatal("PEM_write_bio_PrivateKey");
|
||||||
EVP_PKEY_free(pKey);
|
EVP_PKEY_free(pKey);
|
||||||
BIO_free_all(bp_private);
|
BIO_free_all(bp_private);
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,13 @@ public:
|
||||||
QString processConfigWithLocalSettings(QString jsonConfig);
|
QString processConfigWithLocalSettings(QString jsonConfig);
|
||||||
QString processConfigWithExportSettings(QString jsonConfig);
|
QString processConfigWithExportSettings(QString jsonConfig);
|
||||||
|
|
||||||
ErrorCode signCert(DockerContainer container,
|
ErrorCode signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId);
|
||||||
const ServerCredentials &credentials, QString clientId);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConnectionData createCertRequest();
|
ConnectionData createCertRequest();
|
||||||
|
|
||||||
ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials,
|
ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, ErrorCode *errorCode = nullptr);
|
ErrorCode *errorCode = nullptr);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // OPENVPN_CONFIGURATOR_H
|
#endif // OPENVPN_CONFIGURATOR_H
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,16 @@
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
#include "containers/containers_defs.h"
|
#include "containers/containers_defs.h"
|
||||||
|
#include "core/scripts_registry.h"
|
||||||
#include "core/servercontroller.h"
|
#include "core/servercontroller.h"
|
||||||
|
|
||||||
ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr<Settings> settings,
|
||||||
ConfiguratorBase(settings, parent)
|
QObject *parent): ConfiguratorBase(settings, parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &credentials,
|
QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
ErrorCode e = ErrorCode::NoError;
|
ErrorCode e = ErrorCode::NoError;
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
|
|
@ -28,18 +28,12 @@ QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &c
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject config;
|
QString ssClientConfig = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::shadowsocks_client_template, container),
|
||||||
config.insert("server", credentials.hostName);
|
|
||||||
config.insert("server_port", "$SHADOWSOCKS_SERVER_PORT");
|
|
||||||
config.insert("local_port", "$SHADOWSOCKS_LOCAL_PORT");
|
|
||||||
config.insert("password", ssKey);
|
|
||||||
config.insert("timeout", 60);
|
|
||||||
config.insert("method", "$SHADOWSOCKS_CIPHER");
|
|
||||||
|
|
||||||
|
|
||||||
QString textCfg = serverController.replaceVars(QJsonDocument(config).toJson(),
|
|
||||||
serverController.genVarsForScript(credentials, container, containerConfig));
|
serverController.genVarsForScript(credentials, container, containerConfig));
|
||||||
|
|
||||||
|
ssClientConfig.replace("$SHADOWSOCKS_PASSWORD", ssKey);
|
||||||
|
ssClientConfig = serverController.replaceVars(ssClientConfig, serverController.genVarsForScript(credentials, container, containerConfig));
|
||||||
|
|
||||||
//qDebug().noquote() << textCfg;
|
//qDebug().noquote() << textCfg;
|
||||||
return textCfg;
|
return ssClientConfig;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "ssh_configurator.h"
|
#include "ssh_configurator.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
@ -14,11 +15,9 @@
|
||||||
#include "core/server_defs.h"
|
#include "core/server_defs.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
|
SshConfigurator::SshConfigurator(std::shared_ptr<Settings> settings,
|
||||||
SshConfigurator::SshConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
QObject *parent): ConfiguratorBase(settings, parent)
|
||||||
ConfiguratorBase(settings, parent)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SshConfigurator::convertOpenSShKey(const QString &key)
|
QString SshConfigurator::convertOpenSShKey(const QString &key)
|
||||||
|
|
@ -73,10 +72,8 @@ void SshConfigurator::openSshTerminal(const ServerCredentials &credentials)
|
||||||
// todo: connect by key
|
// todo: connect by key
|
||||||
// p->setNativeArguments(QString("%1@%2")
|
// p->setNativeArguments(QString("%1@%2")
|
||||||
// .arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
// .arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
||||||
}
|
} else {
|
||||||
else {
|
p->setNativeArguments(QString("%1@%2 -pw %3").arg(credentials.userName).arg(credentials.hostName, credentials.password));
|
||||||
p->setNativeArguments(QString("%1@%2 -pw %3")
|
|
||||||
.arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
p->setProgram("/bin/bash");
|
p->setProgram("/bin/bash");
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ public:
|
||||||
QProcessEnvironment prepareEnv();
|
QProcessEnvironment prepareEnv();
|
||||||
QString convertOpenSShKey(const QString &key);
|
QString convertOpenSShKey(const QString &key);
|
||||||
void openSshTerminal(const ServerCredentials &credentials);
|
void openSshTerminal(const ServerCredentials &credentials);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SSH_CONFIGURATOR_H
|
#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 "wireguard_configurator.h"
|
||||||
#include "ikev2_configurator.h"
|
#include "ikev2_configurator.h"
|
||||||
#include "ssh_configurator.h"
|
#include "ssh_configurator.h"
|
||||||
|
#include "v2ray_configurator.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
@ -14,8 +15,8 @@
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings,
|
||||||
ConfiguratorBase(settings, parent)
|
QObject *parent) : ConfiguratorBase(settings, parent)
|
||||||
{
|
{
|
||||||
openVpnConfigurator = std::shared_ptr<OpenVpnConfigurator>(new OpenVpnConfigurator(settings, this));
|
openVpnConfigurator = std::shared_ptr<OpenVpnConfigurator>(new OpenVpnConfigurator(settings, this));
|
||||||
shadowSocksConfigurator = std::shared_ptr<ShadowSocksConfigurator>(new ShadowSocksConfigurator(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));
|
sshConfigurator = std::shared_ptr<SshConfigurator>(new SshConfigurator(settings, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials,
|
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
switch (proto) {
|
switch (proto) {
|
||||||
case Proto::OpenVpn:
|
case Proto::OpenVpn:
|
||||||
return openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, errorCode);
|
return openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, errorCode);
|
||||||
|
|
||||||
case Proto::ShadowSocks:
|
case Proto::ShadowSocks:
|
||||||
return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode);
|
return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode);
|
||||||
|
|
||||||
case Proto::Cloak:
|
case Proto::Cloak:
|
||||||
return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
|
return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
|
||||||
|
|
||||||
case Proto::WireGuard:
|
case Proto::WireGuard:
|
||||||
return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, errorCode);
|
return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, errorCode);
|
||||||
|
|
||||||
case Proto::Ikev2:
|
case Proto::Ikev2:
|
||||||
return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
|
return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
|
||||||
|
case Proto::V2Ray:
|
||||||
|
return v2RayConfigurator->genV2RayConfig(credentials, container, containerConfig, errorCode);
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
@ -62,8 +60,7 @@ QPair<QString, QString> VpnConfigurator::getDnsForConfig(int serverIndex)
|
||||||
if (dns.first.isEmpty() || !Utils::checkIPv4Format(dns.first)) {
|
if (dns.first.isEmpty() || !Utils::checkIPv4Format(dns.first)) {
|
||||||
if (useAmneziaDns && m_settings->containers(serverIndex).contains(DockerContainer::Dns)) {
|
if (useAmneziaDns && m_settings->containers(serverIndex).contains(DockerContainer::Dns)) {
|
||||||
dns.first = protocols::dns::amneziaDnsIp;
|
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)) {
|
if (dns.second.isEmpty() || !Utils::checkIPv4Format(dns.second)) {
|
||||||
dns.second = m_settings->secondaryDns();
|
dns.second = m_settings->secondaryDns();
|
||||||
|
|
@ -73,8 +70,7 @@ QPair<QString, QString> VpnConfigurator::getDnsForConfig(int serverIndex)
|
||||||
return dns;
|
return dns;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container,
|
QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config)
|
||||||
Proto proto, QString &config)
|
|
||||||
{
|
{
|
||||||
auto dns = getDnsForConfig(serverIndex);
|
auto dns = getDnsForConfig(serverIndex);
|
||||||
|
|
||||||
|
|
@ -84,8 +80,7 @@ QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerCo
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container,
|
QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto, QString &config)
|
||||||
Proto proto, QString &config)
|
|
||||||
{
|
{
|
||||||
processConfigWithDnsSettings(serverIndex, container, proto, config);
|
processConfigWithDnsSettings(serverIndex, container, proto, config);
|
||||||
|
|
||||||
|
|
@ -95,8 +90,7 @@ QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, Docker
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container,
|
QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config)
|
||||||
Proto proto, QString &config)
|
|
||||||
{
|
{
|
||||||
processConfigWithDnsSettings(serverIndex, container, proto, config);
|
processConfigWithDnsSettings(serverIndex, container, proto, config);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ class CloakConfigurator;
|
||||||
class WireguardConfigurator;
|
class WireguardConfigurator;
|
||||||
class Ikev2Configurator;
|
class Ikev2Configurator;
|
||||||
class SshConfigurator;
|
class SshConfigurator;
|
||||||
|
class V2RayConfigurator;
|
||||||
|
|
||||||
// Retrieve connection settings from server
|
// Retrieve connection settings from server
|
||||||
class VpnConfigurator : ConfiguratorBase
|
class VpnConfigurator : ConfiguratorBase
|
||||||
|
|
@ -31,8 +32,7 @@ public:
|
||||||
QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
|
QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
|
||||||
|
|
||||||
// workaround for containers which is not support normal configaration
|
// workaround for containers which is not support normal configaration
|
||||||
void updateContainerConfigAfterInstallation(DockerContainer container,
|
void updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig, const QString &stdOut);
|
||||||
QJsonObject &containerConfig, const QString &stdOut);
|
|
||||||
|
|
||||||
std::shared_ptr<OpenVpnConfigurator> openVpnConfigurator;
|
std::shared_ptr<OpenVpnConfigurator> openVpnConfigurator;
|
||||||
std::shared_ptr<ShadowSocksConfigurator> shadowSocksConfigurator;
|
std::shared_ptr<ShadowSocksConfigurator> shadowSocksConfigurator;
|
||||||
|
|
@ -40,6 +40,7 @@ public:
|
||||||
std::shared_ptr<WireguardConfigurator> wireguardConfigurator;
|
std::shared_ptr<WireguardConfigurator> wireguardConfigurator;
|
||||||
std::shared_ptr<Ikev2Configurator> ikev2Configurator;
|
std::shared_ptr<Ikev2Configurator> ikev2Configurator;
|
||||||
std::shared_ptr<SshConfigurator> sshConfigurator;
|
std::shared_ptr<SshConfigurator> sshConfigurator;
|
||||||
|
std::shared_ptr<V2RayConfigurator> v2RayConfigurator;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VPN_CONFIGURATOR_H
|
#endif // VPN_CONFIGURATOR_H
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,11 @@
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
|
|
||||||
#include "containers/containers_defs.h"
|
#include "containers/containers_defs.h"
|
||||||
#include "core/server_defs.h"
|
#include "core/server_defs.h"
|
||||||
#include "core/scripts_registry.h"
|
#include "core/scripts_registry.h"
|
||||||
|
|
@ -21,10 +19,9 @@
|
||||||
#include "core/servercontroller.h"
|
#include "core/servercontroller.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
WireguardConfigurator::WireguardConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
WireguardConfigurator::WireguardConfigurator(std::shared_ptr<Settings> settings,
|
||||||
ConfiguratorBase(settings, parent)
|
QObject *parent): ConfiguratorBase(settings, parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
||||||
|
|
@ -59,7 +56,9 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials,
|
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();
|
WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys();
|
||||||
connData.host = credentials.hostName;
|
connData.host = credentials.hostName;
|
||||||
|
|
@ -95,8 +94,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
||||||
// Calc next IP address
|
// Calc next IP address
|
||||||
if (ips.isEmpty()) {
|
if (ips.isEmpty()) {
|
||||||
nextIpNumber = "2";
|
nextIpNumber = "2";
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
int next = ips.last().split(".").last().toInt() + 1;
|
int next = ips.last().split(".").last().toInt() + 1;
|
||||||
if (next > 254) {
|
if (next > 254) {
|
||||||
if (errorCode) *errorCode = ErrorCode::AddressPoolError;
|
if (errorCode) *errorCode = ErrorCode::AddressPoolError;
|
||||||
|
|
@ -120,14 +118,16 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get keys
|
// 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", "");
|
connData.serverPubKey.replace("\n", "");
|
||||||
if (e) {
|
if (e) {
|
||||||
if (errorCode) *errorCode = e;
|
if (errorCode) *errorCode = e;
|
||||||
return connData;
|
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", "");
|
connData.pskKey.replace("\n", "");
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
|
|
@ -136,32 +136,29 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add client to config
|
// Add client to config
|
||||||
QString configPart = QString(
|
QString configPart = QString("[Peer]\n"
|
||||||
"[Peer]\n"
|
|
||||||
"PublicKey = %1\n"
|
"PublicKey = %1\n"
|
||||||
"PresharedKey = %2\n"
|
"PresharedKey = %2\n"
|
||||||
"AllowedIPs = %3/32\n\n").
|
"AllowedIPs = %3/32\n\n").arg(connData.clientPubKey, connData.pskKey, connData.clientIP);
|
||||||
arg(connData.clientPubKey).
|
|
||||||
arg(connData.pskKey).
|
|
||||||
arg(connData.clientIP);
|
|
||||||
|
|
||||||
e = serverController.uploadTextFileToContainer(container, credentials, configPart,
|
e = serverController.uploadTextFileToContainer(container, credentials, configPart,
|
||||||
protocols::wireguard::serverConfigPath, libssh::SftpOverwriteMode::SftpAppendToExisting);
|
protocols::wireguard::serverConfigPath,
|
||||||
|
libssh::SftpOverwriteMode::SftpAppendToExisting);
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
if (errorCode) *errorCode = e;
|
if (errorCode) *errorCode = e;
|
||||||
return connData;
|
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,
|
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.replaceVars(script, serverController.genVarsForScript(credentials, container)));
|
||||||
serverController.genVarsForScript(credentials, container)));
|
|
||||||
|
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials,
|
QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container),
|
QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container),
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,9 @@ public:
|
||||||
QString processConfigWithLocalSettings(QString config);
|
QString processConfigWithLocalSettings(QString config);
|
||||||
QString processConfigWithExportSettings(QString config);
|
QString processConfigWithExportSettings(QString config);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConnectionData prepareWireguardConfig(const ServerCredentials &credentials,
|
ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||||
|
|
||||||
ConnectionData genClientKeys();
|
ConnectionData genClientKeys();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,9 @@ QVector<amnezia::Proto> ContainerProps::protocolsForContainer(amnezia::DockerCon
|
||||||
case DockerContainer::Ipsec:
|
case DockerContainer::Ipsec:
|
||||||
return { Proto::Ikev2 /*, Protocol::L2tp */};
|
return { Proto::Ikev2 /*, Protocol::L2tp */};
|
||||||
|
|
||||||
|
case DockerContainer::V2Ray:
|
||||||
|
return { Proto::OpenVpn, Proto::V2Ray };
|
||||||
|
|
||||||
case DockerContainer::Dns:
|
case DockerContainer::Dns:
|
||||||
return { };
|
return { };
|
||||||
|
|
||||||
|
|
@ -86,6 +89,7 @@ QMap<DockerContainer, QString> ContainerProps::containerHumanNames()
|
||||||
{DockerContainer::Cloak, "OpenVpn over Cloak"},
|
{DockerContainer::Cloak, "OpenVpn over Cloak"},
|
||||||
{DockerContainer::WireGuard, "WireGuard"},
|
{DockerContainer::WireGuard, "WireGuard"},
|
||||||
{DockerContainer::Ipsec, QObject::tr("IPsec")},
|
{DockerContainer::Ipsec, QObject::tr("IPsec")},
|
||||||
|
{DockerContainer::V2Ray, "V2Ray"},
|
||||||
|
|
||||||
{DockerContainer::TorWebSite, QObject::tr("Web site in Tor network")},
|
{DockerContainer::TorWebSite, QObject::tr("Web site in Tor network")},
|
||||||
{DockerContainer::Dns, QObject::tr("DNS Service")},
|
{DockerContainer::Dns, QObject::tr("DNS Service")},
|
||||||
|
|
@ -103,6 +107,7 @@ QMap<DockerContainer, QString> ContainerProps::containerDescriptions()
|
||||||
"configured with traffic masking by Cloak plugin")},
|
"configured with traffic masking by Cloak plugin")},
|
||||||
{DockerContainer::WireGuard, QObject::tr("WireGuard container")},
|
{DockerContainer::WireGuard, QObject::tr("WireGuard container")},
|
||||||
{DockerContainer::Ipsec, QObject::tr("IPsec container")},
|
{DockerContainer::Ipsec, QObject::tr("IPsec container")},
|
||||||
|
{DockerContainer::V2Ray, QObject::tr("V2Ray container")},
|
||||||
|
|
||||||
{DockerContainer::TorWebSite, QObject::tr("Web site in Tor network")},
|
{DockerContainer::TorWebSite, QObject::tr("Web site in Tor network")},
|
||||||
{DockerContainer::Dns, QObject::tr("DNS Service")},
|
{DockerContainer::Dns, QObject::tr("DNS Service")},
|
||||||
|
|
@ -120,6 +125,8 @@ amnezia::ServiceType ContainerProps::containerService(DockerContainer c)
|
||||||
case DockerContainer::ShadowSocks : return ServiceType::Vpn;
|
case DockerContainer::ShadowSocks : return ServiceType::Vpn;
|
||||||
case DockerContainer::WireGuard : return ServiceType::Vpn;
|
case DockerContainer::WireGuard : return ServiceType::Vpn;
|
||||||
case DockerContainer::Ipsec : return ServiceType::Vpn;
|
case DockerContainer::Ipsec : return ServiceType::Vpn;
|
||||||
|
case DockerContainer::V2Ray : return ServiceType::Vpn;
|
||||||
|
|
||||||
case DockerContainer::TorWebSite : return ServiceType::Other;
|
case DockerContainer::TorWebSite : return ServiceType::Other;
|
||||||
case DockerContainer::Dns : return ServiceType::Other;
|
case DockerContainer::Dns : return ServiceType::Other;
|
||||||
//case DockerContainer::FileShare : 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::ShadowSocks : return Proto::ShadowSocks;
|
||||||
case DockerContainer::WireGuard : return Proto::WireGuard;
|
case DockerContainer::WireGuard : return Proto::WireGuard;
|
||||||
case DockerContainer::Ipsec : return Proto::Ikev2;
|
case DockerContainer::Ipsec : return Proto::Ikev2;
|
||||||
|
case DockerContainer::V2Ray : return Proto::V2Ray;
|
||||||
|
|
||||||
case DockerContainer::TorWebSite : return Proto::TorWebSite;
|
case DockerContainer::TorWebSite : return Proto::TorWebSite;
|
||||||
case DockerContainer::Dns : return Proto::Dns;
|
case DockerContainer::Dns : return Proto::Dns;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ enum DockerContainer {
|
||||||
Cloak,
|
Cloak,
|
||||||
WireGuard,
|
WireGuard,
|
||||||
Ipsec,
|
Ipsec,
|
||||||
|
V2Ray,
|
||||||
|
|
||||||
//non-vpn
|
//non-vpn
|
||||||
TorWebSite,
|
TorWebSite,
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ enum ErrorCode
|
||||||
ShadowSocksExecutableMissing,
|
ShadowSocksExecutableMissing,
|
||||||
CloakExecutableMissing,
|
CloakExecutableMissing,
|
||||||
AmneziaServiceConnectionFailed,
|
AmneziaServiceConnectionFailed,
|
||||||
|
V2RayExecutableMissing,
|
||||||
ExecutableMissing,
|
ExecutableMissing,
|
||||||
|
|
||||||
// VPN errors
|
// VPN errors
|
||||||
|
|
@ -67,7 +68,9 @@ enum ErrorCode
|
||||||
OpenSslFailed,
|
OpenSslFailed,
|
||||||
OpenVpnExecutableCrashed,
|
OpenVpnExecutableCrashed,
|
||||||
ShadowSocksExecutableCrashed,
|
ShadowSocksExecutableCrashed,
|
||||||
CloakExecutableCrashed
|
CloakExecutableCrashed,
|
||||||
|
V2RayExecutableCrashed,
|
||||||
|
V2RayKeyMissing
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace amnezia
|
} // namespace amnezia
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ QString errorString(ErrorCode code){
|
||||||
case (AmneziaServiceConnectionFailed): return QObject::tr("Amnezia helper service error");
|
case (AmneziaServiceConnectionFailed): return QObject::tr("Amnezia helper service error");
|
||||||
case (OpenSslFailed): return QObject::tr("OpenSSL failed");
|
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
|
// VPN errors
|
||||||
case (OpenVpnAdaptersInUseError): return QObject::tr("Can't connect: another VPN connection is active");
|
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");
|
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::ShadowSocks: return QLatin1String("openvpn_shadowsocks");
|
||||||
case DockerContainer::WireGuard: return QLatin1String("wireguard");
|
case DockerContainer::WireGuard: return QLatin1String("wireguard");
|
||||||
case DockerContainer::Ipsec: return QLatin1String("ipsec");
|
case DockerContainer::Ipsec: return QLatin1String("ipsec");
|
||||||
|
case DockerContainer::V2Ray: return QLatin1String("openvpn_v2ray_vmess");
|
||||||
|
|
||||||
case DockerContainer::TorWebSite: return QLatin1String("website_tor");
|
case DockerContainer::TorWebSite: return QLatin1String("website_tor");
|
||||||
case DockerContainer::Dns: return QLatin1String("dns");
|
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::container_startup: return QLatin1String("start.sh");
|
||||||
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
|
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
|
||||||
case ProtocolScriptType::wireguard_template: return QLatin1String("template.conf");
|
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,
|
configure_container,
|
||||||
container_startup,
|
container_startup,
|
||||||
openvpn_template,
|
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 &ssConfig = config.value(ProtocolProps::protoToString(Proto::ShadowSocks)).toObject();
|
||||||
const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject();
|
const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject();
|
||||||
const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject();
|
const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject();
|
||||||
|
const QJsonObject &v2RayConfig = config.value(ProtocolProps::protoToString(Proto::V2Ray)).toObject();
|
||||||
//
|
//
|
||||||
|
|
||||||
Vars vars;
|
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) }});
|
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
|
// IPsec vars
|
||||||
vars.append({{"$IPSEC_VPN_L2TP_NET", "192.168.42.0/24"}});
|
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"}});
|
vars.append({{"$IPSEC_VPN_L2TP_POOL", "192.168.42.10-192.168.42.250"}});
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,7 @@ ErrorCode OpenVpnOverCloakProtocol::start()
|
||||||
args << "-u";
|
args << "-u";
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug().noquote() << "OpenVpnOverCloakProtocol::start()"
|
qDebug().noquote() << "OpenVpnOverCloakProtocol::start()" << cloakExecPath() << args.join(" ");
|
||||||
<< cloakExecPath() << args.join(" ");
|
|
||||||
|
|
||||||
m_ckProcess.setProcessChannelMode(QProcess::MergedChannels);
|
m_ckProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
|
||||||
|
|
@ -84,8 +83,9 @@ ErrorCode OpenVpnOverCloakProtocol::start()
|
||||||
setConnectionState(VpnConnectionState::Connecting);
|
setConnectionState(VpnConnectionState::Connecting);
|
||||||
|
|
||||||
return OpenVpnProtocol::start();
|
return OpenVpnProtocol::start();
|
||||||
|
} else {
|
||||||
|
return ErrorCode::CloakExecutableMissing;
|
||||||
}
|
}
|
||||||
else return ErrorCode::CloakExecutableMissing;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ QMap<amnezia::Proto, QString> ProtocolProps::protocolHumanNames()
|
||||||
{Proto::WireGuard, "WireGuard"},
|
{Proto::WireGuard, "WireGuard"},
|
||||||
{Proto::Ikev2, "IKEv2"},
|
{Proto::Ikev2, "IKEv2"},
|
||||||
{Proto::L2tp, "L2TP"},
|
{Proto::L2tp, "L2TP"},
|
||||||
|
{Proto::V2Ray, "V2Ray"},
|
||||||
|
|
||||||
{Proto::TorWebSite, "Web site in Tor network"},
|
{Proto::TorWebSite, "Web site in Tor network"},
|
||||||
{Proto::Dns, "DNS Service"},
|
{Proto::Dns, "DNS Service"},
|
||||||
|
|
@ -96,6 +97,8 @@ amnezia::ServiceType ProtocolProps::protocolService(Proto p)
|
||||||
case Proto::Cloak : return ServiceType::Vpn;
|
case Proto::Cloak : return ServiceType::Vpn;
|
||||||
case Proto::ShadowSocks : return ServiceType::Vpn;
|
case Proto::ShadowSocks : return ServiceType::Vpn;
|
||||||
case Proto::WireGuard : return ServiceType::Vpn;
|
case Proto::WireGuard : return ServiceType::Vpn;
|
||||||
|
case Proto::V2Ray : return ServiceType::Vpn;
|
||||||
|
|
||||||
case Proto::TorWebSite : return ServiceType::Other;
|
case Proto::TorWebSite : return ServiceType::Other;
|
||||||
case Proto::Dns : return ServiceType::Other;
|
case Proto::Dns : return ServiceType::Other;
|
||||||
case Proto::FileShare : return ServiceType::Other;
|
case Proto::FileShare : return ServiceType::Other;
|
||||||
|
|
@ -113,6 +116,7 @@ int ProtocolProps::defaultPort(Proto p)
|
||||||
case Proto::WireGuard : return 51820;
|
case Proto::WireGuard : return 51820;
|
||||||
case Proto::Ikev2 : return -1;
|
case Proto::Ikev2 : return -1;
|
||||||
case Proto::L2tp : return -1;
|
case Proto::L2tp : return -1;
|
||||||
|
case Proto::V2Ray : return 10086;
|
||||||
|
|
||||||
case Proto::TorWebSite : return -1;
|
case Proto::TorWebSite : return -1;
|
||||||
case Proto::Dns : return 53;
|
case Proto::Dns : return 53;
|
||||||
|
|
@ -132,6 +136,7 @@ bool ProtocolProps::defaultPortChangeable(Proto p)
|
||||||
case Proto::WireGuard : return true;
|
case Proto::WireGuard : return true;
|
||||||
case Proto::Ikev2 : return false;
|
case Proto::Ikev2 : return false;
|
||||||
case Proto::L2tp : return false;
|
case Proto::L2tp : return false;
|
||||||
|
case Proto::V2Ray : return true;
|
||||||
|
|
||||||
|
|
||||||
case Proto::TorWebSite : return true;
|
case Proto::TorWebSite : return true;
|
||||||
|
|
@ -151,6 +156,7 @@ TransportProto ProtocolProps::defaultTransportProto(Proto p)
|
||||||
case Proto::WireGuard : return TransportProto::Udp;
|
case Proto::WireGuard : return TransportProto::Udp;
|
||||||
case Proto::Ikev2 : return TransportProto::Udp;
|
case Proto::Ikev2 : return TransportProto::Udp;
|
||||||
case Proto::L2tp : return TransportProto::Udp;
|
case Proto::L2tp : return TransportProto::Udp;
|
||||||
|
case Proto::V2Ray : return TransportProto::Tcp;
|
||||||
// non-vpn
|
// non-vpn
|
||||||
case Proto::TorWebSite : return TransportProto::Tcp;
|
case Proto::TorWebSite : return TransportProto::Tcp;
|
||||||
case Proto::Dns : return TransportProto::Udp;
|
case Proto::Dns : return TransportProto::Udp;
|
||||||
|
|
@ -169,6 +175,7 @@ bool ProtocolProps::defaultTransportProtoChangeable(Proto p)
|
||||||
case Proto::WireGuard : return false;
|
case Proto::WireGuard : return false;
|
||||||
case Proto::Ikev2 : return false;
|
case Proto::Ikev2 : return false;
|
||||||
case Proto::L2tp : return false;
|
case Proto::L2tp : return false;
|
||||||
|
case Proto::V2Ray : return false;
|
||||||
// non-vpn
|
// non-vpn
|
||||||
case Proto::TorWebSite : return false;
|
case Proto::TorWebSite : return false;
|
||||||
case Proto::Dns : return false;
|
case Proto::Dns : 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 {
|
namespace sftp {
|
||||||
constexpr char defaultUserName[] = "sftp_user";
|
constexpr char defaultUserName[] = "sftp_user";
|
||||||
|
|
||||||
|
|
@ -148,6 +154,7 @@ enum Proto {
|
||||||
WireGuard,
|
WireGuard,
|
||||||
Ikev2,
|
Ikev2,
|
||||||
L2tp,
|
L2tp,
|
||||||
|
V2Ray,
|
||||||
|
|
||||||
// non-vpn
|
// non-vpn
|
||||||
TorWebSite,
|
TorWebSite,
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
||||||
return lastError();
|
return lastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef Q_OS_IOS
|
#ifndef Q_OS_IOS
|
||||||
if (Utils::processIsRunning(Utils::executable("ss-local", false))) {
|
if (Utils::processIsRunning(Utils::executable("ss-local", false))) {
|
||||||
Utils::killProcessByName(Utils::executable("ss-local", false));
|
Utils::killProcessByName(Utils::executable("ss-local", false));
|
||||||
|
|
@ -48,12 +47,10 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
QStringList args = QStringList() << "-c" << m_shadowSocksCfgFile.fileName();
|
QStringList args = QStringList() << "-c" << m_shadowSocksCfgFile.fileName();
|
||||||
#else
|
#else
|
||||||
QStringList args = QStringList() << "-c" << m_shadowSocksCfgFile.fileName()
|
QStringList args = QStringList() << "-c" << m_shadowSocksCfgFile.fileName() << "--no-delay";
|
||||||
<< "--no-delay";
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qDebug().noquote() << "ShadowSocksVpnProtocol::start()"
|
qDebug().noquote() << "ShadowSocksVpnProtocol::start()" << shadowSocksExecPath() << args.join(" ");
|
||||||
<< shadowSocksExecPath() << args.join(" ");
|
|
||||||
|
|
||||||
m_ssProcess.setProcessChannelMode(QProcess::MergedChannels);
|
m_ssProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
|
||||||
|
|
@ -84,8 +81,9 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
||||||
setConnectionState(VpnConnectionState::Connecting);
|
setConnectionState(VpnConnectionState::Connecting);
|
||||||
|
|
||||||
return OpenVpnProtocol::start();
|
return OpenVpnProtocol::start();
|
||||||
|
} else {
|
||||||
|
return ErrorCode::ShadowSocksExecutableMissing;
|
||||||
}
|
}
|
||||||
else return ErrorCode::ShadowSocksExecutableMissing;
|
|
||||||
#else
|
#else
|
||||||
return ErrorCode::NotImplementedError;
|
return ErrorCode::NotImplementedError;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -116,17 +114,5 @@ QString ShadowSocksVpnProtocol::shadowSocksExecPath()
|
||||||
|
|
||||||
void ShadowSocksVpnProtocol::readShadowSocksConfiguration(const QJsonObject &configuration)
|
void ShadowSocksVpnProtocol::readShadowSocksConfiguration(const QJsonObject &configuration)
|
||||||
{
|
{
|
||||||
QJsonObject shadowSocksConfig = configuration.value(ProtocolProps::key_proto_config_data(Proto::ShadowSocks)).toObject();
|
m_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;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef SHADOWSOCKSVPNPROTOCOL_H
|
#ifndef SHADOWSOCKSVPNPROTOCOL_H
|
||||||
#define SHADOWSOCKSVPNPROTOCOL_H
|
#define SHADOWSOCKSVPNPROTOCOL_H
|
||||||
|
|
||||||
#include "openvpnprotocol.h"
|
|
||||||
#include "QProcess"
|
#include "QProcess"
|
||||||
#include "containers/containers_defs.h"
|
|
||||||
|
#include "openvpnprotocol.h"
|
||||||
|
|
||||||
class ShadowSocksVpnProtocol : public OpenVpnProtocol
|
class ShadowSocksVpnProtocol : public OpenVpnProtocol
|
||||||
{
|
{
|
||||||
|
|
@ -14,20 +14,18 @@ public:
|
||||||
ErrorCode start() override;
|
ErrorCode start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
protected:
|
|
||||||
void readShadowSocksConfiguration(const QJsonObject &configuration);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QJsonObject m_shadowSocksConfig;
|
QJsonObject m_shadowSocksConfig;
|
||||||
|
|
||||||
private:
|
void readShadowSocksConfiguration(const QJsonObject &configuration);
|
||||||
static QString shadowSocksExecPath();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifndef Q_OS_IOS
|
#ifndef Q_OS_IOS
|
||||||
QProcess m_ssProcess;
|
QProcess m_ssProcess;
|
||||||
#endif
|
#endif
|
||||||
QTemporaryFile m_shadowSocksCfgFile;
|
QTemporaryFile m_shadowSocksCfgFile;
|
||||||
|
|
||||||
|
static QString shadowSocksExecPath();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHADOWSOCKSVPNPROTOCOL_H
|
#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 "shadowsocksvpnprotocol.h"
|
||||||
#include "openvpnovercloakprotocol.h"
|
#include "openvpnovercloakprotocol.h"
|
||||||
#include "wireguardprotocol.h"
|
#include "wireguardprotocol.h"
|
||||||
|
#include "v2rayprotocol.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
|
|
@ -114,6 +115,7 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject&
|
||||||
case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration);
|
case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration);
|
||||||
case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration);
|
case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration);
|
||||||
case DockerContainer::WireGuard: return new WireguardProtocol(configuration);
|
case DockerContainer::WireGuard: return new WireguardProtocol(configuration);
|
||||||
|
case DockerContainer::V2Ray: return new V2RayProtocol(configuration);
|
||||||
#endif
|
#endif
|
||||||
default: return nullptr;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,5 +166,13 @@
|
||||||
<file>ui/qml/Pages/PageAdvancedServerSettings.qml</file>
|
<file>ui/qml/Pages/PageAdvancedServerSettings.qml</file>
|
||||||
<file>ui/qml/Controls/PopupWarning.qml</file>
|
<file>ui/qml/Controls/PopupWarning.qml</file>
|
||||||
<file>ui/qml/Controls/PopupWithTextField.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>
|
</qresource>
|
||||||
</RCC>
|
</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 ShadowSocksLogic;
|
||||||
friend class CloakLogic;
|
friend class CloakLogic;
|
||||||
friend class UiLogic;
|
friend class UiLogic;
|
||||||
|
friend class V2RayLogic;
|
||||||
|
|
||||||
void onUpdatePage() override;
|
void onUpdatePage() override;
|
||||||
ErrorCode doInstallAction(const std::function<ErrorCode()> &action);
|
ErrorCode doInstallAction(const std::function<ErrorCode()> &action);
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ QJsonObject ShadowSocksLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
|
||||||
void ShadowSocksLogic::onPushButtonSaveClicked()
|
void ShadowSocksLogic::onPushButtonSaveClicked()
|
||||||
{
|
{
|
||||||
QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer, Proto::ShadowSocks);
|
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 containerConfig = m_settings->containerConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer);
|
||||||
QJsonObject newContainerConfig = containerConfig;
|
QJsonObject newContainerConfig = containerConfig;
|
||||||
|
|
|
||||||
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/ShadowSocksLogic.h"
|
||||||
#include "pages_logic/protocols/OtherProtocolsLogic.h"
|
#include "pages_logic/protocols/OtherProtocolsLogic.h"
|
||||||
#include "pages_logic/protocols/WireGuardLogic.h"
|
#include "pages_logic/protocols/WireGuardLogic.h"
|
||||||
|
#include "pages_logic/protocols/V2RayLogic.h"
|
||||||
|
|
||||||
using namespace amnezia;
|
using namespace amnezia;
|
||||||
using namespace PageEnumNS;
|
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::ShadowSocks, new ShadowSocksLogic(this));
|
||||||
m_protocolLogicMap.insert(Proto::Cloak, new CloakLogic(this));
|
m_protocolLogicMap.insert(Proto::Cloak, new CloakLogic(this));
|
||||||
m_protocolLogicMap.insert(Proto::WireGuard, new WireGuardLogic(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::Dns, new OtherProtocolsLogic(this));
|
||||||
m_protocolLogicMap.insert(Proto::Sftp, new OtherProtocolsLogic(this));
|
m_protocolLogicMap.insert(Proto::Sftp, new OtherProtocolsLogic(this));
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ class PageProtocolLogicBase;
|
||||||
class OpenVpnLogic;
|
class OpenVpnLogic;
|
||||||
class ShadowSocksLogic;
|
class ShadowSocksLogic;
|
||||||
class CloakLogic;
|
class CloakLogic;
|
||||||
|
class V2RayLogic;
|
||||||
|
|
||||||
class OtherProtocolsLogic;
|
class OtherProtocolsLogic;
|
||||||
|
|
||||||
|
|
@ -94,6 +95,7 @@ public:
|
||||||
friend class OpenVpnLogic;
|
friend class OpenVpnLogic;
|
||||||
friend class ShadowSocksLogic;
|
friend class ShadowSocksLogic;
|
||||||
friend class CloakLogic;
|
friend class CloakLogic;
|
||||||
|
friend class V2RayLogic;
|
||||||
|
|
||||||
friend class OtherProtocolsLogic;
|
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