Wireguard protocol + refactoring
This commit is contained in:
parent
8bdfe1741a
commit
2f6fb0d557
41 changed files with 1245 additions and 152 deletions
|
@ -15,7 +15,9 @@ HEADERS += \
|
|||
../ipc/ipc.h \
|
||||
configurators/cloak_configurator.h \
|
||||
configurators/shadowsocks_configurator.h \
|
||||
configurators/ssh_configurator.h \
|
||||
configurators/vpn_configurator.h \
|
||||
configurators/wireguard_configurator.h \
|
||||
core/defs.h \
|
||||
core/errorstrings.h \
|
||||
core/ipcclient.h \
|
||||
|
@ -29,6 +31,7 @@ HEADERS += \
|
|||
protocols/openvpnovercloakprotocol.h \
|
||||
protocols/protocols_defs.h \
|
||||
protocols/shadowsocksvpnprotocol.h \
|
||||
protocols/wireguardprotocol.h \
|
||||
settings.h \
|
||||
ui/Controls/SlidingStackedWidget.h \
|
||||
ui/mainwindow.h \
|
||||
|
@ -43,7 +46,9 @@ HEADERS += \
|
|||
SOURCES += \
|
||||
configurators/cloak_configurator.cpp \
|
||||
configurators/shadowsocks_configurator.cpp \
|
||||
configurators/ssh_configurator.cpp \
|
||||
configurators/vpn_configurator.cpp \
|
||||
configurators/wireguard_configurator.cpp \
|
||||
core/errorstrings.cpp \
|
||||
core/ipcclient.cpp \
|
||||
configurators/openvpn_configurator.cpp \
|
||||
|
@ -56,6 +61,7 @@ SOURCES += \
|
|||
protocols/openvpnovercloakprotocol.cpp \
|
||||
protocols/protocols_defs.cpp \
|
||||
protocols/shadowsocksvpnprotocol.cpp \
|
||||
protocols/wireguardprotocol.cpp \
|
||||
settings.cpp \
|
||||
ui/Controls/SlidingStackedWidget.cpp \
|
||||
ui/mainwindow.cpp \
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
#include <QTemporaryDir>
|
||||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
#include <utils.h>
|
||||
|
||||
#include "core/server_defs.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
#include "core/scripts_registry.h"
|
||||
#include "utils.h"
|
||||
|
||||
QString OpenVpnConfigurator::getEasyRsaShPath()
|
||||
{
|
||||
|
@ -227,7 +227,7 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString config)
|
|||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
if (m_settings().routeMode() == Settings::VpnOnlyForwardSites) {
|
||||
if (m_settings().routeMode() != Settings::VpnAllSites) {
|
||||
config.replace("redirect-gateway def1 bypass-dhcp", "");
|
||||
}
|
||||
else {
|
||||
|
@ -266,40 +266,6 @@ QString OpenVpnConfigurator::processConfigWithExportSettings(QString config)
|
|||
return config;
|
||||
}
|
||||
|
||||
QString OpenVpnConfigurator::convertOpenSShKey(const QString &key)
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
QTemporaryFile tmp;
|
||||
#ifdef QT_DEBUG
|
||||
tmp.setAutoRemove(false);
|
||||
#endif
|
||||
tmp.open();
|
||||
tmp.write(key.toUtf8());
|
||||
tmp.close();
|
||||
|
||||
// ssh-keygen -p -P "" -N "" -m pem -f id_ssh
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProgram("cmd.exe");
|
||||
p.setNativeArguments(QString("/C \"ssh-keygen.exe -p -P \"\" -N \"\" -m pem -f \"%1\"\"").arg(tmp.fileName()));
|
||||
#else
|
||||
p.setProgram("ssh-keygen");
|
||||
p.setArguments(QStringList() << "-p" << "-P" << "" << "-N" << "" << "-m" << "pem" << "-f" << tmp.fileName());
|
||||
#endif
|
||||
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
|
||||
qDebug().noquote() << "OpenVpnConfigurator::convertOpenSShKey" << p.exitCode() << p.exitStatus() << p.readAll();
|
||||
|
||||
tmp.open();
|
||||
|
||||
return tmp.readAll();
|
||||
}
|
||||
|
||||
ErrorCode OpenVpnConfigurator::signCert(DockerContainer container,
|
||||
const ServerCredentials &credentials, QString clientId)
|
||||
{
|
||||
|
|
|
@ -28,8 +28,6 @@ public:
|
|||
static QString processConfigWithLocalSettings(QString config);
|
||||
static QString processConfigWithExportSettings(QString config);
|
||||
|
||||
static QString convertOpenSShKey(const QString &key);
|
||||
|
||||
static ErrorCode signCert(DockerContainer container,
|
||||
const ServerCredentials &credentials, QString clientId);
|
||||
|
||||
|
|
95
client/configurators/ssh_configurator.cpp
Normal file
95
client/configurators/ssh_configurator.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
#include "ssh_configurator.h"
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTemporaryDir>
|
||||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
#include <QTextEdit>
|
||||
#include <QPlainTextEdit>
|
||||
#include <qtimer.h>
|
||||
|
||||
#include "core/server_defs.h"
|
||||
#include "utils.h"
|
||||
|
||||
using namespace QSsh;
|
||||
|
||||
|
||||
QString SshConfigurator::convertOpenSShKey(const QString &key)
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
QTemporaryFile tmp;
|
||||
#ifdef QT_DEBUG
|
||||
tmp.setAutoRemove(false);
|
||||
#endif
|
||||
tmp.open();
|
||||
tmp.write(key.toUtf8());
|
||||
tmp.close();
|
||||
|
||||
// ssh-keygen -p -P "" -N "" -m pem -f id_ssh
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProgram("cmd.exe");
|
||||
p.setNativeArguments(QString("/C \"ssh-keygen.exe -p -P \"\" -N \"\" -m pem -f \"%1\"\"").arg(tmp.fileName()));
|
||||
#else
|
||||
p.setProgram("ssh-keygen");
|
||||
p.setArguments(QStringList() << "-p" << "-P" << "" << "-N" << "" << "-m" << "pem" << "-f" << tmp.fileName());
|
||||
#endif
|
||||
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
|
||||
qDebug().noquote() << "OpenVpnConfigurator::convertOpenSShKey" << p.exitCode() << p.exitStatus() << p.readAll();
|
||||
|
||||
tmp.open();
|
||||
|
||||
return tmp.readAll();
|
||||
}
|
||||
|
||||
void SshConfigurator::openSshTerminal(const ServerCredentials &credentials)
|
||||
{
|
||||
QProcess *p = new QProcess();
|
||||
p->setReadChannelMode(QProcess::SeparateChannels);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
p->setProcessEnvironment(prepareEnv());
|
||||
p->setProgram(qApp->applicationDirPath() + "\\cygwin\\putty.exe");
|
||||
|
||||
if (credentials.password.contains("PRIVATE KEY")) {
|
||||
// todo: connect by key
|
||||
// p->setNativeArguments(QString("%1@%2")
|
||||
// .arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
||||
}
|
||||
else {
|
||||
p->setNativeArguments(QString("%1@%2 -pw %3")
|
||||
.arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
||||
}
|
||||
#else
|
||||
p.setProgram("/bin/bash");
|
||||
#endif
|
||||
|
||||
p->startDetached();
|
||||
}
|
||||
|
||||
QProcessEnvironment SshConfigurator::prepareEnv()
|
||||
{
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString pathEnvVar = env.value("PATH");
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
pathEnvVar.clear();
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\cygwin;");
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\openvpn;");
|
||||
#else
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS");
|
||||
#endif
|
||||
|
||||
env.insert("PATH", pathEnvVar);
|
||||
//qDebug().noquote() << "ENV PATH" << pathEnvVar;
|
||||
return env;
|
||||
}
|
20
client/configurators/ssh_configurator.h
Normal file
20
client/configurators/ssh_configurator.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef SSH_CONFIGURATOR_H
|
||||
#define SSH_CONFIGURATOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "settings.h"
|
||||
#include "core/servercontroller.h"
|
||||
|
||||
class SshConfigurator
|
||||
{
|
||||
public:
|
||||
static QProcessEnvironment prepareEnv();
|
||||
static QString convertOpenSShKey(const QString &key);
|
||||
static void openSshTerminal(const ServerCredentials &credentials);
|
||||
|
||||
};
|
||||
|
||||
#endif // SSH_CONFIGURATOR_H
|
178
client/configurators/wireguard_configurator.cpp
Normal file
178
client/configurators/wireguard_configurator.cpp
Normal file
|
@ -0,0 +1,178 @@
|
|||
#include "wireguard_configurator.h"
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTemporaryDir>
|
||||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include "sftpdefs.h"
|
||||
|
||||
#include "core/server_defs.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
#include "core/scripts_registry.h"
|
||||
#include "utils.h"
|
||||
|
||||
QProcessEnvironment WireguardConfigurator::prepareEnv()
|
||||
{
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString pathEnvVar = env.value("PATH");
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
pathEnvVar.clear();
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\wireguard;");
|
||||
#else
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS");
|
||||
#endif
|
||||
|
||||
env.insert("PATH", pathEnvVar);
|
||||
qDebug().noquote() << "ENV PATH" << pathEnvVar;
|
||||
return env;
|
||||
}
|
||||
|
||||
WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
||||
{
|
||||
ConnectionData connData;
|
||||
|
||||
QString program;
|
||||
#ifdef Q_OS_WIN
|
||||
program = QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\wireguard\\wg.exe";
|
||||
#else
|
||||
program = QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS/wg";
|
||||
#endif
|
||||
|
||||
// Priv
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
p.setProgram(program);
|
||||
|
||||
p.setArguments(QStringList() << "genkey");
|
||||
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
|
||||
connData.clientPrivKey = QString(p.readAll());
|
||||
connData.clientPrivKey.replace("\r", "");
|
||||
connData.clientPrivKey.replace("\n", "");
|
||||
}
|
||||
|
||||
// Pub
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
p.setProgram(program);
|
||||
|
||||
p.setArguments(QStringList() << "pubkey");
|
||||
|
||||
p.start();
|
||||
p.write(connData.clientPrivKey.toUtf8());
|
||||
p.closeWriteChannel();
|
||||
p.waitForFinished();
|
||||
|
||||
connData.clientPubKey = QString(p.readAll());
|
||||
connData.clientPubKey.replace("\r", "");
|
||||
connData.clientPubKey.replace("\n", "");
|
||||
}
|
||||
|
||||
return connData;
|
||||
}
|
||||
|
||||
WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode)
|
||||
{
|
||||
WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys();
|
||||
connData.host = credentials.hostName;
|
||||
|
||||
if (connData.clientPrivKey.isEmpty() || connData.clientPubKey.isEmpty()) {
|
||||
if (errorCode) *errorCode = ErrorCode::EasyRsaExecutableMissing;
|
||||
return connData;
|
||||
}
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
connData.serverPubKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPublicKeyPath, &e);
|
||||
connData.serverPubKey.replace("\n", "");
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return connData;
|
||||
}
|
||||
|
||||
connData.pskKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPskKeyPath, &e);
|
||||
connData.pskKey.replace("\n", "");
|
||||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return connData;
|
||||
}
|
||||
|
||||
|
||||
QString configPart = QString(
|
||||
"[Peer]\n"
|
||||
"PublicKey = %1\n"
|
||||
"PresharedKey = %2\n"
|
||||
"AllowedIPs = $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR\n\n").
|
||||
arg(connData.clientPubKey).
|
||||
arg(connData.pskKey);
|
||||
|
||||
configPart = ServerController::replaceVars(configPart, ServerController::genVarsForScript(credentials, container));
|
||||
|
||||
qDebug().noquote() << "Adding wg conf part to server" << configPart;
|
||||
|
||||
e = ServerController::uploadTextFileToContainer(container, credentials, configPart,
|
||||
protocols::wireguard::serverConfigPath, QSsh::SftpOverwriteMode::SftpAppendToExisting);
|
||||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return connData;
|
||||
}
|
||||
|
||||
e = ServerController::runScript(ServerController::sshParams(credentials),
|
||||
ServerController::replaceVars("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip /opt/amnezia/wireguard/wg0.conf)'",
|
||||
ServerController::genVarsForScript(credentials, container)));
|
||||
|
||||
return connData;
|
||||
}
|
||||
|
||||
Settings &WireguardConfigurator::m_settings()
|
||||
{
|
||||
static Settings s;
|
||||
return s;
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
QString config = ServerController::replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container),
|
||||
ServerController::genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
ConnectionData connData = prepareWireguardConfig(credentials, container, errorCode);
|
||||
if (errorCode && *errorCode) {
|
||||
return "";
|
||||
}
|
||||
|
||||
config.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", connData.clientPrivKey);
|
||||
config.replace("$WIREGUARD_SERVER_PUBLIC_KEY", connData.serverPubKey);
|
||||
config.replace("$WIREGUARD_PSK", connData.pskKey);
|
||||
|
||||
qDebug().noquote() << config;
|
||||
return config;
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::processConfigWithLocalSettings(QString config)
|
||||
{
|
||||
// TODO replace DNS if it already set
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::processConfigWithExportSettings(QString config)
|
||||
{
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
return config;
|
||||
}
|
41
client/configurators/wireguard_configurator.h
Normal file
41
client/configurators/wireguard_configurator.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef WIREGUARD_CONFIGURATOR_H
|
||||
#define WIREGUARD_CONFIGURATOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "settings.h"
|
||||
#include "core/servercontroller.h"
|
||||
|
||||
class WireguardConfigurator
|
||||
{
|
||||
public:
|
||||
|
||||
struct ConnectionData {
|
||||
QString clientPrivKey; // client private key
|
||||
QString clientPubKey; // client public key
|
||||
QString serverPubKey; // tls-auth key
|
||||
QString pskKey; // preshared key
|
||||
QString host; // host ip
|
||||
};
|
||||
|
||||
static QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static QString processConfigWithLocalSettings(QString config);
|
||||
static QString processConfigWithExportSettings(QString config);
|
||||
|
||||
|
||||
private:
|
||||
static QProcessEnvironment prepareEnv();
|
||||
|
||||
static ConnectionData prepareWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static ConnectionData genClientKeys();
|
||||
|
||||
static Settings &m_settings();
|
||||
};
|
||||
|
||||
#endif // WIREGUARD_CONFIGURATOR_H
|
|
@ -13,7 +13,7 @@ struct ServerCredentials
|
|||
QString password;
|
||||
int port = 22;
|
||||
|
||||
bool isValid() { return !hostName.isEmpty() && !userName.isEmpty() && !password.isEmpty() && port > 0; }
|
||||
bool isValid() const { return !hostName.isEmpty() && !userName.isEmpty() && !password.isEmpty() && port > 0; }
|
||||
};
|
||||
|
||||
enum ErrorCode
|
||||
|
@ -44,6 +44,7 @@ enum ErrorCode
|
|||
OpenVpnConfigMissing,
|
||||
OpenVpnManagementServerError,
|
||||
EasyRsaError,
|
||||
ConfigMissing,
|
||||
|
||||
// Distro errors
|
||||
OpenVpnExecutableMissing,
|
||||
|
@ -51,6 +52,7 @@ enum ErrorCode
|
|||
ShadowSocksExecutableMissing,
|
||||
CloakExecutableMissing,
|
||||
AmneziaServiceConnectionFailed,
|
||||
ExecutableMissing,
|
||||
|
||||
// VPN errors
|
||||
OpenVpnAdaptersInUseError,
|
||||
|
@ -69,6 +71,7 @@ const char key_openvpn_config_data[] = "openvpn_config_data";
|
|||
const char key_openvpn_config_path[] = "openvpn_config_path";
|
||||
const char key_shadowsocks_config_data[] = "shadowsocks_config_data";
|
||||
const char key_cloak_config_data[] = "cloak_config_data";
|
||||
const char key_wireguard_config_data[] = "wireguard_config_data";
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ QSharedPointer<IpcProcessInterfaceReplica> IpcClient::CreatePrivilegedProcess()
|
|||
qWarning() << "IpcProcessInterfaceReplica replica is not connected!";
|
||||
}
|
||||
|
||||
connect(pd->ipcProcess.data(), &IpcProcessInterfaceReplica::destroyed, pd->ipcProcess.data(), [pd](){
|
||||
QObject::connect(pd->ipcProcess.data(), &IpcProcessInterfaceReplica::destroyed, pd->ipcProcess.data(), [pd](){
|
||||
pd->replicaNode->deleteLater();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ QString amnezia::scriptName(ProtocolScriptType type)
|
|||
case ProtocolScriptType::configure_container: return QLatin1String("configure_container.sh");
|
||||
case ProtocolScriptType::container_startup: return QLatin1String("start.sh");
|
||||
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
|
||||
case ProtocolScriptType::wireguard_template: return QLatin1String("template.conf");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ enum ProtocolScriptType {
|
|||
run_container,
|
||||
configure_container,
|
||||
container_startup,
|
||||
openvpn_template
|
||||
openvpn_template,
|
||||
wireguard_template
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -120,7 +120,8 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams,
|
|||
}
|
||||
|
||||
ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path)
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path,
|
||||
QSsh::SftpOverwriteMode overwriteMode)
|
||||
{
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
QString tmpFileName = QString("/tmp/%1.tmp").arg(Utils::getRandomString(16));
|
||||
|
@ -132,11 +133,29 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
|||
stdOut += data + "\n";
|
||||
};
|
||||
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
if (overwriteMode == QSsh::SftpOverwriteMode::SftpOverwriteExisting) {
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
|
||||
if (e) return e;
|
||||
}
|
||||
else if (overwriteMode == QSsh::SftpOverwriteMode::SftpAppendToExisting) {
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(tmpFileName),
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
|
||||
if (e) return e;
|
||||
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName).arg(path),
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
|
||||
if (e) return e;
|
||||
}
|
||||
else return ErrorCode::NotImplementedError;
|
||||
|
||||
|
||||
if (e) return e;
|
||||
if (stdOut.contains("Error: No such container:")) {
|
||||
return ErrorCode::ServerContainerMissingError;
|
||||
}
|
||||
|
@ -199,15 +218,16 @@ QString ServerController::getTextFileFromContainer(DockerContainer container,
|
|||
if (errorCode) *errorCode = fromSshProcessExitStatus(exitStatus);
|
||||
}
|
||||
|
||||
if (errorCode) *errorCode = ErrorCode::NoError;
|
||||
return proc->readAllStandardOutput();
|
||||
}
|
||||
|
||||
ErrorCode ServerController::checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials)
|
||||
{
|
||||
QString caCert = ServerController::getTextFileFromContainer(container,
|
||||
credentials, amnezia::protocols::openvpn::caCertPath);
|
||||
credentials, protocols::openvpn::caCertPath);
|
||||
QString taKey = ServerController::getTextFileFromContainer(container,
|
||||
credentials, amnezia::protocols::openvpn::taKeyPath);
|
||||
credentials, protocols::openvpn::taKeyPath);
|
||||
|
||||
if (!caCert.isEmpty() && !taKey.isEmpty()) {
|
||||
return ErrorCode::NoError;
|
||||
|
@ -217,7 +237,8 @@ ErrorCode ServerController::checkOpenVpnServer(DockerContainer container, const
|
|||
}
|
||||
}
|
||||
|
||||
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath)
|
||||
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath,
|
||||
QSsh::SftpOverwriteMode overwriteMode)
|
||||
{
|
||||
SshConnection *client = connectToHost(sshParams(credentials));
|
||||
if (client->state() != SshConnection::State::Connected) {
|
||||
|
@ -508,11 +529,12 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred
|
|||
genVarsForScript(credentials, container, config)));
|
||||
}
|
||||
|
||||
ServerController::Vars ServerController:: genVarsForScript(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
const QJsonObject &openvpnConfig = config.value(config_key::openvpn).toObject();
|
||||
const QJsonObject &cloakConfig = config.value(config_key::cloak).toObject();
|
||||
const QJsonObject &ssConfig = config.value(config_key::shadowsocks).toObject();
|
||||
const QJsonObject &wireguarConfig = config.value(config_key::wireguard).toObject();
|
||||
//
|
||||
|
||||
Vars vars;
|
||||
|
@ -520,20 +542,20 @@ ServerController::Vars ServerController:: genVarsForScript(const ServerCredent
|
|||
vars.append({{"$REMOTE_HOST", credentials.hostName}});
|
||||
|
||||
// OpenVPN vars
|
||||
vars.append({{"$VPN_SUBNET_IP", openvpnConfig.value(config_key::subnet_address).toString(amnezia::protocols::vpnDefaultSubnetAddress) }});
|
||||
vars.append({{"$VPN_SUBNET_MASK_VAL", openvpnConfig.value(config_key::subnet_mask_val).toString(amnezia::protocols::vpnDefaultSubnetMaskVal) }});
|
||||
vars.append({{"$VPN_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(amnezia::protocols::vpnDefaultSubnetMask) }});
|
||||
vars.append({{"$OPENVPN_SUBNET_IP", openvpnConfig.value(config_key::subnet_address).toString(protocols::openvpn::defaultSubnetAddress) }});
|
||||
vars.append({{"$OPENVPN_SUBNET_CIDR", openvpnConfig.value(config_key::subnet_cidr).toString(protocols::openvpn::defaultSubnetCidr) }});
|
||||
vars.append({{"$OPENVPN_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(protocols::openvpn::defaultSubnetMask) }});
|
||||
|
||||
vars.append({{"$OPENVPN_PORT", openvpnConfig.value(config_key::port).toString(amnezia::protocols::openvpn::defaultPort) }});
|
||||
vars.append({{"$OPENVPN_TRANSPORT_PROTO", openvpnConfig.value(config_key::transport_proto).toString(amnezia::protocols::openvpn::defaultTransportProto) }});
|
||||
vars.append({{"$OPENVPN_PORT", openvpnConfig.value(config_key::port).toString(protocols::openvpn::defaultPort) }});
|
||||
vars.append({{"$OPENVPN_TRANSPORT_PROTO", openvpnConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) }});
|
||||
|
||||
bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(amnezia::protocols::openvpn::defaultNcpDisable);
|
||||
bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable);
|
||||
vars.append({{"$OPENVPN_NCP_DISABLE", isNcpDisabled ? protocols::openvpn::ncpDisableString : "" }});
|
||||
|
||||
vars.append({{"$OPENVPN_CIPHER", openvpnConfig.value(config_key::cipher).toString(amnezia::protocols::openvpn::defaultCipher) }});
|
||||
vars.append({{"$OPENVPN_HASH", openvpnConfig.value(config_key::hash).toString(amnezia::protocols::openvpn::defaultHash) }});
|
||||
vars.append({{"$OPENVPN_CIPHER", openvpnConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher) }});
|
||||
vars.append({{"$OPENVPN_HASH", openvpnConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash) }});
|
||||
|
||||
bool isTlsAuth = openvpnConfig.value(config_key::tls_auth).toBool(amnezia::protocols::openvpn::defaultTlsAuth);
|
||||
bool isTlsAuth = openvpnConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth);
|
||||
vars.append({{"$OPENVPN_TLS_AUTH", isTlsAuth ? protocols::openvpn::tlsAuthString : "" }});
|
||||
if (!isTlsAuth) {
|
||||
// erase $OPENVPN_TA_KEY, so it will not set in OpenVpnConfigurator::genOpenVpnConfig
|
||||
|
@ -541,9 +563,9 @@ ServerController::Vars ServerController:: genVarsForScript(const ServerCredent
|
|||
}
|
||||
|
||||
// ShadowSocks vars
|
||||
vars.append({{"$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(amnezia::protocols::shadowsocks::defaultPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_LOCAL_PORT", ssConfig.value(config_key::local_port).toString(amnezia::protocols::shadowsocks::defaultLocalProxyPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_CIPHER", ssConfig.value(config_key::cipher).toString(amnezia::protocols::shadowsocks::defaultCipher) }});
|
||||
vars.append({{"$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_LOCAL_PORT", ssConfig.value(config_key::local_port).toString(protocols::shadowsocks::defaultLocalProxyPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_CIPHER", ssConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher) }});
|
||||
|
||||
vars.append({{"$CONTAINER_NAME", amnezia::containerToString(container)}});
|
||||
vars.append({{"$DOCKERFILE_FOLDER", "/opt/amnezia/" + amnezia::containerToString(container)}});
|
||||
|
@ -552,6 +574,14 @@ ServerController::Vars ServerController:: genVarsForScript(const ServerCredent
|
|||
vars.append({{"$CLOAK_SERVER_PORT", cloakConfig.value(config_key::port).toString(protocols::cloak::defaultPort) }});
|
||||
vars.append({{"$FAKE_WEB_SITE_ADDRESS", cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) }});
|
||||
|
||||
// Wireguard vars
|
||||
vars.append({{"$WIREGUARD_SUBNET_IP", openvpnConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) }});
|
||||
vars.append({{"$WIREGUARD_SUBNET_CIDR", openvpnConfig.value(config_key::subnet_cidr).toString(protocols::wireguard::defaultSubnetCidr) }});
|
||||
vars.append({{"$WIREGUARD_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(protocols::wireguard::defaultSubnetMask) }});
|
||||
|
||||
vars.append({{"$WIREGUARD_SERVER_PORT", wireguarConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) }});
|
||||
|
||||
|
||||
QString serverIp = Utils::getIPAddress(credentials.hostName);
|
||||
if (!serverIp.isEmpty()) {
|
||||
vars.append({{"$SERVER_IP_ADDRESS", serverIp}});
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "defs.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
#include "sftpdefs.h"
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
|
@ -35,10 +36,12 @@ public:
|
|||
|
||||
static ErrorCode checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials);
|
||||
|
||||
static ErrorCode uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath);
|
||||
static ErrorCode uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data,
|
||||
const QString &remotePath, QSsh::SftpOverwriteMode overwriteMode = QSsh::SftpOverwriteMode::SftpOverwriteExisting);
|
||||
|
||||
static ErrorCode uploadTextFileToContainer(DockerContainer container,
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path);
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path,
|
||||
QSsh::SftpOverwriteMode overwriteMode = QSsh::SftpOverwriteMode::SftpOverwriteExisting);
|
||||
|
||||
static QString getTextFileFromContainer(DockerContainer container,
|
||||
const ServerCredentials &credentials, const QString &path, ErrorCode *errorCode = nullptr);
|
||||
|
@ -54,9 +57,10 @@ public:
|
|||
static Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject());
|
||||
|
||||
static QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr);
|
||||
private:
|
||||
static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
||||
|
||||
private:
|
||||
|
||||
static ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
|
||||
static ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
static ErrorCode buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#define APPLICATION_NAME "AmneziaVPN"
|
||||
#define SERVICE_NAME "AmneziaVPN-service"
|
||||
#define ORGANIZATION_NAME "AmneziaVPN.ORG"
|
||||
#define APP_MAJOR_VERSION "1.7.4"
|
||||
#define APP_VERSION "1.7.4.0"
|
||||
#define APP_MAJOR_VERSION "1.7.5"
|
||||
#define APP_VERSION "1.7.5.3"
|
||||
|
||||
#endif // DEFINES_H
|
||||
|
|
|
@ -5,12 +5,16 @@
|
|||
#include <QTcpSocket>
|
||||
|
||||
#include "debug.h"
|
||||
#include "openvpnprotocol.h"
|
||||
#include "defines.h"
|
||||
#include "utils.h"
|
||||
#include "openvpnprotocol.h"
|
||||
|
||||
|
||||
OpenVpnProtocol::OpenVpnProtocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
Utils::initializePath(defaultConfigPath());
|
||||
|
||||
readOpenVpnConfiguration(configuration);
|
||||
connect(&m_managementServer, &ManagementServer::readyRead, this, &OpenVpnProtocol::onReadyReadDataFromManagementServer);
|
||||
}
|
||||
|
@ -22,6 +26,17 @@ OpenVpnProtocol::~OpenVpnProtocol()
|
|||
QThread::msleep(200);
|
||||
}
|
||||
|
||||
QString OpenVpnProtocol::defaultConfigFileName()
|
||||
{
|
||||
qDebug() << "OpenVpnProtocol::defaultConfigFileName" << defaultConfigPath() + QString("/%1.ovpn").arg(APPLICATION_NAME);
|
||||
return defaultConfigPath() + QString("/%1.ovpn").arg(APPLICATION_NAME);
|
||||
}
|
||||
|
||||
QString OpenVpnProtocol::defaultConfigPath()
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/config";
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::stop()
|
||||
{
|
||||
qDebug() << "OpenVpnProtocol::stop()";
|
||||
|
@ -81,7 +96,7 @@ void OpenVpnProtocol::readOpenVpnConfiguration(const QJsonObject &configuration)
|
|||
QFileInfo file(m_configFileName);
|
||||
|
||||
if (file.fileName().isEmpty()) {
|
||||
m_configFileName = Utils::defaultVpnConfigFileName();
|
||||
m_configFileName = defaultConfigFileName();
|
||||
}
|
||||
|
||||
qDebug().noquote() << QString("Set config file: '%1'").arg(configPath());
|
||||
|
|
|
@ -22,6 +22,8 @@ public:
|
|||
void stop() override;
|
||||
|
||||
ErrorCode checkAndSetupTapDriver();
|
||||
static QString defaultConfigFileName();
|
||||
static QString defaultConfigPath();
|
||||
|
||||
protected slots:
|
||||
void onReadyReadDataFromManagementServer();
|
||||
|
|
|
@ -36,7 +36,7 @@ constexpr char block_outside_dns[] = "block_outside_dns";
|
|||
|
||||
constexpr char subnet_address[] = "subnet_address";
|
||||
constexpr char subnet_mask[] = "subnet_mask";
|
||||
constexpr char subnet_mask_val[] = "subnet_mask_val";
|
||||
constexpr char subnet_cidr[] = "subnet_cidr";
|
||||
|
||||
// proto config keys
|
||||
constexpr char last_config[] = "last_config";
|
||||
|
@ -55,14 +55,16 @@ constexpr char amnezia_wireguard[] = "amnezia-wireguard";
|
|||
|
||||
namespace protocols {
|
||||
|
||||
constexpr char vpnDefaultSubnetAddress[] = "10.8.0.0";
|
||||
constexpr char vpnDefaultSubnetMask[] = "255.255.255.0";
|
||||
constexpr char vpnDefaultSubnetMaskVal[] = "24";
|
||||
|
||||
|
||||
constexpr char UDP[] = "udp"; // case sens
|
||||
constexpr char TCP[] = "tcp";
|
||||
|
||||
namespace openvpn {
|
||||
constexpr char defaultSubnetAddress[] = "10.8.0.0";
|
||||
constexpr char defaultSubnetMask[] = "255.255.255.0";
|
||||
constexpr char defaultSubnetCidr[] = "24";
|
||||
|
||||
constexpr char caCertPath[] = "/opt/amnezia/openvpn/pki/ca.crt";
|
||||
constexpr char clientCertPath[] = "/opt/amnezia/openvpn/pki/issued";
|
||||
constexpr char taKeyPath[] = "/opt/amnezia/openvpn/ta.key";
|
||||
|
@ -96,6 +98,17 @@ constexpr char defaultCipher[] = "chacha20-ietf-poly1305";
|
|||
|
||||
}
|
||||
|
||||
namespace wireguard {
|
||||
constexpr char defaultSubnetAddress[] = "10.8.1.0";
|
||||
constexpr char defaultSubnetMask[] = "255.255.255.0";
|
||||
constexpr char defaultSubnetCidr[] = "24";
|
||||
|
||||
constexpr char defaultPort[] = "51820";
|
||||
constexpr char serverConfigPath[] = "/opt/amnezia/wireguard/wg0.conf";
|
||||
constexpr char serverPublicKeyPath[] = "/opt/amnezia/wireguard/wireguard_server_public_key.key";
|
||||
constexpr char serverPskKeyPath[] = "/opt/amnezia/wireguard/wireguard_psk.key";
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace protocols
|
||||
|
|
232
client/protocols/wireguardprotocol.cpp
Normal file
232
client/protocols/wireguardprotocol.cpp
Normal file
|
@ -0,0 +1,232 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QTcpSocket>
|
||||
#include <QThread>
|
||||
|
||||
#include "debug.h"
|
||||
#include "wireguardprotocol.h"
|
||||
#include "utils.h"
|
||||
|
||||
WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
//m_configFile.setFileTemplate(QDir::tempPath() + QDir::separator() + serviceName() + ".conf");
|
||||
m_configFile.setFileName(QDir::tempPath() + QDir::separator() + serviceName() + ".conf");
|
||||
readWireguardConfiguration(configuration);
|
||||
}
|
||||
|
||||
WireguardProtocol::~WireguardProtocol()
|
||||
{
|
||||
qDebug() << "WireguardProtocol::~WireguardProtocol()";
|
||||
WireguardProtocol::stop();
|
||||
QThread::msleep(200);
|
||||
}
|
||||
|
||||
void WireguardProtocol::stop()
|
||||
{
|
||||
if (!QFileInfo::exists(wireguardExecPath())) {
|
||||
qCritical() << "Wireguard executable missing!";
|
||||
setLastError(ErrorCode::ExecutableMissing);
|
||||
return;
|
||||
}
|
||||
|
||||
m_wireguardStopProcess = IpcClient::CreatePrivilegedProcess();
|
||||
|
||||
if (!m_wireguardStopProcess) {
|
||||
qCritical() << "IpcProcess replica is not created!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return;
|
||||
}
|
||||
|
||||
m_wireguardStopProcess->waitForSource(1000);
|
||||
if (!m_wireguardStopProcess->isInitialized()) {
|
||||
qWarning() << "IpcProcess replica is not connected!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return;
|
||||
}
|
||||
|
||||
m_wireguardStopProcess->setProgram(wireguardExecPath());
|
||||
|
||||
|
||||
QStringList arguments({"/uninstalltunnelservice", serviceName(), });
|
||||
m_wireguardStopProcess->setArguments(arguments);
|
||||
|
||||
qDebug() << arguments.join(" ");
|
||||
|
||||
connect(m_wireguardStopProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, this, [this](QProcess::ProcessError error) {
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol errorOccurred" << error;
|
||||
setConnectionState(ConnectionState::Disconnected);
|
||||
});
|
||||
|
||||
connect(m_wireguardStopProcess.data(), &IpcProcessInterfaceReplica::stateChanged, this, [this](QProcess::ProcessState newState) {
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol Stop stateChanged" << newState;
|
||||
});
|
||||
|
||||
m_wireguardStopProcess->start();
|
||||
|
||||
setConnectionState(VpnProtocol::Disconnected);
|
||||
}
|
||||
|
||||
void WireguardProtocol::readWireguardConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
if (configuration.contains(config::key_wireguard_config_data)) {
|
||||
if (!m_configFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
qCritical() << "Failed to save wireguard config to" << m_configFile.fileName();
|
||||
return;
|
||||
}
|
||||
|
||||
m_isConfigLoaded = true;
|
||||
|
||||
m_configFile.write(configuration.value(config::key_wireguard_config_data).toString().toUtf8());
|
||||
m_configFile.close();
|
||||
m_configFileName = m_configFile.fileName();
|
||||
|
||||
qDebug().noquote() << QString("Set config data") << m_configFileName;
|
||||
qDebug().noquote() << QString("Set config data") << configuration.value(config::key_wireguard_config_data).toString().toUtf8();
|
||||
}
|
||||
// else if (configuration.contains(config::key_wireguard_config_path)) {
|
||||
// m_configFileName = configuration.value(config::key_wireguard_config_path).toString();
|
||||
// QFileInfo file(m_configFileName);
|
||||
|
||||
// if (file.fileName().isEmpty()) {
|
||||
// m_configFileName = defaultConfigFileName();
|
||||
// }
|
||||
|
||||
// qDebug().noquote() << QString("Set config file: '%1'").arg(configPath());
|
||||
// }
|
||||
}
|
||||
|
||||
//bool WireguardProtocol::openVpnProcessIsRunning() const
|
||||
//{
|
||||
// return Utils::processIsRunning("openvpn");
|
||||
//}
|
||||
|
||||
QString WireguardProtocol::configPath() const
|
||||
{
|
||||
return m_configFileName;
|
||||
}
|
||||
|
||||
void WireguardProtocol::updateRouteGateway(QString line)
|
||||
{
|
||||
// TODO: fix for macos
|
||||
line = line.split("ROUTE_GATEWAY", QString::SkipEmptyParts).at(1);
|
||||
if (!line.contains("/")) return;
|
||||
m_routeGateway = line.split("/", QString::SkipEmptyParts).first();
|
||||
m_routeGateway.replace(" ", "");
|
||||
qDebug() << "Set VPN route gateway" << m_routeGateway;
|
||||
}
|
||||
|
||||
QString WireguardProtocol::wireguardExecPath() const
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return Utils::executable("wireguard/wireguard", true);
|
||||
#else
|
||||
return Utils::executable("/wireguard", true);
|
||||
#endif
|
||||
}
|
||||
|
||||
ErrorCode WireguardProtocol::start()
|
||||
{
|
||||
if (!m_isConfigLoaded) {
|
||||
setLastError(ErrorCode::ConfigMissing);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
//qDebug() << "Start OpenVPN connection";
|
||||
WireguardProtocol::stop();
|
||||
|
||||
if (!QFileInfo::exists(wireguardExecPath())) {
|
||||
setLastError(ErrorCode::ExecutableMissing);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
if (!QFileInfo::exists(configPath())) {
|
||||
setLastError(ErrorCode::ConfigMissing);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
setConnectionState(ConnectionState::Connecting);
|
||||
|
||||
m_wireguardStartProcess = IpcClient::CreatePrivilegedProcess();
|
||||
|
||||
if (!m_wireguardStartProcess) {
|
||||
//qWarning() << "IpcProcess replica is not created!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
m_wireguardStartProcess->waitForSource(1000);
|
||||
if (!m_wireguardStartProcess->isInitialized()) {
|
||||
qWarning() << "IpcProcess replica is not connected!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
m_wireguardStartProcess->setProgram(wireguardExecPath());
|
||||
|
||||
|
||||
QStringList arguments({"/installtunnelservice", configPath(), });
|
||||
m_wireguardStartProcess->setArguments(arguments);
|
||||
|
||||
qDebug() << arguments.join(" ");
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, this, [this](QProcess::ProcessError error) {
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol errorOccurred" << error;
|
||||
setConnectionState(ConnectionState::Disconnected);
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::stateChanged, this, [this](QProcess::ProcessState newState) {
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol stateChanged" << newState;
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::finished, this, [this]() {
|
||||
setConnectionState(ConnectionState::Connected);
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyRead, this, [this]() {
|
||||
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAll();
|
||||
reply.waitForFinished(1000);
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol readyRead" << reply.returnValue();
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyReadStandardOutput, this, [this]() {
|
||||
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAllStandardOutput();
|
||||
reply.waitForFinished(1000);
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardOutput" << reply.returnValue();
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyReadStandardError, this, [this]() {
|
||||
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAllStandardError();
|
||||
reply.waitForFinished(1000);
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardError" << reply.returnValue();
|
||||
});
|
||||
|
||||
m_wireguardStartProcess->start();
|
||||
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
void WireguardProtocol::updateVpnGateway(const QString &line)
|
||||
{
|
||||
// // line looks like
|
||||
// // PUSH: Received control message: 'PUSH_REPLY,route 10.8.0.1,topology net30,ping 10,ping-restart 120,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM'
|
||||
|
||||
// QStringList params = line.split(",");
|
||||
// for (const QString &l : params) {
|
||||
// if (l.contains("ifconfig")) {
|
||||
// if (l.split(" ").size() == 3) {
|
||||
// m_vpnLocalAddress = l.split(" ").at(1);
|
||||
// m_vpnGateway = l.split(" ").at(2);
|
||||
|
||||
// qDebug() << QString("Set vpn local address %1, gw %2").arg(m_vpnLocalAddress).arg(vpnGateway());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
QString WireguardProtocol::serviceName() const
|
||||
{
|
||||
return "AmneziaVPN.WireGuard0";
|
||||
}
|
46
client/protocols/wireguardprotocol.h
Normal file
46
client/protocols/wireguardprotocol.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef WIREGUARDPROTOCOL_H
|
||||
#define WIREGUARDPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTimer>
|
||||
|
||||
#include "vpnprotocol.h"
|
||||
#include "core/ipcclient.h"
|
||||
|
||||
class WireguardProtocol : public VpnProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WireguardProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
virtual ~WireguardProtocol() override;
|
||||
|
||||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
private:
|
||||
QString configPath() const;
|
||||
QString wireguardExecPath() const;
|
||||
//bool openVpnProcessIsRunning() const;
|
||||
void readWireguardConfiguration(const QJsonObject &configuration);
|
||||
|
||||
void updateRouteGateway(QString line);
|
||||
void updateVpnGateway(const QString &line);
|
||||
QString serviceName() const;
|
||||
|
||||
|
||||
private:
|
||||
QString m_configFileName;
|
||||
QFile m_configFile;
|
||||
|
||||
QSharedPointer<IpcProcessInterfaceReplica> m_wireguardStartProcess;
|
||||
QSharedPointer<IpcProcessInterfaceReplica> m_wireguardStopProcess;
|
||||
|
||||
bool m_isConfigLoaded = false;
|
||||
|
||||
};
|
||||
|
||||
#endif // WIREGUARDPROTOCOL_H
|
|
@ -62,5 +62,10 @@
|
|||
<file>server_scripts/openvpn_shadowsocks/start.sh</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/template.ovpn</file>
|
||||
<file>images/folder.png</file>
|
||||
<file>server_scripts/wireguard/configure_container.sh</file>
|
||||
<file>server_scripts/wireguard/Dockerfile</file>
|
||||
<file>server_scripts/wireguard/run_container.sh</file>
|
||||
<file>server_scripts/wireguard/start.sh</file>
|
||||
<file>server_scripts/wireguard/template.conf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -7,7 +7,7 @@ ca /opt/amnezia/openvpn/ca.crt \\n\
|
|||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key \\n\
|
||||
dh /opt/amnezia/openvpn/dh.pem \\n\
|
||||
server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
||||
server $OPENVPN_SUBNET_IP $OPENVPN_SUBNET_MASK \\n\
|
||||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# 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
|
||||
|
||||
|
@ -12,10 +13,10 @@ iptables -A FORWARD -i tun0 -j ACCEPT
|
|||
iptables -A OUTPUT -o tun0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i tun0 -o eth0 -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -o eth0 -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 $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
|
|
|
@ -7,7 +7,7 @@ ca /opt/amnezia/openvpn/ca.crt \\n\
|
|||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key \\n\
|
||||
dh /opt/amnezia/openvpn/dh.pem \\n\
|
||||
server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
||||
server $OPENVPN_SUBNET_IP $OPENVPN_SUBNET_MASK \\n\
|
||||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# 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
|
||||
|
||||
|
@ -12,10 +13,10 @@ iptables -A FORWARD -i tun0 -j ACCEPT
|
|||
iptables -A OUTPUT -o tun0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i tun0 -o eth0 -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -o eth0 -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 $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
|
|
|
@ -7,7 +7,7 @@ ca /opt/amnezia/openvpn/ca.crt \\n\
|
|||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key \\n\
|
||||
dh /opt/amnezia/openvpn/dh.pem \\n\
|
||||
server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
||||
server $OPENVPN_SUBNET_IP $OPENVPN_SUBNET_MASK \\n\
|
||||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# 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
|
||||
|
||||
|
@ -12,10 +13,10 @@ iptables -A FORWARD -i tun0 -j ACCEPT
|
|||
iptables -A OUTPUT -o tun0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i tun0 -o eth0 -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -o eth0 -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 $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
|
|
47
client/server_scripts/wireguard/Dockerfile
Normal file
47
client/server_scripts/wireguard/Dockerfile
Normal file
|
@ -0,0 +1,47 @@
|
|||
#FROM alpine:latest
|
||||
FROM itsthenetwork/alpine-tcpdump:latest
|
||||
|
||||
LABEL maintainer="AmneziaVPN"
|
||||
|
||||
#Install required packages
|
||||
RUN apk add --no-cache curl wireguard-tools dumb-init
|
||||
RUN apk --update upgrade --no-cache
|
||||
|
||||
RUN mkdir -p /opt/amnezia
|
||||
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
|
||||
RUN chmod a+x /opt/amnezia/start.sh
|
||||
|
||||
# Tune network
|
||||
RUN echo -e " \n\
|
||||
fs.file-max = 51200 \n\
|
||||
\n\
|
||||
net.core.rmem_max = 67108864 \n\
|
||||
net.core.wmem_max = 67108864 \n\
|
||||
net.core.netdev_max_backlog = 250000 \n\
|
||||
net.core.somaxconn = 4096 \n\
|
||||
\n\
|
||||
net.ipv4.tcp_syncookies = 1 \n\
|
||||
net.ipv4.tcp_tw_reuse = 1 \n\
|
||||
net.ipv4.tcp_tw_recycle = 0 \n\
|
||||
net.ipv4.tcp_fin_timeout = 30 \n\
|
||||
net.ipv4.tcp_keepalive_time = 1200 \n\
|
||||
net.ipv4.ip_local_port_range = 10000 65000 \n\
|
||||
net.ipv4.tcp_max_syn_backlog = 8192 \n\
|
||||
net.ipv4.tcp_max_tw_buckets = 5000 \n\
|
||||
net.ipv4.tcp_fastopen = 3 \n\
|
||||
net.ipv4.tcp_mem = 25600 51200 102400 \n\
|
||||
net.ipv4.tcp_rmem = 4096 87380 67108864 \n\
|
||||
net.ipv4.tcp_wmem = 4096 65536 67108864 \n\
|
||||
net.ipv4.tcp_mtu_probing = 1 \n\
|
||||
net.ipv4.tcp_congestion_control = hybla \n\
|
||||
# for low-latency network, use cubic instead \n\
|
||||
# net.ipv4.tcp_congestion_control = cubic \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/sysctl.conf && \
|
||||
mkdir -p /etc/security && \
|
||||
echo -e " \n\
|
||||
* soft nofile 51200 \n\
|
||||
* hard nofile 51200 \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf
|
||||
|
||||
ENTRYPOINT [ "dumb-init", "/opt/amnezia/start.sh" ]
|
||||
CMD [ "" ]
|
13
client/server_scripts/wireguard/configure_container.sh
Normal file
13
client/server_scripts/wireguard/configure_container.sh
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Wireguard config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
mkdir -p /opt/amnezia/wireguard; \
|
||||
cd /opt/amnezia/wireguard || exit 1; \
|
||||
WIREGUARD_SERVER_PRIVATE_KEY=$(wg genkey) && echo $WIREGUARD_SERVER_PRIVATE_KEY > /opt/amnezia/wireguard/wireguard_server_private_key.key; \
|
||||
WIREGUARD_SERVER_PUBLIC_KEY=$(echo $WIREGUARD_SERVER_PRIVATE_KEY | wg pubkey) && echo $WIREGUARD_SERVER_PUBLIC_KEY > /opt/amnezia/wireguard/wireguard_server_public_key.key; \
|
||||
WIREGUARD_PSK=$(wg genpsk) && echo $WIREGUARD_PSK > /opt/amnezia/wireguard/wireguard_psk.key; \
|
||||
echo -e "\
|
||||
[Interface]\\n\
|
||||
PrivateKey = $WIREGUARD_SERVER_PRIVATE_KEY \\n\
|
||||
Address = $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR \\n\
|
||||
ListenPort = $WIREGUARD_SERVER_PORT \\n\
|
||||
" >/opt/amnezia/wireguard/wg0.conf'
|
15
client/server_scripts/wireguard/run_container.sh
Normal file
15
client/server_scripts/wireguard/run_container.sh
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Run container
|
||||
sudo docker run -d \
|
||||
--restart always \
|
||||
--privileged \
|
||||
--cap-add=NET_ADMIN \
|
||||
--cap-add=SYS_MODULE \
|
||||
-p $WIREGUARD_SERVER_PORT:$WIREGUARD_SERVER_PORT/udp \
|
||||
-v /lib/modules:/lib/modules \
|
||||
--sysctl="net.ipv4.conf.all.src_valid_mark=1" \
|
||||
--name $CONTAINER_NAME \
|
||||
$CONTAINER_NAME
|
||||
|
||||
# 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"
|
||||
|
25
client/server_scripts/wireguard/start.sh
Normal file
25
client/server_scripts/wireguard/start.sh
Normal file
|
@ -0,0 +1,25 @@
|
|||
#!/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
|
||||
|
||||
# kill daemons in case of restart
|
||||
wg-quick down /opt/amnezia/wireguard/wg0.conf
|
||||
|
||||
# start daemons if configured
|
||||
if [ -f /opt/amnezia/wireguard/wg0.conf ]; then (wg-quick up /opt/amnezia/wireguard/wg0.conf); fi
|
||||
|
||||
# Allow traffic on the TUN interface.
|
||||
iptables -A INPUT -i wg0 -j ACCEPT
|
||||
iptables -A FORWARD -i wg0 -j ACCEPT
|
||||
iptables -A OUTPUT -o wg0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i wg0 -o eth0 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_MASK_CIDR -j ACCEPT
|
||||
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
iptables -t nat -A POSTROUTING -s $WIREGUARD_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
|
||||
tail -f /dev/null
|
11
client/server_scripts/wireguard/template.conf
Normal file
11
client/server_scripts/wireguard/template.conf
Normal file
|
@ -0,0 +1,11 @@
|
|||
[Interface]
|
||||
Address = 10.8.1.2/32
|
||||
DNS = 1.1.1.1, 1.0.0.1
|
||||
PrivateKey = $WIREGUARD_CLIENT_PRIVATE_KEY
|
||||
|
||||
[Peer]
|
||||
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
||||
PresharedKey = $WIREGUARD_PSK
|
||||
AllowedIPs = 0.0.0.0/0, ::/0
|
||||
Endpoint = $SERVER_IP_ADDRESS:$WIREGUARD_SERVER_PORT
|
||||
PersistentKeepalive = 25
|
|
@ -78,17 +78,6 @@ public:
|
|||
|
||||
RouteMode routeMode() const { return static_cast<RouteMode>(m_settings.value("Conf/routeMode", 0).toInt()); }
|
||||
void setRouteMode(RouteMode mode) { m_settings.setValue("Conf/routeMode", mode); }
|
||||
// bool customRouting() const { return m_settings.value("Conf/customRouting", false).toBool(); }
|
||||
// void setCustomRouting(bool customRouting) { m_settings.setValue("Conf/customRouting", customRouting); }
|
||||
|
||||
// // list of sites to pass blocking added by user
|
||||
// QStringList customSites() { return m_settings.value("Conf/customSites").toStringList(); }
|
||||
// void setCustomSites(const QStringList &customSites) { m_settings.setValue("Conf/customSites", customSites); }
|
||||
|
||||
// // list of ips to pass blocking generated from customSites
|
||||
// QStringList customIps() { return m_settings.value("Conf/customIps").toStringList(); }
|
||||
// void setCustomIps(const QStringList &customIps) { m_settings.setValue("Conf/customIps", customIps); }
|
||||
|
||||
|
||||
QVariantMap vpnSites(RouteMode mode) const { return m_settings.value("Conf/" + routeModeString(mode)).toMap(); }
|
||||
void setVpnSites(RouteMode mode, const QVariantMap &sites) { m_settings.setValue("Conf/"+ routeModeString(mode), sites); m_settings.sync(); }
|
||||
|
@ -100,16 +89,6 @@ public:
|
|||
void removeVpnSites(RouteMode mode, const QStringList &sites);
|
||||
|
||||
|
||||
// QVariantMap vpnForwardSites() const { return m_settings.value("Conf/vpnForwardSites").toMap(); }
|
||||
// void setVpnForwardSites(const QVariantMap &sites) { m_settings.setValue("Conf/vpnForwardSites", sites); }
|
||||
// void addVpnForwardSite(const QString &site, const QString &ip);
|
||||
// QStringList getVpnForwardIps() const;
|
||||
|
||||
// QVariantMap vpnExceptSites() const { return m_settings.value("Conf/vpnExceptSites").toMap(); }
|
||||
// void setVpnExceptSites(const QVariantMap &sites) { m_settings.setValue("Conf/vpnExceptSites", sites); }
|
||||
// void addVpnExceptSite(const QString &site, const QString &ip);
|
||||
// QStringList getVpnExceptIps() const;
|
||||
|
||||
QString primaryDns() const;
|
||||
QString secondaryDns() const;
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
#include "configurators/cloak_configurator.h"
|
||||
#include "configurators/vpn_configurator.h"
|
||||
#include "configurators/openvpn_configurator.h"
|
||||
#include "configurators/shadowsocks_configurator.h"
|
||||
#include "configurators/cloak_configurator.h"
|
||||
#include "configurators/ssh_configurator.h"
|
||||
|
||||
#include "core/servercontroller.h"
|
||||
#include "core/server_defs.h"
|
||||
|
@ -113,7 +113,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
qInfo().noquote() << QString("Started %1 version %2").arg(APPLICATION_NAME).arg(APP_VERSION);
|
||||
qInfo().noquote() << QString("%1 (%2)").arg(QSysInfo::prettyProductName()).arg(QSysInfo::currentCpuArchitecture());
|
||||
|
||||
Utils::initializePath(Utils::configPath());
|
||||
|
||||
m_vpnConnection = new VpnConnection(this);
|
||||
connect(m_vpnConnection, SIGNAL(bytesChanged(quint64, quint64)), this, SLOT(onBytesChanged(quint64, quint64)));
|
||||
|
@ -129,8 +128,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
});
|
||||
}
|
||||
|
||||
qDebug().noquote() << QString("Default config: %1").arg(Utils::defaultVpnConfigFileName());
|
||||
|
||||
m_ipAddressValidator.setRegExp(Utils::ipAddressRegExp());
|
||||
m_ipAddressPortValidator.setRegExp(Utils::ipAddressPortRegExp());
|
||||
m_ipNetwok24Validator.setRegExp(Utils::ipNetwork24RegExp());
|
||||
|
@ -378,6 +375,9 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
|
|||
selectedDockerContainer = m_settings.defaultContainer(selectedServerIndex);
|
||||
goToPage(Page::ServerVpnProtocols);
|
||||
break;
|
||||
case Qt::Key_T:
|
||||
SshConfigurator::openSshTerminal(m_settings.serverCredentials(m_settings.defaultServerIndex()));
|
||||
break;
|
||||
case Qt::Key_Escape:
|
||||
if (currentPage() == Page::Vpn) break;
|
||||
if (currentPage() == Page::ServerConfiguring) break;
|
||||
|
@ -470,7 +470,7 @@ void MainWindow::onPushButtonNewServerConnect(bool)
|
|||
}
|
||||
|
||||
if (key.contains("OPENSSH") && key.contains("BEGIN") && key.contains("PRIVATE KEY")) {
|
||||
key = OpenVpnConfigurator::convertOpenSShKey(key);
|
||||
key = SshConfigurator::convertOpenSShKey(key);
|
||||
}
|
||||
|
||||
serverCredentials.password = key;
|
||||
|
@ -1272,18 +1272,20 @@ void MainWindow::setupProtocolsPageConnections()
|
|||
{
|
||||
QJsonObject openvpnConfig;
|
||||
|
||||
// default buttons
|
||||
// all containers
|
||||
QList<DockerContainer> containers {
|
||||
DockerContainer::OpenVpn,
|
||||
DockerContainer::OpenVpnOverShadowSocks,
|
||||
DockerContainer::OpenVpnOverCloak
|
||||
DockerContainer::OpenVpnOverCloak,
|
||||
DockerContainer::WireGuard
|
||||
};
|
||||
|
||||
// default buttons
|
||||
QList<QPushButton *> defaultButtons {
|
||||
ui->pushButton_proto_openvpn_cont_default,
|
||||
ui->pushButton_proto_ss_openvpn_cont_default,
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default,
|
||||
ui->pushButton_proto_wireguard_cont_default
|
||||
};
|
||||
|
||||
for (int i = 0; i < containers.size(); ++i) {
|
||||
|
@ -1297,7 +1299,8 @@ void MainWindow::setupProtocolsPageConnections()
|
|||
QList<QPushButton *> installButtons {
|
||||
ui->pushButton_proto_openvpn_cont_install,
|
||||
ui->pushButton_proto_ss_openvpn_cont_install,
|
||||
ui->pushButton_proto_cloak_openvpn_cont_install
|
||||
ui->pushButton_proto_cloak_openvpn_cont_install,
|
||||
ui->pushButton_proto_wireguard_cont_install
|
||||
};
|
||||
|
||||
for (int i = 0; i < containers.size(); ++i) {
|
||||
|
@ -1338,7 +1341,8 @@ void MainWindow::setupProtocolsPageConnections()
|
|||
QList<QPushButton *> shareButtons {
|
||||
ui->pushButton_proto_openvpn_cont_share,
|
||||
ui->pushButton_proto_ss_openvpn_cont_share,
|
||||
ui->pushButton_proto_cloak_openvpn_cont_share
|
||||
ui->pushButton_proto_cloak_openvpn_cont_share,
|
||||
ui->pushButton_proto_wireguard_cont_share
|
||||
};
|
||||
|
||||
for (int i = 0; i < containers.size(); ++i) {
|
||||
|
@ -1827,6 +1831,10 @@ void MainWindow::onPushButtonAddCustomSitesClicked()
|
|||
m_vpnConnection->addRoutes(QStringList() << ip);
|
||||
m_vpnConnection->flushDns();
|
||||
}
|
||||
else if (Utils::ipAddressWithSubnetRegExp().exactMatch(newSite)) {
|
||||
m_vpnConnection->addRoutes(QStringList() << newSite);
|
||||
m_vpnConnection->flushDns();
|
||||
}
|
||||
|
||||
updateSitesPage();
|
||||
};
|
||||
|
@ -1961,33 +1969,58 @@ void MainWindow::updateProtocolsPage()
|
|||
ui->progressBar_protocols_container_reinstall->hide();
|
||||
|
||||
auto containers = m_settings.containers(selectedServerIndex);
|
||||
|
||||
DockerContainer defaultContainer = m_settings.defaultContainer(selectedServerIndex);
|
||||
bool haveAuthData = m_settings.haveAuthData(selectedServerIndex);
|
||||
|
||||
DockerContainer defaultContainer = m_settings.defaultContainer(selectedServerIndex);
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default->setChecked(defaultContainer == DockerContainer::OpenVpnOverCloak);
|
||||
ui->pushButton_proto_ss_openvpn_cont_default->setChecked(defaultContainer == DockerContainer::OpenVpnOverShadowSocks);
|
||||
ui->pushButton_proto_openvpn_cont_default->setChecked(defaultContainer == DockerContainer::OpenVpn);
|
||||
// all containers
|
||||
QList<DockerContainer> allContainers {
|
||||
DockerContainer::OpenVpn,
|
||||
DockerContainer::OpenVpnOverShadowSocks,
|
||||
DockerContainer::OpenVpnOverCloak,
|
||||
DockerContainer::WireGuard
|
||||
};
|
||||
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default->setVisible(haveAuthData && containers.contains(DockerContainer::OpenVpnOverCloak));
|
||||
ui->pushButton_proto_ss_openvpn_cont_default->setVisible(haveAuthData && containers.contains(DockerContainer::OpenVpnOverShadowSocks));
|
||||
ui->pushButton_proto_openvpn_cont_default->setVisible(haveAuthData && containers.contains(DockerContainer::OpenVpn));
|
||||
// install buttons
|
||||
QList<QPushButton *> installButtons {
|
||||
ui->pushButton_proto_openvpn_cont_install,
|
||||
ui->pushButton_proto_ss_openvpn_cont_install,
|
||||
ui->pushButton_proto_cloak_openvpn_cont_install,
|
||||
ui->pushButton_proto_wireguard_cont_install
|
||||
};
|
||||
|
||||
ui->pushButton_proto_cloak_openvpn_cont_share->setVisible(haveAuthData && containers.contains(DockerContainer::OpenVpnOverCloak));
|
||||
ui->pushButton_proto_ss_openvpn_cont_share->setVisible(haveAuthData && containers.contains(DockerContainer::OpenVpnOverShadowSocks));
|
||||
ui->pushButton_proto_openvpn_cont_share->setVisible(haveAuthData && containers.contains(DockerContainer::OpenVpn));
|
||||
// default buttons
|
||||
QList<QPushButton *> defaultButtons {
|
||||
ui->pushButton_proto_openvpn_cont_default,
|
||||
ui->pushButton_proto_ss_openvpn_cont_default,
|
||||
ui->pushButton_proto_cloak_openvpn_cont_default,
|
||||
ui->pushButton_proto_wireguard_cont_default
|
||||
};
|
||||
|
||||
ui->pushButton_proto_cloak_openvpn_cont_install->setChecked(containers.contains(DockerContainer::OpenVpnOverCloak));
|
||||
ui->pushButton_proto_ss_openvpn_cont_install->setChecked(containers.contains(DockerContainer::OpenVpnOverShadowSocks));
|
||||
ui->pushButton_proto_openvpn_cont_install->setChecked(containers.contains(DockerContainer::OpenVpn));
|
||||
// share buttons
|
||||
QList<QPushButton *> shareButtons {
|
||||
ui->pushButton_proto_openvpn_cont_share,
|
||||
ui->pushButton_proto_ss_openvpn_cont_share,
|
||||
ui->pushButton_proto_cloak_openvpn_cont_share,
|
||||
ui->pushButton_proto_wireguard_cont_share
|
||||
};
|
||||
|
||||
ui->pushButton_proto_cloak_openvpn_cont_install->setEnabled(haveAuthData);
|
||||
ui->pushButton_proto_ss_openvpn_cont_install->setEnabled(haveAuthData);
|
||||
ui->pushButton_proto_openvpn_cont_install->setEnabled(haveAuthData);
|
||||
// frames
|
||||
QList<QFrame *> frames {
|
||||
ui->frame_openvpn_settings,
|
||||
ui->frame_openvpn_ss_settings,
|
||||
ui->frame_openvpn_ss_cloak_settings,
|
||||
ui->frame_wireguard_settings
|
||||
};
|
||||
|
||||
ui->frame_openvpn_ss_cloak_settings->setVisible(containers.contains(DockerContainer::OpenVpnOverCloak));
|
||||
ui->frame_openvpn_ss_settings->setVisible(containers.contains(DockerContainer::OpenVpnOverShadowSocks));
|
||||
ui->frame_openvpn_settings->setVisible(containers.contains(DockerContainer::OpenVpn));
|
||||
for (int i = 0; i < allContainers.size(); ++i) {
|
||||
defaultButtons.at(i)->setChecked(defaultContainer == allContainers.at(i));
|
||||
defaultButtons.at(i)->setVisible(haveAuthData && containers.contains(allContainers.at(i)));
|
||||
shareButtons.at(i)->setVisible(haveAuthData && containers.contains(allContainers.at(i)));
|
||||
installButtons.at(i)->setChecked(containers.contains(allContainers.at(i)));
|
||||
installButtons.at(i)->setEnabled(haveAuthData);
|
||||
frames.at(i)->setVisible(containers.contains(allContainers.at(i)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateOpenVpnPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData)
|
||||
|
@ -2000,7 +2033,7 @@ void MainWindow::updateOpenVpnPage(const QJsonObject &openvpnConfig, DockerConta
|
|||
ui->radioButton_proto_openvpn_tcp->setEnabled(true);
|
||||
|
||||
ui->lineEdit_proto_openvpn_subnet->setText(openvpnConfig.value(config_key::subnet_address).
|
||||
toString(protocols::vpnDefaultSubnetAddress));
|
||||
toString(protocols::openvpn::defaultSubnetAddress));
|
||||
|
||||
QString trasnsport = openvpnConfig.value(config_key::transport_proto).
|
||||
toString(protocols::openvpn::defaultTransportProto);
|
||||
|
|
|
@ -274,7 +274,7 @@ QPushButton:hover {
|
|||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>13</number>
|
||||
<number>8</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_start">
|
||||
<widget class="QLabel" name="label_25">
|
||||
|
@ -2578,6 +2578,127 @@ border: none;
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_new_server_settings_parent_wireguard">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinAndMaxSize</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_10" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_new_server_wireguard">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>WireGuard</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_new_server_settings_wireguard">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_new_server_settings_wireguard">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_73">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_new_server_wireguard_port">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>185</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>185</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_new_server_2">
|
||||
<property name="orientation">
|
||||
|
@ -5346,6 +5467,161 @@ QPushButton:!checked {
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_wireguard">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinAndMaxSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_74">
|
||||
<property name="text">
|
||||
<string>WireGuard container</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_proto_wireguard_cont_default">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
background: transparent;
|
||||
image: url(:/images/check.png);
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
QPushButton:checked {
|
||||
image: url(:/images/check.png);
|
||||
}
|
||||
QPushButton:!checked {
|
||||
image: url(:/images/uncheck.png);
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_proto_wireguard_cont_share">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background: transparent;
|
||||
image: url(:/images/share.png);
|
||||
padding: 0px;
|
||||
margin: 0px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_proto_wireguard_cont_install">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
background: transparent;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
QPushButton:checked {
|
||||
image: url(:/images/connect_button_connected.png);
|
||||
}
|
||||
QPushButton:!checked {
|
||||
image: url(:/images/connect_button_disconnected.png);
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_wireguard_settings">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_18">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_proto_wireguard_cont_wireguard_config">
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>WireGuard settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -23,11 +23,6 @@ QString Utils::getRandomString(int len)
|
|||
return randomString;
|
||||
}
|
||||
|
||||
QString Utils::defaultVpnConfigFileName()
|
||||
{
|
||||
return configPath() + QString("/%1.ovpn").arg(APPLICATION_NAME);
|
||||
}
|
||||
|
||||
QString Utils::systemLogPath()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -54,11 +49,6 @@ bool Utils::initializePath(const QString& path)
|
|||
return true;
|
||||
}
|
||||
|
||||
QString Utils::configPath()
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/config";
|
||||
}
|
||||
|
||||
bool Utils::createEmptyFile(const QString& path)
|
||||
{
|
||||
QFile f(path);
|
||||
|
|
|
@ -13,8 +13,6 @@ class Utils {
|
|||
public:
|
||||
static QString getRandomString(int len);
|
||||
|
||||
static QString configPath();
|
||||
static QString defaultVpnConfigFileName();
|
||||
static QString executable(const QString& baseName, bool absPath);
|
||||
static QString systemLogPath();
|
||||
static bool createEmptyFile(const QString& path);
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
#include <configurators/openvpn_configurator.h>
|
||||
#include <configurators/cloak_configurator.h>
|
||||
#include <configurators/shadowsocks_configurator.h>
|
||||
#include <configurators/wireguard_configurator.h>
|
||||
#include <core/servercontroller.h>
|
||||
#include <protocols/wireguardprotocol.h>
|
||||
|
||||
#include "ipc.h"
|
||||
#include "core/ipcclient.h"
|
||||
|
@ -43,7 +45,7 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
|||
if (state == VpnProtocol::Connected){
|
||||
IpcClient::Interface()->flushDns();
|
||||
|
||||
if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) {
|
||||
if (m_settings.routeMode() != Settings::VpnAllSites) {
|
||||
IpcClient::Interface()->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0");
|
||||
//qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size();
|
||||
}
|
||||
|
@ -55,6 +57,10 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
|||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), m_settings.getVpnIps(Settings::VpnOnlyForwardSites));
|
||||
}
|
||||
else if (m_settings.routeMode() == Settings::VpnAllExceptSites) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0/1");
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "128.0.0.0/1");
|
||||
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), QStringList() << remoteAddress());
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), m_settings.getVpnIps(Settings::VpnAllExceptSites));
|
||||
}
|
||||
|
||||
|
@ -71,6 +77,11 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
|||
emit connectionStateChanged(state);
|
||||
}
|
||||
|
||||
const QString &VpnConnection::remoteAddress() const
|
||||
{
|
||||
return m_remoteAddress;
|
||||
}
|
||||
|
||||
QSharedPointer<VpnProtocol> VpnConnection::vpnProtocol() const
|
||||
{
|
||||
return m_vpnProtocol;
|
||||
|
@ -159,6 +170,10 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex,
|
|||
configData = ShadowSocksConfigurator::genShadowSocksConfig(credentials,
|
||||
container, containerConfig, &e);
|
||||
}
|
||||
else if (proto == Protocol::WireGuard) {
|
||||
configData = WireguardConfigurator::genWireguardConfig(credentials,
|
||||
container, containerConfig, &e);
|
||||
}
|
||||
|
||||
if (errorCode && e) {
|
||||
*errorCode = e;
|
||||
|
@ -197,7 +212,7 @@ ErrorCode VpnConnection::createVpnConfiguration(int serverIndex,
|
|||
return errorCode;
|
||||
}
|
||||
|
||||
QFile file(Utils::defaultVpnConfigFileName());
|
||||
QFile file(OpenVpnProtocol::defaultConfigFileName());
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
|
||||
QTextStream stream(&file);
|
||||
stream << openVpnConfigData << endl;
|
||||
|
@ -226,6 +241,13 @@ ErrorCode VpnConnection::createVpnConfiguration(int serverIndex,
|
|||
m_vpnConfiguration.insert(config::key_cloak_config_data, cloakConfigData);
|
||||
}
|
||||
|
||||
if (container == DockerContainer::WireGuard) {
|
||||
QString wgConfigData = createVpnConfigurationForProto(
|
||||
serverIndex, credentials, container, containerConfig, Protocol::WireGuard, &errorCode);
|
||||
|
||||
m_vpnConfiguration.insert(config::key_wireguard_config_data, wgConfigData);
|
||||
}
|
||||
|
||||
//qDebug().noquote() << "VPN config" << QJsonDocument(m_vpnConfiguration).toJson();
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
@ -233,11 +255,15 @@ ErrorCode VpnConnection::createVpnConfiguration(int serverIndex,
|
|||
ErrorCode VpnConnection::connectToVpn(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig)
|
||||
{
|
||||
qDebug() << "СonnectToVpn, Route mode is" << m_settings.routeMode();
|
||||
qDebug() << QString("СonnectToVpn, Server index is %1, container is %2, route mode is")
|
||||
.arg(serverIndex).arg(containerToString(container)) << m_settings.routeMode();
|
||||
m_remoteAddress = credentials.hostName;
|
||||
|
||||
emit connectionStateChanged(VpnProtocol::Connecting);
|
||||
|
||||
ServerController::setupServerFirewall(credentials);
|
||||
if (credentials.isValid()) {
|
||||
ServerController::setupServerFirewall(credentials);
|
||||
}
|
||||
|
||||
if (m_vpnProtocol) {
|
||||
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
|
@ -287,6 +313,15 @@ ErrorCode VpnConnection::connectToVpn(int serverIndex,
|
|||
return e;
|
||||
}
|
||||
}
|
||||
else if (container == DockerContainer::WireGuard) {
|
||||
ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::WireGuard, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
}
|
||||
|
||||
m_vpnProtocol.reset(new WireguardProtocol(m_vpnConfiguration));
|
||||
}
|
||||
|
||||
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(VpnProtocol::ConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::ConnectionState)));
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
void deleteRoutes(const QStringList &ips);
|
||||
void flushDns();
|
||||
|
||||
const QString &remoteAddress() const;
|
||||
|
||||
signals:
|
||||
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
void connectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
|
@ -66,6 +68,7 @@ private:
|
|||
Settings m_settings;
|
||||
QJsonObject m_vpnConfiguration;
|
||||
QJsonObject m_routeMode;
|
||||
QString m_remoteAddress;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -29,12 +29,14 @@ class IpcProcessInterface
|
|||
SLOT( setProgram(const QString &program) );
|
||||
SLOT( setWorkingDirectory(const QString &dir) );
|
||||
|
||||
SLOT( QByteArray readAll() );
|
||||
SLOT( QByteArray readAllStandardError() );
|
||||
SLOT( QByteArray readAllStandardOutput() );
|
||||
|
||||
|
||||
SIGNAL( errorOccurred(QProcess::ProcessError error) );
|
||||
SIGNAL( finished(int exitCode, QProcess::ExitStatus exitStatus) );
|
||||
SIGNAL( readyRead() );
|
||||
SIGNAL( readyReadStandardError() );
|
||||
SIGNAL( readyReadStandardOutput() );
|
||||
SIGNAL( started() );
|
||||
|
|
|
@ -7,6 +7,7 @@ IpcServerProcess::IpcServerProcess(QObject *parent) :
|
|||
{
|
||||
connect(m_process.data(), &QProcess::errorOccurred, this, &IpcServerProcess::errorOccurred);
|
||||
connect(m_process.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &IpcServerProcess::finished);
|
||||
connect(m_process.data(), &QProcess::readyRead, this, &IpcServerProcess::readyRead);
|
||||
connect(m_process.data(), &QProcess::readyReadStandardError, this, &IpcServerProcess::readyReadStandardError);
|
||||
connect(m_process.data(), &QProcess::readyReadStandardOutput, this, &IpcServerProcess::readyReadStandardOutput);
|
||||
connect(m_process.data(), &QProcess::started, this, &IpcServerProcess::started);
|
||||
|
@ -88,6 +89,11 @@ void IpcServerProcess::setWorkingDirectory(const QString &dir)
|
|||
m_process->setWorkingDirectory(dir);
|
||||
}
|
||||
|
||||
QByteArray IpcServerProcess::readAll()
|
||||
{
|
||||
return m_process->readAll();
|
||||
}
|
||||
|
||||
QByteArray IpcServerProcess::readAllStandardError()
|
||||
{
|
||||
return m_process->readAllStandardError();
|
||||
|
|
|
@ -23,6 +23,7 @@ public:
|
|||
void setProgram(const QString &program) override;
|
||||
void setWorkingDirectory(const QString &dir) override;
|
||||
|
||||
QByteArray readAll() override;
|
||||
QByteArray readAllStandardError() override;
|
||||
QByteArray readAllStandardOutput() override;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue