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

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