Files
amnezia-client/client/protocols/wireguardprotocol.cpp
T

283 lines
8.8 KiB
C++
Raw Normal View History

2021-06-12 11:59:36 +03:00
#include <QCoreApplication>
#include <QFileInfo>
#include <QProcess>
#include <QTcpSocket>
#include <QThread>
2022-12-28 13:41:45 +03:00
#include "logger.h"
2021-06-12 11:59:36 +03:00
#include "wireguardprotocol.h"
#include "utilities.h"
2021-06-12 11:59:36 +03:00
2023-07-15 14:19:48 -07:00
#include "mozilla/localsocketcontroller.h"
WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject* parent) : VpnProtocol(configuration, parent)
2021-06-12 11:59:36 +03:00
{
m_configFile.setFileName(QDir::tempPath() + QDir::separator() + serviceName() + ".conf");
2023-01-24 09:43:12 +03:00
writeWireguardConfiguration(configuration);
2023-07-15 14:19:48 -07:00
// MZ
#if defined(MZ_LINUX)
//m_impl.reset(new LinuxController());
#elif defined(MZ_MACOS) // || defined(MZ_WINDOWS)
m_impl.reset(new LocalSocketController());
connect(m_impl.get(), &ControllerImpl::connected, this, [this](const QString& pubkey, const QDateTime& connectionTimestamp) {
emit connectionStateChanged(VpnProtocol::Connected);
});
connect(m_impl.get(), &ControllerImpl::disconnected, this, [this](){
emit connectionStateChanged(VpnProtocol::Disconnected);
});
m_impl->initialize(nullptr, nullptr);
#endif
2021-06-12 11:59:36 +03:00
}
WireguardProtocol::~WireguardProtocol()
{
WireguardProtocol::stop();
QThread::msleep(200);
}
void WireguardProtocol::stop()
{
2023-07-15 14:19:48 -07:00
#ifdef Q_OS_MAC
stopMzImpl();
return;
#endif
2022-08-10 22:15:00 +03:00
if (!QFileInfo::exists(Utils::wireguardExecPath())) {
2021-06-12 11:59:36 +03:00
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;
}
2022-08-10 22:15:00 +03:00
m_wireguardStopProcess->setProgram(PermittedProcess::Wireguard);
2021-06-12 11:59:36 +03:00
m_wireguardStopProcess->setArguments(stopArgs());
qDebug() << stopArgs().join(" ");
2021-06-12 11:59:36 +03:00
2021-11-19 19:02:39 +03:00
connect(m_wireguardStopProcess.data(), &PrivilegedProcess::errorOccurred, this, [this](QProcess::ProcessError error) {
qDebug() << "WireguardProtocol::WireguardProtocol Stop errorOccurred" << error;
2021-11-30 21:51:06 +03:00
setConnectionState(VpnConnectionState::Disconnected);
2021-06-12 11:59:36 +03:00
});
2021-11-19 19:02:39 +03:00
connect(m_wireguardStopProcess.data(), &PrivilegedProcess::stateChanged, this, [this](QProcess::ProcessState newState) {
2021-06-12 11:59:36 +03:00
qDebug() << "WireguardProtocol::WireguardProtocol Stop stateChanged" << newState;
});
#ifdef Q_OS_LINUX
if (IpcClient::Interface()) {
QRemoteObjectPendingReply<bool> result = IpcClient::Interface()->isWireguardRunning();
if (result.returnValue()) {
setConnectionState(VpnProtocol::Disconnected);
return;
}
} else {
qCritical() << "IPC client not initialized";
setConnectionState(VpnProtocol::Disconnected);
return;
}
#endif
2021-06-12 11:59:36 +03:00
m_wireguardStopProcess->start();
2021-11-19 19:02:39 +03:00
m_wireguardStopProcess->waitForFinished(10000);
2021-06-12 11:59:36 +03:00
setConnectionState(VpnProtocol::Disconnected);
}
2023-07-15 14:19:48 -07:00
#ifdef Q_OS_MAC
ErrorCode WireguardProtocol::startMzImpl()
{
m_impl->activate(m_rawConfig);
return ErrorCode::NoError;
}
ErrorCode WireguardProtocol::stopMzImpl()
{
m_impl->deactivate();
return ErrorCode::NoError;
}
#endif
2023-01-24 09:43:12 +03:00
void WireguardProtocol::writeWireguardConfiguration(const QJsonObject &configuration)
2021-06-12 11:59:36 +03:00
{
2021-11-30 21:51:06 +03:00
QJsonObject jConfig = configuration.value(ProtocolProps::key_proto_config_data(Proto::WireGuard)).toObject();
2021-06-12 11:59:36 +03:00
2021-10-05 12:22:13 +03:00
if (!m_configFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qCritical() << "Failed to save wireguard config to" << m_configFile.fileName();
return;
}
2021-06-12 11:59:36 +03:00
2021-10-05 12:22:13 +03:00
m_configFile.write(jConfig.value(config_key::config).toString().toUtf8());
m_configFile.close();
#ifdef Q_OS_LINUX
if (IpcClient::Interface()) {
QRemoteObjectPendingReply<bool> 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
2021-10-05 12:22:13 +03:00
m_configFileName = m_configFile.fileName();
#endif
m_isConfigLoaded = true;
2021-06-12 11:59:36 +03:00
qDebug().noquote() << QString("Set config data") << configPath();
2021-11-30 21:51:06 +03:00
qDebug().noquote() << QString("Set config data") << configuration.value(ProtocolProps::key_proto_config_data(Proto::WireGuard)).toString().toUtf8();
2021-06-12 11:59:36 +03:00
}
QString WireguardProtocol::configPath() const
{
return m_configFileName;
}
void WireguardProtocol::updateRouteGateway(QString line)
{
// TODO: fix for macos
line = line.split("ROUTE_GATEWAY", Qt::SkipEmptyParts).at(1);
2021-06-12 11:59:36 +03:00
if (!line.contains("/")) return;
m_routeGateway = line.split("/", Qt::SkipEmptyParts).first();
2021-06-12 11:59:36 +03:00
m_routeGateway.replace(" ", "");
qDebug() << "Set VPN route gateway" << m_routeGateway;
}
ErrorCode WireguardProtocol::start()
{
if (!m_isConfigLoaded) {
setLastError(ErrorCode::ConfigMissing);
return lastError();
}
2023-07-15 14:19:48 -07:00
#ifdef Q_OS_MAC
return startMzImpl();
#endif
2021-06-12 11:59:36 +03:00
2022-08-10 22:15:00 +03:00
if (!QFileInfo::exists(Utils::wireguardExecPath())) {
2021-06-12 11:59:36 +03:00
setLastError(ErrorCode::ExecutableMissing);
return lastError();
}
if (IpcClient::Interface()) {
QRemoteObjectPendingReply<bool> result = IpcClient::Interface()->isWireguardConfigExists(configPath());
if (result.returnValue()) {
setLastError(ErrorCode::ConfigMissing);
return lastError();
}
} else {
qCritical() << "IPC client not initialized";
setLastError(ErrorCode::InternalError);
return lastError();
}
2021-06-12 11:59:36 +03:00
2021-11-30 21:51:06 +03:00
setConnectionState(VpnConnectionState::Connecting);
2021-06-12 11:59:36 +03:00
m_wireguardStartProcess = IpcClient::CreatePrivilegedProcess();
if (!m_wireguardStartProcess) {
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;
}
2022-08-10 22:15:00 +03:00
m_wireguardStartProcess->setProgram(PermittedProcess::Wireguard);
2021-06-12 11:59:36 +03:00
m_wireguardStartProcess->setArguments(startArgs());
qDebug() << startArgs().join(" ");
2021-06-12 11:59:36 +03:00
2021-11-19 19:02:39 +03:00
connect(m_wireguardStartProcess.data(), &PrivilegedProcess::errorOccurred, this, [this](QProcess::ProcessError error) {
2021-06-12 11:59:36 +03:00
qDebug() << "WireguardProtocol::WireguardProtocol errorOccurred" << error;
2021-11-30 21:51:06 +03:00
setConnectionState(VpnConnectionState::Disconnected);
2021-06-12 11:59:36 +03:00
});
2021-11-19 19:02:39 +03:00
connect(m_wireguardStartProcess.data(), &PrivilegedProcess::stateChanged, this, [this](QProcess::ProcessState newState) {
2021-06-12 11:59:36 +03:00
qDebug() << "WireguardProtocol::WireguardProtocol stateChanged" << newState;
});
2021-11-19 19:02:39 +03:00
connect(m_wireguardStartProcess.data(), &PrivilegedProcess::finished, this, [this]() {
2021-11-30 21:51:06 +03:00
setConnectionState(VpnConnectionState::Connected);
2021-06-12 11:59:36 +03:00
});
2021-11-19 19:02:39 +03:00
connect(m_wireguardStartProcess.data(), &PrivilegedProcess::readyRead, this, [this]() {
2021-06-12 11:59:36 +03:00
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAll();
reply.waitForFinished(1000);
qDebug() << "WireguardProtocol::WireguardProtocol readyRead" << reply.returnValue();
});
2021-11-19 19:02:39 +03:00
connect(m_wireguardStartProcess.data(), &PrivilegedProcess::readyReadStandardOutput, this, [this]() {
2021-06-12 11:59:36 +03:00
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAllStandardOutput();
reply.waitForFinished(1000);
qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardOutput" << reply.returnValue();
});
2021-11-19 19:02:39 +03:00
connect(m_wireguardStartProcess.data(), &PrivilegedProcess::readyReadStandardError, this, [this]() {
2021-06-12 11:59:36 +03:00
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAllStandardError();
reply.waitForFinished(10);
2021-06-12 11:59:36 +03:00
qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardError" << reply.returnValue();
});
m_wireguardStartProcess->start();
2021-11-19 19:02:39 +03:00
m_wireguardStartProcess->waitForFinished(10000);
2021-06-12 11:59:36 +03:00
return ErrorCode::NoError;
}
void WireguardProtocol::updateVpnGateway(const QString &line)
{
2023-07-15 14:19:48 -07:00
2021-06-12 11:59:36 +03:00
}
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
2023-07-15 14:19:48 -07:00
return {};
#endif
}
QStringList WireguardProtocol::startArgs()
{
#ifdef Q_OS_WIN
return {"--add", configPath()};
#elif defined Q_OS_LINUX
return {"up", "wg99"};
#else
2023-07-15 14:19:48 -07:00
return {};
#endif
}