From caad670dbfa4f21b74bb8563f9673550909132b0 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 28 Feb 2023 17:16:38 +0300 Subject: [PATCH] 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;