diff --git a/client/platforms/windows/daemon/windowsdaemontunnel.cpp b/client/platforms/windows/daemon/windowsdaemontunnel.cpp index b8a8b5b60..04bc67a6e 100644 --- a/client/platforms/windows/daemon/windowsdaemontunnel.cpp +++ b/client/platforms/windows/daemon/windowsdaemontunnel.cpp @@ -37,11 +37,14 @@ int WindowsDaemonTunnel::run(QStringList& tokens) { QCoreApplication::setApplicationName("Amnezia VPN Tunnel"); QCoreApplication::setApplicationVersion(Constants::versionString()); - if (tokens.length() != 2) { - logger.error() << "Expected 1 parameter only: the config file."; + if (tokens.length() < 2 || tokens.length() > 3) { + logger.error() << "Expected: []"; return 1; } QString maybeConfig = tokens.at(1); + QString name = tokens.length() == 3 && !tokens.at(2).isEmpty() + ? tokens.at(2) + : WireguardUtilsWindows::s_defaultInterfaceName(); if (!maybeConfig.startsWith("[Interface]")) { logger.error() << "parameter Does not seem to be a config"; @@ -64,7 +67,6 @@ int WindowsDaemonTunnel::run(QStringList& tokens) { WindowsUtils::windowsLog("Failed to get WireGuardTunnelService function"); return 1; } - auto name = WireguardUtilsWindows::s_interfaceName(); if (!tunnelProc(maybeConfig.utf16(), name.utf16())) { logger.error() << "Failed to activate the tunnel service"; return 1; diff --git a/client/platforms/windows/daemon/windowstunnelservice.cpp b/client/platforms/windows/daemon/windowstunnelservice.cpp index 1438133cc..ae11e69b5 100644 --- a/client/platforms/windows/daemon/windowstunnelservice.cpp +++ b/client/platforms/windows/daemon/windowstunnelservice.cpp @@ -15,9 +15,8 @@ #include "platforms/windows/windowsutils.h" #include "windowsdaemon.h" -#define TUNNEL_NAMED_PIPE \ - "\\\\." \ - "\\pipe\\ProtectedPrefix\\Administrators\\AmneziaWG\\AmneziaVPN" +#define TUNNEL_NAMED_PIPE_PREFIX \ + "\\\\.\\pipe\\ProtectedPrefix\\Administrators\\AmneziaWG\\" constexpr uint32_t WINDOWS_TUNNEL_MONITOR_TIMEOUT_MSEC = 2000; @@ -28,6 +27,10 @@ Logger logger("WindowsTunnelService"); static bool stopAndDeleteTunnelService(SC_HANDLE service); static bool waitForServiceStatus(SC_HANDLE service, DWORD expectedStatus); +std::wstring WindowsTunnelService::serviceNameForIfname(const QString& ifname) { + return (QStringLiteral("AmneziaWGTunnel$") + ifname).toStdWString(); +} + WindowsTunnelService::WindowsTunnelService(QObject* parent) : QObject(parent) { MZ_COUNT_CTOR(WindowsTunnelService); logger.debug() << "WindowsTunnelService created."; @@ -37,7 +40,7 @@ WindowsTunnelService::WindowsTunnelService(QObject* parent) : QObject(parent) { WindowsUtils::windowsLog("Failed to open SCManager"); } - // Is the service already running? Terminate it. + // Is the legacy single-tunnel service still around? Terminate it. SC_HANDLE service = OpenService((SC_HANDLE)m_scm, TUNNEL_SERVICE_NAME, SERVICE_ALL_ACCESS); if (service != nullptr) { @@ -108,8 +111,11 @@ void WindowsTunnelService::timeout() { emit backendFailure(); } -bool WindowsTunnelService::start(const QString& configData) { - logger.debug() << "Starting the tunnel service"; +bool WindowsTunnelService::start(const QString& configData, const QString& ifname) { + logger.debug() << "Starting the tunnel service for" << ifname; + + m_ifname = ifname; + const std::wstring serviceName = serviceNameForIfname(ifname); m_logworker = new WindowsTunnelLogger(WindowsCommons::tunnelLogFile()); m_logworker->moveToThread(&m_logthread); @@ -128,10 +134,9 @@ bool WindowsTunnelService::start(const QString& configData) { m_logworker = nullptr; }); - // Let's see if we have to delete a previous instance. - service = OpenService(scm, TUNNEL_SERVICE_NAME, SERVICE_ALL_ACCESS); + service = OpenService(scm, serviceName.c_str(), SERVICE_ALL_ACCESS); if (service) { - logger.debug() << "An existing service has been detected. Let's close it."; + logger.debug() << "A stale service was detected. Cleaning it up."; if (!stopAndDeleteTunnelService(service)) { return false; } @@ -143,12 +148,12 @@ bool WindowsTunnelService::start(const QString& configData) { { QTextStream out(&serviceCmdline); out << "\"" << qApp->applicationFilePath() << "\" tunneldaemon \"" - << configData << "\""; + << configData << "\" \"" << ifname << "\""; } logger.debug() << "Service:" << qApp->applicationFilePath(); - service = CreateService(scm, TUNNEL_SERVICE_NAME, L"Amnezia VPN (tunnel)", + service = CreateService(scm, serviceName.c_str(), L"Amnezia VPN (tunnel)", SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, (const wchar_t*)serviceCmdline.utf16(), nullptr, 0, @@ -236,8 +241,9 @@ static bool stopAndDeleteTunnelService(SC_HANDLE service) { } QString WindowsTunnelService::uapiCommand(const QString& command) { - // Create a pipe to the tunnel service. - LPTSTR tunnelName = (LPTSTR)TEXT(TUNNEL_NAMED_PIPE); + const std::wstring pipeName = std::wstring(TEXT(TUNNEL_NAMED_PIPE_PREFIX)) + + m_ifname.toStdWString(); + LPCWSTR tunnelName = pipeName.c_str(); HANDLE pipe = CreateFile(tunnelName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); if (pipe == INVALID_HANDLE_VALUE) { diff --git a/client/platforms/windows/daemon/windowstunnelservice.h b/client/platforms/windows/daemon/windowstunnelservice.h index c6027a3bd..3d03bf33f 100644 --- a/client/platforms/windows/daemon/windowstunnelservice.h +++ b/client/platforms/windows/daemon/windowstunnelservice.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "windowstunnellogger.h" @@ -20,11 +21,13 @@ class WindowsTunnelService final : public QObject { WindowsTunnelService(QObject* parent = nullptr); ~WindowsTunnelService(); - bool start(const QString& configData); + bool start(const QString& configData, const QString& ifname); void stop(); bool isRunning(); QString uapiCommand(const QString& command); + static std::wstring serviceNameForIfname(const QString& ifname); + signals: void backendFailure(); @@ -36,6 +39,7 @@ class WindowsTunnelService final : public QObject { QTimer m_timer; QThread m_logthread; WindowsTunnelLogger* m_logworker = nullptr; + QString m_ifname; // These are really SC_HANDLEs in disguise. void* m_scm = nullptr; diff --git a/client/platforms/windows/daemon/wireguardutilswindows.cpp b/client/platforms/windows/daemon/wireguardutilswindows.cpp index 36f5d2d15..89eec438b 100644 --- a/client/platforms/windows/daemon/wireguardutilswindows.cpp +++ b/client/platforms/windows/daemon/wireguardutilswindows.cpp @@ -12,6 +12,7 @@ #include +#include "killswitch.h" #include "leakdetector.h" #include "logger.h" #include "windowsfirewall.h" @@ -110,15 +111,14 @@ bool WireguardUtilsWindows::addInterface(const InterfaceConfig& config) { configString.truncate(peerStart); } - if (!m_tunnel.start(configString)) { + m_ifname = config.m_ifname.isEmpty() ? s_defaultInterfaceName() : config.m_ifname; + if (!m_tunnel.start(configString, m_ifname)) { logger.error() << "Failed to activate the tunnel service"; return false; } - // Determine the interface LUID NET_LUID luid; - const QString ifname = config.m_ifname.isEmpty() ? interfaceName() : config.m_ifname; - DWORD result = ConvertInterfaceAliasToLuid((wchar_t*)ifname.utf16(), &luid); + DWORD result = ConvertInterfaceAliasToLuid((wchar_t*)m_ifname.utf16(), &luid); if (result != 0) { logger.error() << "Failed to lookup LUID:" << result; return false; @@ -127,11 +127,11 @@ bool WireguardUtilsWindows::addInterface(const InterfaceConfig& config) { m_routeMonitor = new WindowsRouteMonitor(luid.Value, this); if (config.m_killSwitchEnabled) { - // Enable the windows firewall NET_IFINDEX ifindex; ConvertInterfaceLuidToIndex(&luid, &ifindex); m_firewall->allowAllTraffic(); m_firewall->enableInterface(ifindex); + KillSwitch::instance()->addAllowedRange({}); } logger.debug() << "Registration completed"; diff --git a/client/platforms/windows/daemon/wireguardutilswindows.h b/client/platforms/windows/daemon/wireguardutilswindows.h index 276966b40..8828cb82f 100644 --- a/client/platforms/windows/daemon/wireguardutilswindows.h +++ b/client/platforms/windows/daemon/wireguardutilswindows.h @@ -27,10 +27,8 @@ class WireguardUtilsWindows final : public WireguardUtils { ~WireguardUtilsWindows(); bool interfaceExists() override { return m_tunnel.isRunning(); } - QString interfaceName() override { - return WireguardUtilsWindows::s_interfaceName(); - } - static const QString s_interfaceName() { return "AmneziaVPN"; } + QString interfaceName() override { return m_ifname; } + static const QString s_defaultInterfaceName() { return "AmneziaVPN"; } bool addInterface(const InterfaceConfig& config) override; bool deleteInterface() override; @@ -54,6 +52,7 @@ class WireguardUtilsWindows final : public WireguardUtils { void buildMibForwardRow(const IPAddress& prefix, void* row); quint64 m_luid = 0; + QString m_ifname; WindowsTunnelService m_tunnel; QPointer m_routeMonitor; QPointer m_firewall;