diff --git a/client/configurators/wireguard_configurator.cpp b/client/configurators/wireguard_configurator.cpp index 1bca973d..69699998 100644 --- a/client/configurators/wireguard_configurator.cpp +++ b/client/configurators/wireguard_configurator.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -19,13 +20,17 @@ #include "settings.h" #include "utilities.h" -WireguardConfigurator::WireguardConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, - bool isAwg, QObject *parent) +WireguardConfigurator::WireguardConfigurator(std::shared_ptr settings, + const QSharedPointer &serverController, bool isAwg, + QObject *parent) : ConfiguratorBase(settings, serverController, parent), m_isAwg(isAwg) { - m_serverConfigPath = m_isAwg ? amnezia::protocols::awg::serverConfigPath : amnezia::protocols::wireguard::serverConfigPath; - m_serverPublicKeyPath = m_isAwg ? amnezia::protocols::awg::serverPublicKeyPath : amnezia::protocols::wireguard::serverPublicKeyPath; - m_serverPskKeyPath = m_isAwg ? amnezia::protocols::awg::serverPskKeyPath : amnezia::protocols::wireguard::serverPskKeyPath; + m_serverConfigPath = + m_isAwg ? amnezia::protocols::awg::serverConfigPath : amnezia::protocols::wireguard::serverConfigPath; + m_serverPublicKeyPath = + m_isAwg ? amnezia::protocols::awg::serverPublicKeyPath : amnezia::protocols::wireguard::serverPublicKeyPath; + m_serverPskKeyPath = + m_isAwg ? amnezia::protocols::awg::serverPskKeyPath : amnezia::protocols::wireguard::serverPskKeyPath; m_configTemplate = m_isAwg ? ProtocolScriptType::awg_template : ProtocolScriptType::wireguard_template; m_protocolName = m_isAwg ? config_key::awg : config_key::wireguard; @@ -63,9 +68,31 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys() return connData; } +QList WireguardConfigurator::getIpsFromConf(const QString &input) +{ + QRegularExpression regex("AllowedIPs = (\\d+\\.\\d+\\.\\d+\\.\\d+)"); + QRegularExpressionMatchIterator matchIterator = regex.globalMatch(input); + + QList ips; + + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + const QString address_string { match.captured(1) }; + const QHostAddress address { address_string }; + if (address.isNull()) { + qWarning() << "Couldn't recognize the ip address: " << address_string; + } else { + ips << address; + } + } + + return ips; +} + WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode &errorCode) + const QJsonObject &containerConfig, + ErrorCode &errorCode) { WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys(); connData.host = credentials.hostName; @@ -76,65 +103,45 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon return connData; } - // Get list of already created clients (only IP addresses) - QString nextIpNumber; - { - QString script = QString("cat %1 | grep AllowedIPs").arg(m_serverConfigPath); - QString stdOut; - auto cbReadStdOut = [&](const QString &data, libssh::Client &) { - stdOut += data + "\n"; - return ErrorCode::NoError; - }; + QString getIpsScript = QString("cat %1 | grep AllowedIPs").arg(m_serverConfigPath); + QString stdOut; + auto cbReadStdOut = [&](const QString &data, libssh::Client &) { + stdOut += data + "\n"; + return ErrorCode::NoError; + }; - errorCode = m_serverController->runContainerScript(credentials, container, script, cbReadStdOut); - if (errorCode != ErrorCode::NoError) { - return connData; - } + errorCode = m_serverController->runContainerScript(credentials, container, getIpsScript, cbReadStdOut); + if (errorCode != ErrorCode::NoError) { + return connData; + } + auto ips = getIpsFromConf(stdOut); - stdOut.replace("AllowedIPs = ", ""); - stdOut.replace("/32", ""); - QStringList ips = stdOut.split("\n", Qt::SkipEmptyParts); - - // remove extra IPs from each line for case when user manually edited the wg0.conf - // and added there more IPs for route his itnernal networks, like: - // ... - // AllowedIPs = 10.8.1.6/32, 192.168.1.0/24, 192.168.2.0/24, ... - // ... - // without this code - next IP would be 1 if last item in 'ips' has format above - QStringList vpnIps; - for (const auto &ip : ips) { - vpnIps.append(ip.split(",", Qt::SkipEmptyParts).first().trimmed()); - } - ips = vpnIps; - - // Calc next IP address - if (ips.isEmpty()) { - nextIpNumber = "2"; + QHostAddress nextIp = [&] { + QHostAddress result; + QHostAddress lastIp; + if (ips.empty()) { + lastIp.setAddress(containerConfig.value(m_protocolName) + .toObject() + .value(config_key::subnet_address) + .toString(protocols::wireguard::defaultSubnetAddress)); } else { - int next = ips.last().split(".").last().toInt() + 1; - if (next > 254) { - errorCode = ErrorCode::AddressPoolError; - return connData; - } - nextIpNumber = QString::number(next); + lastIp = ips.last(); } - } - - QString subnetIp = containerConfig.value(m_protocolName).toObject().value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); - { - QStringList l = subnetIp.split(".", Qt::SkipEmptyParts); - if (l.isEmpty()) { - errorCode = ErrorCode::AddressPoolError; - return connData; + quint8 lastOctet = static_cast(lastIp.toIPv4Address()); + switch (lastOctet) { + case 254: result.setAddress(lastIp.toIPv4Address() + 3); break; + case 255: result.setAddress(lastIp.toIPv4Address() + 2); break; + default: result.setAddress(lastIp.toIPv4Address() + 1); break; } - l.removeLast(); - l.append(nextIpNumber); - connData.clientIP = l.join("."); - } + return result; + }(); + + connData.clientIP = nextIp.toString(); // Get keys - connData.serverPubKey = m_serverController->getTextFileFromContainer(container, credentials, m_serverPublicKeyPath, errorCode); + connData.serverPubKey = + m_serverController->getTextFileFromContainer(container, credentials, m_serverPublicKeyPath, errorCode); connData.serverPubKey.replace("\n", ""); if (errorCode != ErrorCode::NoError) { return connData; @@ -161,10 +168,12 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon return connData; } - QString script = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'").arg(m_serverConfigPath); + QString script = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'") + .arg(m_serverConfigPath); errorCode = m_serverController->runScript( - credentials, m_serverController->replaceVars(script, m_serverController->genVarsForScript(credentials, container))); + credentials, + m_serverController->replaceVars(script, m_serverController->genVarsForScript(credentials, container))); return connData; } @@ -173,8 +182,8 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials const QJsonObject &containerConfig, ErrorCode &errorCode) { QString scriptData = amnezia::scriptData(m_configTemplate, container); - QString config = - m_serverController->replaceVars(scriptData, m_serverController->genVarsForScript(credentials, container, containerConfig)); + QString config = m_serverController->replaceVars( + scriptData, m_serverController->genVarsForScript(credentials, container, containerConfig)); ConnectionData connData = prepareWireguardConfig(credentials, container, containerConfig, errorCode); if (errorCode != ErrorCode::NoError) { @@ -208,16 +217,16 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials return QJsonDocument(jConfig).toJson(); } -QString WireguardConfigurator::processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, - QString &protocolConfigString) +QString WireguardConfigurator::processConfigWithLocalSettings(const QPair &dns, + const bool isApiConfig, QString &protocolConfigString) { processConfigWithDnsSettings(dns, protocolConfigString); return protocolConfigString; } -QString WireguardConfigurator::processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, - QString &protocolConfigString) +QString WireguardConfigurator::processConfigWithExportSettings(const QPair &dns, + const bool isApiConfig, QString &protocolConfigString) { processConfigWithDnsSettings(dns, protocolConfigString); diff --git a/client/configurators/wireguard_configurator.h b/client/configurators/wireguard_configurator.h index 22e8a8be..a4302e3e 100644 --- a/client/configurators/wireguard_configurator.h +++ b/client/configurators/wireguard_configurator.h @@ -1,6 +1,7 @@ #ifndef WIREGUARD_CONFIGURATOR_H #define WIREGUARD_CONFIGURATOR_H +#include #include #include @@ -12,8 +13,8 @@ class WireguardConfigurator : public ConfiguratorBase { Q_OBJECT public: - WireguardConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, bool isAwg, - QObject *parent = nullptr); + WireguardConfigurator(std::shared_ptr settings, const QSharedPointer &serverController, + bool isAwg, QObject *parent = nullptr); struct ConnectionData { @@ -26,15 +27,18 @@ public: QString port; }; - QString createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, - ErrorCode &errorCode); + QString createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode &errorCode); - QString processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, QString &protocolConfigString); - QString processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, QString &protocolConfigString); + QString processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString); + QString processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString); static ConnectionData genClientKeys(); private: + QList getIpsFromConf(const QString &input); ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode &errorCode);