Wireguard protocol + refactoring

This commit is contained in:
pokamest 2021-06-12 11:59:36 +03:00
parent 8bdfe1741a
commit 2f6fb0d557
41 changed files with 1245 additions and 152 deletions

View file

@ -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 \

View file

@ -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)
{

View file

@ -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);

View 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;
}

View 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

View 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;
}

View 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

View file

@ -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";
}

View file

@ -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();
});
}

View file

@ -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");
}
}

View file

@ -23,7 +23,8 @@ enum ProtocolScriptType {
run_container,
configure_container,
container_startup,
openvpn_template
openvpn_template,
wireguard_template
};

View file

@ -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}});

View file

@ -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());

View file

@ -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

View file

@ -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());

View file

@ -22,6 +22,8 @@ public:
void stop() override;
ErrorCode checkAndSetupTapDriver();
static QString defaultConfigFileName();
static QString defaultConfigPath();
protected slots:
void onReadyReadDataFromManagementServer();

View file

@ -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

View 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";
}

View 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

View file

@ -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>

View file

@ -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\

View file

@ -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

View file

@ -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\

View file

@ -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

View file

@ -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\

View file

@ -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

View 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 [ "" ]

View 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'

View 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"

View 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

View 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

View file

@ -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;

View file

@ -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);

View file

@ -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">

View file

@ -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);

View file

@ -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);

View file

@ -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)));

View file

@ -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;
};

View file

@ -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() );

View file

@ -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();

View file

@ -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;