diff --git a/client/protocols/wireguardprotocol.cpp b/client/protocols/wireguardprotocol.cpp index 0f5c06fe1..acfaf1bd4 100644 --- a/client/protocols/wireguardprotocol.cpp +++ b/client/protocols/wireguardprotocol.cpp @@ -51,7 +51,7 @@ void WireguardProtocol::stop() m_wireguardStopProcess->setProgram(wireguardExecPath()); - QStringList arguments({"/uninstalltunnelservice", serviceName(), }); + QStringList arguments({"--remove", configPath()}); m_wireguardStopProcess->setArguments(arguments); qDebug() << arguments.join(" "); @@ -123,7 +123,7 @@ void WireguardProtocol::updateRouteGateway(QString line) QString WireguardProtocol::wireguardExecPath() const { #ifdef Q_OS_WIN - return Utils::executable("wireguard/wireguard", true); + return Utils::executable("wireguard/wireguard-service", true); #elif defined Q_OS_LINUX return Utils::usrExecutable("wg"); #else @@ -172,7 +172,7 @@ ErrorCode WireguardProtocol::start() m_wireguardStartProcess->setProgram(wireguardExecPath()); - QStringList arguments({"/installtunnelservice", configPath(), }); + QStringList arguments({"--add", configPath()}); m_wireguardStartProcess->setArguments(arguments); qDebug() << arguments.join(" "); diff --git a/deploy/build_windows.bat b/deploy/build_windows.bat index bd83e9dc4..88f29fc9e 100644 --- a/deploy/build_windows.bat +++ b/deploy/build_windows.bat @@ -82,6 +82,7 @@ signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://ti echo "Copying deploy data..." xcopy %DEPLOY_DATA_DIR% %OUT_APP_DIR% /s /e /y /i /f +copy "%WORK_DIR:"=%\service\wireguard-service\release\wireguard-service.exe" %OUT_APP_DIR%\wireguard\ del %OUT_APP_DIR%\botand.dll diff --git a/deploy/data/windows/x32/wireguard/tunnel.dll b/deploy/data/windows/x32/wireguard/tunnel.dll new file mode 100644 index 000000000..016595ab6 Binary files /dev/null and b/deploy/data/windows/x32/wireguard/tunnel.dll differ diff --git a/deploy/data/windows/x32/wireguard/wireguard.dll b/deploy/data/windows/x32/wireguard/wireguard.dll new file mode 100644 index 000000000..b5b141adc Binary files /dev/null and b/deploy/data/windows/x32/wireguard/wireguard.dll differ diff --git a/deploy/data/windows/x64/wireguard/tunnel.dll b/deploy/data/windows/x64/wireguard/tunnel.dll new file mode 100644 index 000000000..310a4a31a Binary files /dev/null and b/deploy/data/windows/x64/wireguard/tunnel.dll differ diff --git a/deploy/data/windows/x64/wireguard/wg.exe b/deploy/data/windows/x64/wireguard/wg.exe deleted file mode 100644 index b69dfc41f..000000000 Binary files a/deploy/data/windows/x64/wireguard/wg.exe and /dev/null differ diff --git a/deploy/data/windows/x64/wireguard/wireguard.dll b/deploy/data/windows/x64/wireguard/wireguard.dll new file mode 100644 index 000000000..8af4d087b Binary files /dev/null and b/deploy/data/windows/x64/wireguard/wireguard.dll differ diff --git a/deploy/data/windows/x64/wireguard/wireguard.exe b/deploy/data/windows/x64/wireguard/wireguard.exe deleted file mode 100644 index c63bd1c96..000000000 Binary files a/deploy/data/windows/x64/wireguard/wireguard.exe and /dev/null differ diff --git a/service/service.pro b/service/service.pro index 333243ce7..213929a3c 100644 --- a/service/service.pro +++ b/service/service.pro @@ -4,4 +4,7 @@ include(common.pri) qtservice-uselib:SUBDIRS=buildlib SUBDIRS+=server + win32 { + SUBDIRS+=wireguard-service + } } diff --git a/service/wireguard-service/main.cpp b/service/wireguard-service/main.cpp new file mode 100644 index 000000000..8e5f231e7 --- /dev/null +++ b/service/wireguard-service/main.cpp @@ -0,0 +1,31 @@ +#include "wireguardtunnelservice.h" +#include +#include + +int wmain(int argc, wchar_t** argv) +{ + if (argc != 3) { + debug_log(L"Wrong argument provided"); + return 1; + } + TCHAR option[20]; + TCHAR configFile[5000]; + + StringCchCopy(option, 20, argv[1]); + StringCchCopy(configFile, 5000, argv[2]); + + WireguardTunnelService tunnel(configFile); + + if (lstrcmpi(option, TEXT("--run")) == 0) { + debug_log(L"start tunnel"); + tunnel.startTunnel(); + } else if (lstrcmpi(option, TEXT("--add")) == 0) { + tunnel.addService(); + } else if (lstrcmpi(option, TEXT("--remove")) == 0) { + tunnel.removeService(); + } else { + debug_log(L"Wrong argument provided"); + return 1; + } + return 0; +} diff --git a/service/wireguard-service/wireguard-service.pro b/service/wireguard-service/wireguard-service.pro new file mode 100644 index 000000000..f248bbbff --- /dev/null +++ b/service/wireguard-service/wireguard-service.pro @@ -0,0 +1,23 @@ +TARGET = wireguard-service +TEMPLATE = app +CONFIG += console +CONFIG -= app_bundle +CONFIG -= qt +LIBS += \ + -luser32 \ + -lrasapi32 \ + -lshlwapi \ + -liphlpapi \ + -lws2_32 \ + -liphlpapi \ + -lgdi32 \ + -lAdvapi32 \ + -lKernel32 + +HEADERS = \ + wireguardtunnelservice.h + +SOURCES = \ + main.cpp \ + wireguardtunnelservice.cpp + diff --git a/service/wireguard-service/wireguardtunnelservice.cpp b/service/wireguard-service/wireguardtunnelservice.cpp new file mode 100644 index 000000000..9864038e4 --- /dev/null +++ b/service/wireguard-service/wireguardtunnelservice.cpp @@ -0,0 +1,160 @@ +#include "wireguardtunnelservice.h" +#include +#include +#include +#include +#include +#include +#include + + +void debug_log(const std::wstring& msg) +{ + std::wcerr << msg << std::endl; +} + +WireguardTunnelService::WireguardTunnelService(const std::wstring& configFile): + m_configFile{configFile} +{ +} + +void WireguardTunnelService::addService() +{ + SC_HANDLE scm; + SC_HANDLE service; + scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (NULL == scm) { + debug_log(L"OpenSCManager failed"); + return; + } + WCHAR szFileName[MAX_PATH]; + + GetModuleFileNameW(NULL, szFileName, MAX_PATH); + std::wstring runCommand = szFileName; + runCommand += TEXT(" --run "); + runCommand += m_configFile; + + debug_log(runCommand); + // check if service is already running + service = OpenServiceW( + scm, + SVCNAME, + SERVICE_ALL_ACCESS + ); + if (NULL != service) { + //service is already running, remove it before add new service + debug_log(L"service is already running, remove it before add new service"); + CloseServiceHandle(service); + removeService(); + } + service = CreateServiceW( + scm, + SVCNAME, + SVCNAME, + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + runCommand.c_str(), + NULL, + NULL, + TEXT("Nsi\0TcpIp"), + NULL, + NULL); + if (NULL == service) { + debug_log(L"CreateServiceW failed"); + CloseServiceHandle(scm); + return; + } + SERVICE_SID_INFO info; + info.dwServiceSidType = SERVICE_SID_TYPE_UNRESTRICTED; + if (ChangeServiceConfig2W(service, + SERVICE_CONFIG_SERVICE_SID_INFO, + &info) == 0) { + debug_log(L"ChangeServiceConfig2 failed"); + CloseServiceHandle(service); + CloseServiceHandle(scm); + return; + } + if (StartServiceW(service, 0, NULL) == 0) { + debug_log(L"StartServiceW failed"); + CloseServiceHandle(service); + CloseServiceHandle(scm); + return; + } + if (DeleteService(service) == 0) { + debug_log(L"DeleteService failed"); + CloseServiceHandle(service); + CloseServiceHandle(scm); + return; + } + CloseServiceHandle(service); + CloseServiceHandle(scm); +} + +void WireguardTunnelService::removeService() +{ + SC_HANDLE scm; + SC_HANDLE service; + scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (NULL == scm) { + debug_log(L"OpenSCManager failed"); + return; + } + service = OpenServiceW( + scm, + SVCNAME, + SERVICE_ALL_ACCESS + ); + if (NULL == service) { + debug_log(L"OpenServiceW failed"); + CloseServiceHandle(scm); + return; + } + SERVICE_STATUS stt; + if (ControlService(service, SERVICE_CONTROL_STOP, &stt) == 0) { + debug_log(L"ControlService failed"); + DeleteService(service); + CloseServiceHandle(service); + CloseServiceHandle(scm); + return; + } + for (int i = 0; + i < 180 && QueryServiceStatus(scm, &stt) && stt.dwCurrentState != SERVICE_STOPPED; + ++i) { + std::this_thread::sleep_for(std::chrono::seconds{1}); + } + DeleteService(service); + CloseServiceHandle(service); + CloseServiceHandle(scm); +} + + +int WireguardTunnelService::startTunnel() +{ + debug_log(TEXT(__FUNCTION__)); + + HMODULE tunnelLib = LoadLibrary(TEXT("tunnel.dll")); + if (!tunnelLib) { + debug_log(L"Failed to load tunnel.dll"); + return 1; + } + + typedef bool WireGuardTunnelService(const LPCWSTR settings); + + WireGuardTunnelService* tunnelProc = (WireGuardTunnelService*)GetProcAddress( + tunnelLib, "WireGuardTunnelService"); + if (!tunnelProc) { + debug_log(L"Failed to get WireGuardTunnelService function"); + return 1; + } + + debug_log(m_configFile.c_str()); + + if (!tunnelProc(m_configFile.c_str())) { + debug_log(L"Failed to activate the tunnel service"); + return 1; + } + return 0; +} + diff --git a/service/wireguard-service/wireguardtunnelservice.h b/service/wireguard-service/wireguardtunnelservice.h new file mode 100644 index 000000000..3afd64c0a --- /dev/null +++ b/service/wireguard-service/wireguardtunnelservice.h @@ -0,0 +1,22 @@ +#ifndef WIREGUARDTUNNELSERVICE_H +#define WIREGUARDTUNNELSERVICE_H + +#include +#include + +#define SVCNAME TEXT("AmneziaVPNWireGuardService") + +class WireguardTunnelService +{ +public: + WireguardTunnelService(const std::wstring& configFile); + void addService(); + void removeService(); + int startTunnel(); +private: + std::wstring m_configFile; +}; + +void debug_log(const std::wstring& msg); + +#endif // WIREGUARDTUNNELSERVICE_H