From caad670dbfa4f21b74bb8563f9673550909132b0 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 28 Feb 2023 17:16:38 +0300 Subject: [PATCH 1/3] added wireguard connection implementation for Linux --- client/protocols/wireguardprotocol.cpp | 107 ++++++++++++++++++------- client/protocols/wireguardprotocol.h | 4 +- client/utilities.cpp | 2 +- ipc/ipc.h | 7 +- ipc/ipc_interface.rep | 3 + ipc/ipcserver.cpp | 45 +++++++++++ ipc/ipcserver.h | 2 + 7 files changed, 133 insertions(+), 37 deletions(-) diff --git a/client/protocols/wireguardprotocol.cpp b/client/protocols/wireguardprotocol.cpp index 224d5176..b348e816 100644 --- a/client/protocols/wireguardprotocol.cpp +++ b/client/protocols/wireguardprotocol.cpp @@ -9,7 +9,7 @@ #include "utilities.h" WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject* parent) : - VpnProtocol(configuration, parent) + VpnProtocol(configuration, parent) { m_configFile.setFileName(QDir::tempPath() + QDir::separator() + serviceName() + ".conf"); writeWireguardConfiguration(configuration); @@ -47,11 +47,8 @@ void WireguardProtocol::stop() m_wireguardStopProcess->setProgram(PermittedProcess::Wireguard); - - QStringList arguments({"--remove", configPath()}); - m_wireguardStopProcess->setArguments(arguments); - - qDebug() << arguments.join(" "); + m_wireguardStopProcess->setArguments(stopArgs()); + qDebug() << stopArgs().join(" "); connect(m_wireguardStopProcess.data(), &PrivilegedProcess::errorOccurred, this, [this](QProcess::ProcessError error) { qDebug() << "WireguardProtocol::WireguardProtocol Stop errorOccurred" << error; @@ -62,12 +59,25 @@ void WireguardProtocol::stop() qDebug() << "WireguardProtocol::WireguardProtocol Stop stateChanged" << newState; }); +#ifdef Q_OS_LINUX + if (IpcClient::Interface()) { + QRemoteObjectPendingReply result = IpcClient::Interface()->isWireguardRunning(); + if (result.returnValue()) { + setConnectionState(VpnProtocol::Disconnected); + return; + } + } else { + qCritical() << "IPC client not initialized"; + setConnectionState(VpnProtocol::Disconnected); + return; + } +#endif + m_wireguardStopProcess->start(); m_wireguardStopProcess->waitForFinished(10000); setConnectionState(VpnProtocol::Disconnected); #endif - } void WireguardProtocol::writeWireguardConfiguration(const QJsonObject &configuration) @@ -79,13 +89,28 @@ void WireguardProtocol::writeWireguardConfiguration(const QJsonObject &configura return; } - m_isConfigLoaded = true; - m_configFile.write(jConfig.value(config_key::config).toString().toUtf8()); m_configFile.close(); - m_configFileName = m_configFile.fileName(); - qDebug().noquote() << QString("Set config data") << m_configFileName; +#ifdef Q_OS_LINUX + if (IpcClient::Interface()) { + QRemoteObjectPendingReply result = IpcClient::Interface()->copyWireguardConfig(m_configFile.fileName()); + if (result.returnValue()) { + qCritical() << "Failed to copy wireguard config"; + return; + } + } else { + qCritical() << "IPC client not initialized"; + return; + } + m_configFileName = "/etc/wireguard/wg99.conf"; +#else + m_configFileName = m_configFile.fileName(); +#endif + + m_isConfigLoaded = true; + + qDebug().noquote() << QString("Set config data") << configPath(); qDebug().noquote() << QString("Set config data") << configuration.value(ProtocolProps::key_proto_config_data(Proto::WireGuard)).toString().toUtf8(); } @@ -120,10 +145,10 @@ ErrorCode WireguardProtocol::start() return lastError(); } - if (!QFileInfo::exists(configPath())) { - setLastError(ErrorCode::ConfigMissing); - return lastError(); - } + // if (!QFileInfo::exists(configPath())) { + // setLastError(ErrorCode::ConfigMissing); + // return lastError(); + // } setConnectionState(VpnConnectionState::Connecting); @@ -143,11 +168,8 @@ ErrorCode WireguardProtocol::start() m_wireguardStartProcess->setProgram(PermittedProcess::Wireguard); - - QStringList arguments({"--add", configPath()}); - m_wireguardStartProcess->setArguments(arguments); - - qDebug() << arguments.join(" "); + m_wireguardStartProcess->setArguments(startArgs()); + qDebug() << startArgs().join(" "); connect(m_wireguardStartProcess.data(), &PrivilegedProcess::errorOccurred, this, [this](QProcess::ProcessError error) { qDebug() << "WireguardProtocol::WireguardProtocol errorOccurred" << error; @@ -191,19 +213,19 @@ ErrorCode WireguardProtocol::start() 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' + // // 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); + // 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()); -// } -// } + // qDebug() << QString("Set vpn local address %1, gw %2").arg(m_vpnLocalAddress).arg(vpnGateway()); + // } + // } // } } @@ -211,3 +233,26 @@ QString WireguardProtocol::serviceName() const { return "AmneziaVPN.WireGuard0"; } + +QStringList WireguardProtocol::stopArgs() +{ +#ifdef Q_OS_WIN + return {"--remove", configPath()}; +#elif defined Q_OS_LINUX + return {"down", "wg99"}; +#else + return {"--remove", configPath()}; +#endif +} + +QStringList WireguardProtocol::startArgs() +{ +#ifdef Q_OS_WIN + return {"--add", configPath()}; +#elif defined Q_OS_LINUX + return {"up", "wg99"}; +#else + return {"--add", configPath()}; +#endif +} + diff --git a/client/protocols/wireguardprotocol.h b/client/protocols/wireguardprotocol.h index 7a50b0d3..59fa39fa 100644 --- a/client/protocols/wireguardprotocol.h +++ b/client/protocols/wireguardprotocol.h @@ -28,7 +28,8 @@ private: void updateRouteGateway(QString line); void updateVpnGateway(const QString &line); QString serviceName() const; - + QStringList stopArgs(); + QStringList startArgs(); private: QString m_configFileName; @@ -36,6 +37,7 @@ private: QSharedPointer m_wireguardStartProcess; QSharedPointer m_wireguardStopProcess; + IpcClient *m_ipcClient; bool m_isConfigLoaded = false; diff --git a/client/utilities.cpp b/client/utilities.cpp index dc17e33f..0d582059 100644 --- a/client/utilities.cpp +++ b/client/utilities.cpp @@ -231,7 +231,7 @@ QString Utils::wireguardExecPath() #ifdef Q_OS_WIN return Utils::executable("wireguard/wireguard-service", true); #elif defined Q_OS_LINUX - return Utils::usrExecutable("wg"); + return Utils::usrExecutable("wg-quick"); #else return Utils::executable("/wireguard", true); #endif diff --git a/ipc/ipc.h b/ipc/ipc.h index e867c063..cb6a1088 100644 --- a/ipc/ipc.h +++ b/ipc/ipc.h @@ -20,13 +20,12 @@ inline QString permittedProcessPath(PermittedProcess pid) { if (pid == PermittedProcess::OpenVPN) { return Utils::openVpnExecPath(); - } - if (pid == PermittedProcess::Wireguard) { + } else if (pid == PermittedProcess::Wireguard) { return Utils::wireguardExecPath(); - } - else if (pid == PermittedProcess::CertUtil) { + } else if (pid == PermittedProcess::CertUtil) { return Utils::certUtilPath(); } + return ""; } diff --git a/ipc/ipc_interface.rep b/ipc/ipc_interface.rep index 2c9f4746..826cd7f8 100644 --- a/ipc/ipc_interface.rep +++ b/ipc/ipc_interface.rep @@ -18,5 +18,8 @@ class IpcInterface SLOT( void cleanUp() ); SLOT( void setLogsEnabled(bool enabled) ); + + SLOT( bool copyWireguardConfig(const QString &sourcePath) ); + SLOT( bool isWireguardRunning() ); }; diff --git a/ipc/ipcserver.cpp b/ipc/ipcserver.cpp index 3d248b84..de5ed582 100644 --- a/ipc/ipcserver.cpp +++ b/ipc/ipcserver.cpp @@ -124,3 +124,48 @@ void IpcServer::setLogsEnabled(bool enabled) Logger::deinit(); } } + +bool IpcServer::copyWireguardConfig(const QString &sourcePath) +{ +#ifdef Q_OS_LINUX + QProcess copyWireguardConfigProcess; + + bool errorOccurred = false; + + connect(©WireguardConfigProcess, &QProcess::errorOccurred, this, [&errorOccurred](QProcess::ProcessError error) { + qDebug() << "WireguardProtocol::WireguardProtocol error occured while copying wireguard config: " << error; + errorOccurred = true; + }); + + copyWireguardConfigProcess.setProgram("/bin/cp"); + copyWireguardConfigProcess.setArguments(QStringList{sourcePath, "/etc/wireguard/wg99.conf"}); + copyWireguardConfigProcess.start(); + copyWireguardConfigProcess.waitForFinished(10000); + return errorOccurred; +#else + return false; +#endif +} + +bool IpcServer::isWireguardRunning() +{ +#ifdef Q_OS_LINUX + QProcess checkWireguardStatusProcess; + + connect(&checkWireguardStatusProcess, &QProcess::errorOccurred, this, [](QProcess::ProcessError error) { + qDebug() << "WireguardProtocol::WireguardProtocol error occured while checking wireguard status: " << error; + }); + + checkWireguardStatusProcess.setProgram("/bin/wg"); + checkWireguardStatusProcess.setArguments(QStringList{"show"}); + checkWireguardStatusProcess.start(); + checkWireguardStatusProcess.waitForFinished(10000); + QString output = checkWireguardStatusProcess.readAllStandardOutput(); + if (!output.isEmpty()) { + return true; + } + return false; +#else + return false; +#endif +} diff --git a/ipc/ipcserver.h b/ipc/ipcserver.h index a5b52ed1..d4ad139c 100644 --- a/ipc/ipcserver.h +++ b/ipc/ipcserver.h @@ -25,6 +25,8 @@ public: virtual QStringList getTapList() override; virtual void cleanUp() override; virtual void setLogsEnabled(bool enabled) override; + virtual bool copyWireguardConfig(const QString &sourcePath) override; + virtual bool isWireguardRunning() override; private: int m_localpid = 0; From 8f189337136bf5cf3a3ed7986f56a90a7599b300 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Thu, 2 Mar 2023 16:19:20 +0300 Subject: [PATCH 2/3] moved the function of checking the availability of wireguard config to ipc client --- client/protocols/wireguardprotocol.cpp | 44 +++++++++++++++----------- ipc/ipc_interface.rep | 1 + ipc/ipcserver.cpp | 6 ++++ ipc/ipcserver.h | 1 + 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/client/protocols/wireguardprotocol.cpp b/client/protocols/wireguardprotocol.cpp index b348e816..666bf80d 100644 --- a/client/protocols/wireguardprotocol.cpp +++ b/client/protocols/wireguardprotocol.cpp @@ -8,8 +8,7 @@ #include "wireguardprotocol.h" #include "utilities.h" -WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject* parent) : - VpnProtocol(configuration, parent) +WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject* parent) : VpnProtocol(configuration, parent) { m_configFile.setFileName(QDir::tempPath() + QDir::separator() + serviceName() + ".conf"); writeWireguardConfiguration(configuration); @@ -145,10 +144,17 @@ ErrorCode WireguardProtocol::start() return lastError(); } - // if (!QFileInfo::exists(configPath())) { - // setLastError(ErrorCode::ConfigMissing); - // return lastError(); - // } + if (IpcClient::Interface()) { + QRemoteObjectPendingReply result = IpcClient::Interface()->isWireguardConfigExists(configPath()); + if (result.returnValue()) { + setLastError(ErrorCode::ConfigMissing); + return lastError(); + } + } else { + qCritical() << "IPC client not initialized"; + setLastError(ErrorCode::InternalError); + return lastError(); + } setConnectionState(VpnConnectionState::Connecting); @@ -198,7 +204,7 @@ ErrorCode WireguardProtocol::start() connect(m_wireguardStartProcess.data(), &PrivilegedProcess::readyReadStandardError, this, [this]() { QRemoteObjectPendingReply reply = m_wireguardStartProcess->readAllStandardError(); - reply.waitForFinished(1000); + reply.waitForFinished(10); qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardError" << reply.returnValue(); }); @@ -213,20 +219,20 @@ ErrorCode WireguardProtocol::start() 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' +// // 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); +// 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()); - // } - // } - // } +// qDebug() << QString("Set vpn local address %1, gw %2").arg(m_vpnLocalAddress).arg(vpnGateway()); +// } +// } +// } } QString WireguardProtocol::serviceName() const diff --git a/ipc/ipc_interface.rep b/ipc/ipc_interface.rep index 826cd7f8..8970f7c8 100644 --- a/ipc/ipc_interface.rep +++ b/ipc/ipc_interface.rep @@ -21,5 +21,6 @@ class IpcInterface SLOT( bool copyWireguardConfig(const QString &sourcePath) ); SLOT( bool isWireguardRunning() ); + SLOT( bool isWireguardConfigExists(const QString &configPath) ); }; diff --git a/ipc/ipcserver.cpp b/ipc/ipcserver.cpp index de5ed582..c872e6ab 100644 --- a/ipc/ipcserver.cpp +++ b/ipc/ipcserver.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "router.h" #include "logger.h" @@ -169,3 +170,8 @@ bool IpcServer::isWireguardRunning() return false; #endif } + +bool IpcServer::isWireguardConfigExists(const QString &configPath) +{ + return QFileInfo::exists(configPath); +} diff --git a/ipc/ipcserver.h b/ipc/ipcserver.h index d4ad139c..d5706784 100644 --- a/ipc/ipcserver.h +++ b/ipc/ipcserver.h @@ -27,6 +27,7 @@ public: virtual void setLogsEnabled(bool enabled) override; virtual bool copyWireguardConfig(const QString &sourcePath) override; virtual bool isWireguardRunning() override; + virtual bool isWireguardConfigExists(const QString &configPath) override; private: int m_localpid = 0; From 9962bac50bba714e9f37591edeb2756efd7708c8 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Sun, 19 Mar 2023 17:05:48 +0300 Subject: [PATCH 3/3] changed using cp to QFile to copy wireguard config --- client/protocols/wireguardprotocol.h | 1 - ipc/ipcserver.cpp | 23 ++++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/client/protocols/wireguardprotocol.h b/client/protocols/wireguardprotocol.h index 59fa39fa..880417b4 100644 --- a/client/protocols/wireguardprotocol.h +++ b/client/protocols/wireguardprotocol.h @@ -37,7 +37,6 @@ private: QSharedPointer m_wireguardStartProcess; QSharedPointer m_wireguardStopProcess; - IpcClient *m_ipcClient; bool m_isConfigLoaded = false; diff --git a/ipc/ipcserver.cpp b/ipc/ipcserver.cpp index c872e6ab..ddbc646c 100644 --- a/ipc/ipcserver.cpp +++ b/ipc/ipcserver.cpp @@ -129,20 +129,17 @@ void IpcServer::setLogsEnabled(bool enabled) bool IpcServer::copyWireguardConfig(const QString &sourcePath) { #ifdef Q_OS_LINUX - QProcess copyWireguardConfigProcess; + const QString wireguardConfigPath = "/etc/wireguard/wg99.conf"; + if (QFile::exists(wireguardConfigPath)) + { + QFile::remove(wireguardConfigPath); + } - bool errorOccurred = false; - - connect(©WireguardConfigProcess, &QProcess::errorOccurred, this, [&errorOccurred](QProcess::ProcessError error) { - qDebug() << "WireguardProtocol::WireguardProtocol error occured while copying wireguard config: " << error; - errorOccurred = true; - }); - - copyWireguardConfigProcess.setProgram("/bin/cp"); - copyWireguardConfigProcess.setArguments(QStringList{sourcePath, "/etc/wireguard/wg99.conf"}); - copyWireguardConfigProcess.start(); - copyWireguardConfigProcess.waitForFinished(10000); - return errorOccurred; + if (!QFile::copy(sourcePath, wireguardConfigPath)) { + qDebug() << "WireguardProtocol::WireguardProtocol error occured while copying wireguard config:"; + return false; + } + return true; #else return false; #endif