diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ca4323b84..b92fb253d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -100,15 +100,15 @@ variables: - curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem --create-dirs -o ${BUILD_LIBS_FOLDER}/qt.zip "${NEXUS_PATH_DEPS}/${OS_IDENTIFIER}/qt.zip" -.download_dependency_stunnel: +.download_dependency_wireguard: script: - curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem - --create-dirs -o ${BUILD_LIBS_FOLDER}/stunnel.zip "${NEXUS_PATH_DEPS}/${OS_IDENTIFIER}/stunnel.zip" + --create-dirs -o ${BUILD_LIBS_FOLDER}/wireguard.zip "${NEXUS_PATH_DEPS}/${OS_IDENTIFIER}/wireguard.zip" -.download_dependency_wireguard: +.download_dependency_wstunnel: script: - curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem - --create-dirs -o ${BUILD_LIBS_FOLDER}/wireguard.zip "${NEXUS_PATH_DEPS}/${OS_IDENTIFIER}/wireguard.zip" + --create-dirs -o ${BUILD_LIBS_FOLDER}/stunnel.zip "${NEXUS_PATH_DEPS}/${OS_IDENTIFIER}/wstunnel.zip" .download_dependency_zlib: script: @@ -130,8 +130,8 @@ variables: - !reference [.download_dependency_openssl, script] - !reference [.download_dependency_openvpn, script] - !reference [.download_dependency_qt, script] - - !reference [.download_dependency_stunnel, script] - !reference [.download_dependency_wireguard, script] + - !reference [.download_dependency_wstunnel, script] - !reference [.download_dependency_zlib, script] - 'IF(Test-Path .\$BUILD_LIBS_FOLDER\) {Get-ChildItem .\$BUILD_LIBS_FOLDER\*.zip | Foreach {.\tools\bin\7z.exe x $_.FullName -o"$BUILD_LIBS_FOLDER\"}}' # extractions @@ -263,8 +263,8 @@ build:win:arm64:installer:tagged: - !reference [.download_dependency_openssl, script] - !reference [.download_dependency_openvpn, script] - !reference [.download_dependency_qt, script] - - !reference [.download_dependency_stunnel, script] - !reference [.download_dependency_wireguard, script] + - !reference [.download_dependency_wstunnel, script] - if [ -d ./${BUILD_LIBS_FOLDER}/ ]; then for z in ./${BUILD_LIBS_FOLDER}/*.zip; do unzip -qod ./${BUILD_LIBS_FOLDER} $z; done; fi # extractions - VAULT_CLIENT_TOKEN=$(curl --cacert tools/cacert.pem --data "{\"role_id\":\"$VAULT_ROLE_ID\",\"secret_id\":\"$VAULT_SECRET_ID\"}" @@ -334,8 +334,8 @@ build:mac:installer:tagged: - !reference [.download_dependency_openssl, script] - !reference [.download_dependency_openvpn, script] - !reference [.download_dependency_qt, script] - - !reference [.download_dependency_stunnel, script] - !reference [.download_dependency_wireguard, script] + - !reference [.download_dependency_wstunnel, script] - if [ -d ./${BUILD_LIBS_FOLDER}/ ]; then for z in ./${BUILD_LIBS_FOLDER}/*.zip; do unzip -qod ./${BUILD_LIBS_FOLDER} $z; done; fi # extractions - VAULT_CLIENT_TOKEN=$(curl --cacert tools/cacert.pem @@ -403,6 +403,7 @@ build:rhel:installer:tagged: .template_archlinux_build: &template_archlinux_build image: archlinux:base-devel before_script: + - pacman -Syu --noconfirm - pacman -Sy --noconfirm git curl python nftables c-ares freetype2 hicolor-icon-theme libglvnd fontconfig libx11 libxkbcommon libxcb net-tools xcb-util-wm xcb-util-image xcb-util-keysyms xcb-util-renderutil .build_archlinux_installer_prep_build_dir: diff --git a/backend/linux/helper/server.cpp b/backend/linux/helper/server.cpp index e3edbdcaf..4724e7e33 100644 --- a/backend/linux/helper/server.cpp +++ b/backend/linux/helper/server.cpp @@ -269,7 +269,7 @@ bool Server::readAndHandleCommand(socket_ptr sock, boost::asio::streambuf *buf, outCmdAnswer.executed = 1; } else if (cmd.target == kTargetStunnel) { Logger::instance().out("Killing Stunnel processes"); - Utils::executeCommand("pkill", {"-f", "windscribestunnel"}); + Utils::executeCommand("pkill", {"-f", "windscribewstunnel"}); outCmdAnswer.executed = 1; } else if (cmd.target == kTargetWStunnel) { Logger::instance().out("Killing WStunnel processes"); @@ -359,7 +359,16 @@ bool Server::readAndHandleCommand(socket_ptr sock, boost::asio::streambuf *buf, ia >> cmd; Logger::instance().out("Starting stunnel"); - std::string fullCmd = Utils::getFullCommandAsUser("windscribe", cmd.exePath, cmd.executable, "/etc/windscribe/stunnel.conf"); + std::stringstream arguments; + arguments << "--listenAddress :" << cmd.localPort; + arguments << " --remoteAddress https://" << cmd.hostname << ":" << cmd.port; + arguments << " --logFilePath \"\""; + if (cmd.extraPadding) { + arguments << " --extraTlsPadding"; + } + arguments << " --tunnelType 2"; + //arguments << " --dev"; // enables verbose logging when necessary + std::string fullCmd = Utils::getFullCommandAsUser("windscribe", cmd.exePath, cmd.executable, arguments.str()); if (fullCmd.empty()) { // Something wrong with the command outCmdAnswer.executed = 0; @@ -374,39 +383,17 @@ bool Server::readAndHandleCommand(socket_ptr sock, boost::asio::streambuf *buf, outCmdAnswer.executed = 1; } } - } else if (cmdId == HELPER_CMD_CONFIGURE_STUNNEL) { - CMD_CONFIGURE_STUNNEL cmd; - ia >> cmd; - - std::stringstream conf; - conf << "[openvpn]\n"; - conf << "client = yes\n"; - conf << "accept = 127.0.0.1:" << cmd.localPort << "\n"; - conf << "connect = " << cmd.hostname << ":" << cmd.port << "\n"; - if (cmd.extraPadding) { - conf << "options = TLSEXT_PADDING\noptions = TLSEXT_PADDING_SUPER\n"; - } - - int fd = open("/etc/windscribe/stunnel.conf", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU); - if (fd < 0) { - Logger::instance().out("Could not open stunnel config for writing"); - outCmdAnswer.executed = 0; - } else { - write(fd, conf.str().c_str(), conf.str().length()); - close(fd); - outCmdAnswer.executed = 1; - outCmdAnswer.cmdId = Utils::executeCommand("chown", {"windscribe:windscribe", "/etc/windscribe/stunnel.conf"}); - } } else if (cmdId == HELPER_CMD_START_WSTUNNEL) { CMD_START_WSTUNNEL cmd; ia >> cmd; Logger::instance().out("Starting wstunnel"); - std::string arguments = "--localToRemote 127.0.0.1:" + std::to_string(cmd.localPort) + ":127.0.0.1:1194 wss://" + cmd.hostname + ":" + std::to_string(cmd.port) + " --verbose --upgradePathPrefix=/"; - if (cmd.isUdp) { - arguments += " --udp"; - } - std::string fullCmd = Utils::getFullCommandAsUser("windscribe", cmd.exePath, cmd.executable, arguments); + std::stringstream arguments; + arguments << "--listenAddress :" << cmd.localPort; + arguments << " --remoteAddress wss://" << cmd.hostname << ":" << cmd.port << "/tcp/127.0.0.1/1194"; + arguments << " --logFilePath \"\""; + //arguments << " --dev"; // enables verbose logging when necessary + std::string fullCmd = Utils::getFullCommandAsUser("windscribe", cmd.exePath, cmd.executable, arguments.str()); if (fullCmd.empty()) { // Something wrong with the command outCmdAnswer.executed = 0; diff --git a/backend/mac/helper/helper-info.plist b/backend/mac/helper/helper-info.plist index 509a796d0..9daedf79f 100644 --- a/backend/mac/helper/helper-info.plist +++ b/backend/mac/helper/helper-info.plist @@ -9,7 +9,7 @@ CFBundleName WindscribeHelper CFBundleVersion - 47 + 48 NSHumanReadableCopyright Copyright © 2023 Windscribe Limited. All rights reserved. LSMinimumSystemVersion diff --git a/backend/mac/helper/server.cpp b/backend/mac/helper/server.cpp index 4bbf91298..2838ed2dd 100644 --- a/backend/mac/helper/server.cpp +++ b/backend/mac/helper/server.cpp @@ -321,7 +321,7 @@ bool Server::readAndHandleCommand(socket_ptr sock, boost::asio::streambuf *buf, outCmdAnswer.executed = 1; } else if (cmd.target == kTargetStunnel) { LOG("Killing Stunnel processes"); - Utils::executeCommand("pkill", {"-f", "windscribestunnel"}); + Utils::executeCommand("pkill", {"-f", "windscribewstunnel"}); outCmdAnswer.executed = 1; } else if (cmd.target == kTargetWStunnel) { LOG("Killing WStunnel processes"); @@ -446,7 +446,16 @@ bool Server::readAndHandleCommand(socket_ptr sock, boost::asio::streambuf *buf, ia >> cmd; LOG("Starting stunnel"); - std::string fullCmd = Utils::getFullCommandAsUser("windscribe", cmd.exePath, cmd.executable, "/etc/windscribe/stunnel.conf"); + std::stringstream arguments; + arguments << "--listenAddress :" << cmd.localPort; + arguments << " --remoteAddress https://" << cmd.hostname << ":" << cmd.port; + arguments << " --logFilePath \"\""; + if (cmd.extraPadding) { + arguments << " --extraTlsPadding"; + } + arguments << " --tunnelType 2"; + //arguments << " --dev"; // enables verbose logging when necessary + std::string fullCmd = Utils::getFullCommandAsUser("windscribe", cmd.exePath, cmd.executable, arguments.str()); if (fullCmd.empty()) { // Something wrong with the command outCmdAnswer.executed = 0; @@ -461,39 +470,17 @@ bool Server::readAndHandleCommand(socket_ptr sock, boost::asio::streambuf *buf, outCmdAnswer.executed = 1; } } - } else if (cmdId == HELPER_CMD_CONFIGURE_STUNNEL) { - CMD_CONFIGURE_STUNNEL cmd; - ia >> cmd; - - std::stringstream conf; - conf << "[openvpn]\n"; - conf << "client = yes\n"; - conf << "accept = 127.0.0.1:" << cmd.localPort << "\n"; - conf << "connect = " << cmd.hostname << ":" << cmd.port << "\n"; - if (cmd.extraPadding) { - conf << "options = TLSEXT_PADDING\noptions = TLSEXT_PADDING_SUPER\n"; - } - - int fd = open("/etc/windscribe/stunnel.conf", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU); - if (fd < 0) { - LOG("Could not open stunnel config for writing"); - outCmdAnswer.executed = 0; - } else { - write(fd, conf.str().c_str(), conf.str().length()); - close(fd); - outCmdAnswer.executed = 1; - outCmdAnswer.cmdId = Utils::executeCommand("chown", {"windscribe:windscribe", "/etc/windscribe/stunnel.conf"}); - } } else if (cmdId == HELPER_CMD_START_WSTUNNEL) { CMD_START_WSTUNNEL cmd; ia >> cmd; LOG("Starting wstunnel"); - std::string arguments = "--localToRemote 127.0.0.1:" + std::to_string(cmd.localPort) + ":127.0.0.1:1194 wss://" + cmd.hostname + ":" + std::to_string(cmd.port) + " --verbose --upgradePathPrefix=/"; - if (cmd.isUdp) { - arguments += " --udp"; - } - std::string fullCmd = Utils::getFullCommandAsUser("windscribe", cmd.exePath, cmd.executable, arguments); + std::stringstream arguments; + arguments << "--listenAddress :" << cmd.localPort; + arguments << " --remoteAddress wss://" << cmd.hostname << ":" << cmd.port << "/tcp/127.0.0.1/1194"; + arguments << " --logFilePath \"\""; + //arguments << " --dev"; // enables verbose logging when necessary + std::string fullCmd = Utils::getFullCommandAsUser("windscribe", cmd.exePath, cmd.executable, arguments.str()); if (fullCmd.empty()) { // Something wrong with the command outCmdAnswer.executed = 0; diff --git a/backend/mac/wstunnel/readme.txt b/backend/mac/wstunnel/readme.txt deleted file mode 100644 index 7a1a0777b..000000000 --- a/backend/mac/wstunnel/readme.txt +++ /dev/null @@ -1 +0,0 @@ -Precompiled binary of wstunnel for Mac. Copies to engine bundle when building engine project. \ No newline at end of file diff --git a/backend/mac/wstunnel/windscribewstunnel b/backend/mac/wstunnel/windscribewstunnel deleted file mode 100755 index 166c7af2a..000000000 Binary files a/backend/mac/wstunnel/windscribewstunnel and /dev/null differ diff --git a/backend/posix_common/helper_commands.h b/backend/posix_common/helper_commands.h index 601f86c27..bbb7a87db 100644 --- a/backend/posix_common/helper_commands.h +++ b/backend/posix_common/helper_commands.h @@ -39,8 +39,7 @@ #define HELPER_CMD_TASK_KILL 31 #define HELPER_CMD_START_CTRLD 32 #define HELPER_CMD_START_STUNNEL 33 -#define HELPER_CMD_CONFIGURE_STUNNEL 34 -#define HELPER_CMD_START_WSTUNNEL 35 +#define HELPER_CMD_START_WSTUNNEL 34 // enums @@ -263,9 +262,6 @@ struct CMD_TASK_KILL { struct CMD_START_STUNNEL { std::string exePath; std::string executable; -}; - -struct CMD_CONFIGURE_STUNNEL { std::string hostname; int port; int localPort; @@ -278,7 +274,6 @@ struct CMD_START_WSTUNNEL { std::string hostname; int port; int localPort; - bool isUdp; }; #endif diff --git a/backend/posix_common/helper_commands_serialize.h b/backend/posix_common/helper_commands_serialize.h index 695fa1560..8d2d670b2 100644 --- a/backend/posix_common/helper_commands_serialize.h +++ b/backend/posix_common/helper_commands_serialize.h @@ -268,15 +268,10 @@ void serialize(Archive &ar, CMD_START_STUNNEL &a, const unsigned int version) UNUSED(version); ar & a.exePath; ar & a.executable; -} - -template -void serialize(Archive &ar, CMD_CONFIGURE_STUNNEL &a, const unsigned int version) -{ - UNUSED(version); ar & a.hostname; ar & a.port; ar & a.localPort; + ar & a.extraPadding; } template @@ -288,7 +283,6 @@ void serialize(Archive &ar, CMD_START_WSTUNNEL &a, const unsigned int version) ar & a.hostname; ar & a.port; ar & a.localPort; - ar & a.isUdp; } } diff --git a/backend/windows/windscribe_service/apps_ids.cpp b/backend/windows/windscribe_service/apps_ids.cpp index be3e33dc1..7bcb876c1 100644 --- a/backend/windows/windscribe_service/apps_ids.cpp +++ b/backend/windows/windscribe_service/apps_ids.cpp @@ -32,7 +32,7 @@ size_t AppsIds::count() const return appIds_.size(); } -FWP_BYTE_BLOB *AppsIds::getAppId(size_t ind) +const FWP_BYTE_BLOB *AppsIds::getAppId(size_t ind) const { if (ind < appIds_.size()) { diff --git a/backend/windows/windscribe_service/apps_ids.h b/backend/windows/windscribe_service/apps_ids.h index af8ba2ab9..2f99854ca 100644 --- a/backend/windows/windscribe_service/apps_ids.h +++ b/backend/windows/windscribe_service/apps_ids.h @@ -13,7 +13,7 @@ class AppsIds void addFrom(const AppsIds &a); size_t count() const; - FWP_BYTE_BLOB *getAppId(size_t ind); + const FWP_BYTE_BLOB *getAppId(size_t ind) const; bool operator==(const AppsIds& other) const; diff --git a/backend/windows/windscribe_service/executecmd.cpp b/backend/windows/windscribe_service/executecmd.cpp index a3f92d05b..aa4fa0e7e 100644 --- a/backend/windows/windscribe_service/executecmd.cpp +++ b/backend/windows/windscribe_service/executecmd.cpp @@ -1,14 +1,8 @@ -#include "all_headers.h" -#include "pipe_for_process.h" -#include "ipc/servicecommunication.h" #include "executecmd.h" -#include "utils.h" -#include "logger.h" -#include -#include -#pragma comment(lib, "WtsApi32.lib") -#pragma comment(lib, "Userenv.lib") +#include "logger.h" +#include "utils.h" +#include "utils/win32handle.h" unsigned long ExecuteCmd::blockingCmdId_ = 0; ExecuteCmd *ExecuteCmd::this_ = NULL; @@ -26,7 +20,7 @@ ExecuteCmd::~ExecuteCmd() this_ = NULL; } -MessagePacketResult ExecuteCmd::executeBlockingCmd(wchar_t *cmd, HANDLE user_token) +MessagePacketResult ExecuteCmd::executeBlockingCmd(const std::wstring &cmd, HANDLE user_token) { MessagePacketResult mpr; @@ -35,9 +29,9 @@ MessagePacketResult ExecuteCmd::executeBlockingCmd(wchar_t *cmd, HANDLE user_tok sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; - HANDLE rPipe, wPipe; - if (!CreatePipe(&rPipe, &wPipe, &sa, 0)) - { + wsl::Win32Handle pipeRead; + wsl::Win32Handle pipeWrite; + if (!CreatePipe(pipeRead.data(), pipeWrite.data(), &sa, 0)) { return mpr; } @@ -47,50 +41,55 @@ MessagePacketResult ExecuteCmd::executeBlockingCmd(wchar_t *cmd, HANDLE user_tok si.cb = sizeof(si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = NULL; - si.hStdError = wPipe; - si.hStdOutput = wPipe; + si.hStdError = pipeWrite.getHandle(); + si.hStdOutput = pipeWrite.getHandle(); + + // As per the Win32 docs; the Unicode version of CreateProcess 'may' modify its lpCommandLine + // parameter. Therefore, this parameter cannot be a pointer to read-only memory (such as a + // const variable or a literal string). If this parameter is a constant string, CreateProcess + // may cause an access violation. Maximum length of the lpCommandLine parameter is 32767. + std::unique_ptr exec(new wchar_t[32767]); + wcsncpy_s(exec.get(), 32767, cmd.c_str(), _TRUNCATE); ZeroMemory( &pi, sizeof(pi) ); const auto run_result = user_token != INVALID_HANDLE_VALUE - ? CreateProcessAsUser(user_token, NULL, cmd, NULL, NULL, TRUE, - CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi) - : CreateProcess(NULL, cmd, NULL, NULL, TRUE, - CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); + ? CreateProcessAsUser(user_token, NULL, exec.get(), NULL, NULL, TRUE, + CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi) + : CreateProcess(NULL, exec.get(), NULL, NULL, TRUE, + CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); - if (run_result) - { + if (run_result) { DWORD exitCode; WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitCode); - CloseHandle(wPipe); - std::string str = Utils::readAllFromPipe(rPipe); - CloseHandle(rPipe); + pipeWrite.closeHandle(); + std::string str = Utils::readAllFromPipe(pipeRead.getHandle()); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); mpr.success = true; mpr.exitCode = exitCode; - mpr.additionalString = str; + mpr.additionalString = str; } - else - { - Logger::instance().out(L"Failed create process: %x", GetLastError()); - CloseHandle(rPipe); - CloseHandle(wPipe); + else { + Logger::instance().out(L"Failed create process: %x", GetLastError()); } + return mpr; } -MessagePacketResult ExecuteCmd::executeUnblockingCmd(const wchar_t *cmd, const wchar_t *szEventName, const wchar_t *szWorkingDir) +MessagePacketResult ExecuteCmd::executeUnblockingCmd(const std::wstring &cmd, const wchar_t *szEventName, const std::wstring &workingDir) { std::lock_guard lock(mutex_); - wchar_t szCmd[1024] = {}; - if (wcslen(cmd) > sizeof(szCmd) / sizeof(szCmd[0]) - 1) - Logger::instance().out(L"Command too long: \"%x\"", cmd); - wcsncpy(szCmd, cmd, sizeof(szCmd)/sizeof(szCmd[0])-1); + // As per the Win32 docs; the Unicode version of CreateProcess 'may' modify its lpCommandLine + // parameter. Therefore, this parameter cannot be a pointer to read-only memory (such as a + // const variable or a literal string). If this parameter is a constant string, CreateProcess + // may cause an access violation. Maximum length of the lpCommandLine parameter is 32767. + std::unique_ptr exec(new wchar_t[32767]); + wcsncpy_s(exec.get(), 32767, cmd.c_str(), _TRUNCATE); MessagePacketResult mpr; @@ -107,15 +106,15 @@ MessagePacketResult ExecuteCmd::executeUnblockingCmd(const wchar_t *cmd, const w si.cb = sizeof(si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = NULL; - si.hStdError = blockingCmd->pipeForProcess.getPipeHandle(); - si.hStdOutput = blockingCmd->pipeForProcess.getPipeHandle(); + si.hStdError = blockingCmd->pipeForProcess.getPipeHandle(); + si.hStdOutput = blockingCmd->pipeForProcess.getPipeHandle(); ZeroMemory( &pi, sizeof(pi) ); - if (CreateProcess(NULL, szCmd, NULL, NULL, TRUE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, szWorkingDir, &si, &pi)) + if (CreateProcess(NULL, exec.get(), NULL, NULL, TRUE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, workingDir.c_str(), &si, &pi)) { - blockingCmd->pipeForProcess.startReading(); - blockingCmd->szEventName = szEventName; - blockingCmd->hProcess = pi.hProcess; + blockingCmd->pipeForProcess.startReading(); + blockingCmd->szEventName = szEventName; + blockingCmd->hProcess = pi.hProcess; blockingCmd->hThread = pi.hThread; blockingCmd->id = blockingCmdId_; @@ -124,13 +123,13 @@ MessagePacketResult ExecuteCmd::executeUnblockingCmd(const wchar_t *cmd, const w blockingCmdId_++; blockingCmds_.push_back(blockingCmd); - + RegisterWaitForSingleObject(&blockingCmd->hWait, blockingCmd->hProcess, waitOrTimerCallback, blockingCmd, INFINITE, WT_EXECUTEONLYONCE); } else { - Logger::instance().out(L"Failed create process: %x", GetLastError()); + Logger::instance().out(L"Failed create process: %x", GetLastError()); delete blockingCmd; } @@ -152,7 +151,7 @@ MessagePacketResult ExecuteCmd::getUnblockingCmdStatus(unsigned long cmdId) mpr.success = true; mpr.exitCode = blockingCmd->dwExitCode; mpr.blockingCmdFinished = true; - mpr.additionalString = blockingCmd->strLogOutput.c_str(); + mpr.additionalString = blockingCmd->strLogOutput.c_str(); blockingCmds_.erase(it); delete blockingCmd; @@ -205,7 +204,7 @@ void ExecuteCmd::waitOrTimerCallback(PVOID lpParameter, BOOLEAN /*timerOrWaitFir GetExitCodeProcess(blockingCmd->hProcess, &exitCode); blockingCmd->dwExitCode = exitCode; - blockingCmd->strLogOutput = blockingCmd->pipeForProcess.stopAndGetOutput(); + blockingCmd->strLogOutput = blockingCmd->pipeForProcess.stopAndGetOutput(); CloseHandle(blockingCmd->hProcess); CloseHandle(blockingCmd->hThread); @@ -214,21 +213,21 @@ void ExecuteCmd::waitOrTimerCallback(PVOID lpParameter, BOOLEAN /*timerOrWaitFir blockingCmd->bFinished = true; - // set event if specified - if (!blockingCmd->szEventName.empty()) - { - HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, blockingCmd->szEventName.c_str()); - if (hEvent != NULL) - { - SetEvent(hEvent); - CloseHandle(hEvent); - Logger::instance().out(L"OpenEvent success"); - } - else - { - Logger::instance().out(L"OpenEvent failed, err=%d", GetLastError()); - } - } + // set event if specified + if (!blockingCmd->szEventName.empty()) + { + HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, blockingCmd->szEventName.c_str()); + if (hEvent != NULL) + { + SetEvent(hEvent); + CloseHandle(hEvent); + Logger::instance().out(L"OpenEvent success"); + } + else + { + Logger::instance().out(L"OpenEvent failed, err=%d", GetLastError()); + } + } } void ExecuteCmd::terminateCmd(unsigned long id, unsigned long waitTimeout) @@ -267,54 +266,54 @@ void ExecuteCmd::clearCmd(unsigned long id) for (auto it = blockingCmds_.begin(); it != blockingCmds_.end(); ++it) { BlockingCmd *blockingCmd = *it; - if (blockingCmd->id == id) - { - if (!blockingCmd->bFinished) - { - CloseHandle(blockingCmd->hProcess); - CloseHandle(blockingCmd->hThread); - - UnregisterWaitEx(blockingCmd->hWait, NULL); - } - blockingCmds_.erase(it); - delete blockingCmd; - break; - } + if (blockingCmd->id == id) + { + if (!blockingCmd->bFinished) + { + CloseHandle(blockingCmd->hProcess); + CloseHandle(blockingCmd->hThread); + + UnregisterWaitEx(blockingCmd->hWait, NULL); + } + blockingCmds_.erase(it); + delete blockingCmd; + break; + } } } void ExecuteCmd::clearAllCmds() { - for (auto it = blockingCmds_.begin(); it != blockingCmds_.end(); ++it) - { - BlockingCmd *blockingCmd = *it; - if (!blockingCmd->bFinished) - { - CloseHandle(blockingCmd->hProcess); - CloseHandle(blockingCmd->hThread); - - UnregisterWaitEx(blockingCmd->hWait, NULL); - } - delete blockingCmd; - } - - blockingCmds_.clear(); + for (auto it = blockingCmds_.begin(); it != blockingCmds_.end(); ++it) + { + BlockingCmd *blockingCmd = *it; + if (!blockingCmd->bFinished) + { + CloseHandle(blockingCmd->hProcess); + CloseHandle(blockingCmd->hThread); + + UnregisterWaitEx(blockingCmd->hWait, NULL); + } + delete blockingCmd; + } + + blockingCmds_.clear(); } BOOL ExecuteCmd::isTokenElevated(HANDLE handle) { - TOKEN_ELEVATION Elevation; - DWORD cbSize = sizeof(TOKEN_ELEVATION); - if (GetTokenInformation(handle, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) - { - return Elevation.TokenIsElevated; - } - - return FALSE; + TOKEN_ELEVATION Elevation; + DWORD cbSize = sizeof(TOKEN_ELEVATION); + if (GetTokenInformation(handle, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) + { + return Elevation.TokenIsElevated; + } + + return FALSE; } void ExecuteCmd::safeCloseHandle(HANDLE handle) { - if (handle) - CloseHandle(handle); + if (handle) + CloseHandle(handle); } diff --git a/backend/windows/windscribe_service/executecmd.h b/backend/windows/windscribe_service/executecmd.h index 61fb04eeb..ad5ff705f 100644 --- a/backend/windows/windscribe_service/executecmd.h +++ b/backend/windows/windscribe_service/executecmd.h @@ -1,5 +1,6 @@ -#ifndef EXECUTECMD_H -#define EXECUTECMD_H +#pragma once + +#include #include @@ -15,11 +16,11 @@ class ExecuteCmd return i; } - MessagePacketResult executeBlockingCmd(wchar_t *cmd, HANDLE user_token = INVALID_HANDLE_VALUE); - MessagePacketResult executeUnblockingCmd(const wchar_t *cmd, const wchar_t *szEventName, const wchar_t *szWorkingDir); - MessagePacketResult getUnblockingCmdStatus(unsigned long cmdId); + MessagePacketResult executeBlockingCmd(const std::wstring &cmd, HANDLE user_token = INVALID_HANDLE_VALUE); + MessagePacketResult executeUnblockingCmd(const std::wstring &cmd, const wchar_t *szEventName, const std::wstring &workingDir); + MessagePacketResult getUnblockingCmdStatus(unsigned long cmdId); MessagePacketResult getActiveUnblockingCmdCount(); - MessagePacketResult clearUnblockingCmd(unsigned long id); + MessagePacketResult clearUnblockingCmd(unsigned long id); MessagePacketResult suspendUnblockingCmd(unsigned long id); private: @@ -32,9 +33,9 @@ class ExecuteCmd struct BlockingCmd { unsigned long id; - std::wstring szEventName; + std::wstring szEventName; - PipeForProcess pipeForProcess; + PipeForProcess pipeForProcess; HANDLE hProcess; HANDLE hThread; HANDLE hWait; @@ -56,11 +57,9 @@ class ExecuteCmd void terminateCmd(unsigned long id, unsigned long waitTimeout); void suspendCmd(unsigned long id); - void clearCmd(unsigned long id); - void clearAllCmds(); + void clearCmd(unsigned long id); + void clearAllCmds(); - BOOL isTokenElevated(HANDLE handle); - void safeCloseHandle(HANDLE handle); + BOOL isTokenElevated(HANDLE handle); + void safeCloseHandle(HANDLE handle); }; - -#endif // EXECUTECMD_H diff --git a/backend/windows/windscribe_service/fwpm_wrapper.cpp b/backend/windows/windscribe_service/fwpm_wrapper.cpp index e3173cddd..c47f68a3c 100644 --- a/backend/windows/windscribe_service/fwpm_wrapper.cpp +++ b/backend/windows/windscribe_service/fwpm_wrapper.cpp @@ -7,7 +7,7 @@ FwpmWrapper::FwpmWrapper() DWORD dwFwAPiRetCode = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, NULL, &engineHandle_); if (dwFwAPiRetCode != ERROR_SUCCESS) { - Logger::instance().out(L"EngineHandleWrapper::EngineHandleWrapper(), FwpmEngineOpen0 failed"); + Logger::instance().out(L"EngineHandleWrapper::EngineHandleWrapper(), FwpmEngineOpen0 failed, %lu", dwFwAPiRetCode); engineHandle_ = NULL; } } @@ -41,7 +41,7 @@ bool FwpmWrapper::beginTransaction() DWORD dwFwAPiRetCode = FwpmTransactionBegin0(engineHandle_, NULL); if (dwFwAPiRetCode != ERROR_SUCCESS) { - Logger::instance().out(L"FwpmWrapper::beginTransaction(), FwpmTransactionBegin0 failed"); + Logger::instance().out(L"FwpmWrapper::beginTransaction(), FwpmTransactionBegin0 failed, %lu", dwFwAPiRetCode); return false; } return true; @@ -52,7 +52,7 @@ bool FwpmWrapper::endTransaction() DWORD dwFwAPiRetCode = FwpmTransactionCommit0(engineHandle_); if (dwFwAPiRetCode != ERROR_SUCCESS) { - Logger::instance().out(L"FwpmWrapper::endTransaction(), FwpmTransactionCommit0 failed"); + Logger::instance().out(L"FwpmWrapper::endTransaction(), FwpmTransactionCommit0 failed, %lu", dwFwAPiRetCode); return false; } return true; diff --git a/backend/windows/windscribe_service/split_tunneling/callout_filter.cpp b/backend/windows/windscribe_service/split_tunneling/callout_filter.cpp index f55a38c28..52695414f 100644 --- a/backend/windows/windscribe_service/split_tunneling/callout_filter.cpp +++ b/backend/windows/windscribe_service/split_tunneling/callout_filter.cpp @@ -50,7 +50,7 @@ CalloutFilter::CalloutFilter(FwpmWrapper &fwmpWrapper): fwmpWrapper_(fwmpWrapper { } -void CalloutFilter::enable(UINT32 localIp, UINT32 vpnIp, const AppsIds &appsIds, bool isExclude, bool isAllowLanTraffic) +void CalloutFilter::enable(UINT32 localIp, UINT32 vpnIp, const AppsIds &windscribeMainExecutableIds, const AppsIds &appsIds, bool isExclude, bool isAllowLanTraffic) { std::lock_guard guard(mutex_); @@ -102,7 +102,7 @@ void CalloutFilter::enable(UINT32 localIp, UINT32 vpnIp, const AppsIds &appsIds, success = false; } - if (success && !addFilters(hEngine, !isExclude && isAllowLanTraffic)) + if (success && !addFilters(hEngine, !isExclude && isAllowLanTraffic, windscribeMainExecutableIds, appsIds)) { Logger::instance().out(L"CalloutFilter::enable(), addFilters failed"); success = false; @@ -212,7 +212,7 @@ bool CalloutFilter::addSubLayer(HANDLE engineHandle) return true; } -bool CalloutFilter::addFilters(HANDLE engineHandle, bool withTcpFilters) +bool CalloutFilter::addFilters(HANDLE engineHandle, bool withTcpFilters, const AppsIds &windscribeMainExecutableIds, const AppsIds &appsIds) { bool retValue = true; const std::vector lanRanges = { @@ -233,19 +233,70 @@ bool CalloutFilter::addFilters(HANDLE engineHandle, bool withTcpFilters) std::vector addrMasks(lanRanges.size()); std::vector localAddrMasks; - if (appsIds_.count() == 0) { + if (appsIds.count() == 0 && windscribeMainExecutableIds.count() == 0) { return true; } - // All traffic goes to BIND filter + // Windscribe main program traffic goes to the bind filter except UDP traffic. Otherwise, DNS resolution in Windscribe app via 127.0.0.1(ctrld util) will not work. + // Not an elegant solution, but working for now. Maybe redo it later when ideas come up. + if (!prevIsExclude_ && windscribeMainExecutableIds.count() > 0) // (only for the inclusive mode) { - std::vector conditions(appsIds_.count()); - for (size_t i = 0; i < appsIds_.count(); ++i) + std::vector conditions; + conditions.reserve(windscribeMainExecutableIds.count()); + for (size_t i = 0; i < windscribeMainExecutableIds.count(); ++i) { - conditions[i].fieldKey = FWPM_CONDITION_ALE_APP_ID; - conditions[i].matchType = FWP_MATCH_EQUAL; - conditions[i].conditionValue.type = FWP_BYTE_BLOB_TYPE; - conditions[i].conditionValue.byteBlob = appsIds_.getAppId(i); + FWPM_FILTER_CONDITION condition; + condition.fieldKey = FWPM_CONDITION_ALE_APP_ID; + condition.matchType = FWP_MATCH_EQUAL; + condition.conditionValue.type = FWP_BYTE_BLOB_TYPE; + condition.conditionValue.byteBlob = (FWP_BYTE_BLOB *)windscribeMainExecutableIds.getAppId(i); + conditions.push_back(condition); + } + + // Skip UDP protocol + if (!prevIsExclude_) { + FWPM_FILTER_CONDITION condition; + condition.fieldKey = FWPM_CONDITION_IP_PROTOCOL; + condition.matchType = FWP_MATCH_NOT_EQUAL; + condition.conditionValue.type = FWP_UINT8; + condition.conditionValue.uint8 = 17; // UDP protocol code as specified in RFC 1700 (see docs) + conditions.push_back(condition); + } + + FWPM_FILTER filter = { 0 }; + filter.subLayerKey = SUBLAYER_CALLOUT_GUID; + filter.layerKey = FWPM_LAYER_ALE_BIND_REDIRECT_V4; + filter.displayData.name = (wchar_t *)L"Windscribe main executable bind filter for callout driver"; + filter.weight.type = FWP_UINT8; + filter.weight.uint8 = 0x01; + filter.providerContextKey = CALLOUT_PROVIDER_CONTEXT_IP_GUID; + filter.flags |= FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT; + filter.numFilterConditions = static_cast(conditions.size()); + filter.filterCondition = &conditions[0]; + filter.action.type = FWP_ACTION_CALLOUT_UNKNOWN; + filter.action.calloutKey = WINDSCRIBE_BIND_CALLOUT_GUID; + + UINT64 filterId; + DWORD ret = FwpmFilterAdd(engineHandle, &filter, NULL, &filterId); + retValue = (ret == ERROR_SUCCESS); + if (!retValue) { + Logger::instance().out(L"CalloutFilter::addFilter(), bind filter for Windscribe main executable failed: %u", ret); + return retValue; + } + } + + // All other traffic for apps goes to BIND filter + { + std::vector conditions; + conditions.reserve(appsIds.count()); + for (size_t i = 0; i < appsIds.count(); ++i) + { + FWPM_FILTER_CONDITION condition; + condition.fieldKey = FWPM_CONDITION_ALE_APP_ID; + condition.matchType = FWP_MATCH_EQUAL; + condition.conditionValue.type = FWP_BYTE_BLOB_TYPE; + condition.conditionValue.byteBlob = (FWP_BYTE_BLOB *)appsIds.getAppId(i); + conditions.push_back(condition); } FWPM_FILTER filter = { 0 }; @@ -323,13 +374,13 @@ bool CalloutFilter::addFilters(HANDLE engineHandle, bool withTcpFilters) std::vector conditions; // Must match one of the apps - for (size_t i = 0; i < appsIds_.count(); ++i) + for (size_t i = 0; i < appsIds.count(); ++i) { FWPM_FILTER_CONDITION condition; condition.fieldKey = FWPM_CONDITION_ALE_APP_ID; condition.matchType = FWP_MATCH_EQUAL; condition.conditionValue.type = FWP_BYTE_BLOB_TYPE; - condition.conditionValue.byteBlob = appsIds_.getAppId(i); + condition.conditionValue.byteBlob = (FWP_BYTE_BLOB *)appsIds.getAppId(i); conditions.push_back(condition); } @@ -409,4 +460,4 @@ bool CalloutFilter::removeAllFilters(FwpmWrapper &fwmpWrapper) fwmpWrapper.unlock(); return true; -} \ No newline at end of file +} diff --git a/backend/windows/windscribe_service/split_tunneling/callout_filter.h b/backend/windows/windscribe_service/split_tunneling/callout_filter.h index c5f3febd5..061be2753 100644 --- a/backend/windows/windscribe_service/split_tunneling/callout_filter.h +++ b/backend/windows/windscribe_service/split_tunneling/callout_filter.h @@ -8,7 +8,7 @@ class CalloutFilter public: explicit CalloutFilter(FwpmWrapper &fwmpWrapper); - void enable(UINT32 localIp, UINT32 vpnIp, const AppsIds &appsIds, bool isExclude, bool allowLanTraffic); + void enable(UINT32 localIp, UINT32 vpnIp, const AppsIds &windscribeMainExecutableIds, const AppsIds &appsIds, bool isExclude, bool allowLanTraffic); void disable(); static bool removeAllFilters(FwpmWrapper &fwmpWrapper); @@ -17,7 +17,7 @@ class CalloutFilter bool addProviderContext(HANDLE engineHandle, const GUID &guid, UINT32 localIp, UINT32 vpnIp, bool isExclude); bool addCallouts(HANDLE engineHandle); bool addSubLayer(HANDLE engineHandle); - bool addFilters(HANDLE engineHandle, bool withTcpFilters); + bool addFilters(HANDLE engineHandle, bool withTcpFilters, const AppsIds &windscribeMainExecutableIds, const AppsIds &appsIds); static bool deleteSublayer(HANDLE engineHandle); diff --git a/backend/windows/windscribe_service/split_tunneling/routes_manager.cpp b/backend/windows/windscribe_service/split_tunneling/routes_manager.cpp index 1b7ba4cbe..26568b955 100644 --- a/backend/windows/windscribe_service/split_tunneling/routes_manager.cpp +++ b/backend/windows/windscribe_service/split_tunneling/routes_manager.cpp @@ -119,9 +119,4 @@ void RoutesManager::addDnsRoutes(const CMD_CONNECT_STATUS &connectStatus) // 10.255.255.0/24 contains the default DNS servers, on-node APIs, decoy traffic servers, etc // and always goes through the tunnel. dnsServersRoutes_.addRoute(table, "10.255.255.0", "255.255.255.0", connectStatus.vpnAdapter.gatewayIp, connectStatus.vpnAdapter.ifIndex, false); - - // However the DNS server may fall outside the above range if configured with custom DNS after connecting. - // Set a /32 for each DNS server to make sure they are routed correctly. - for (auto it = connectStatus.vpnAdapter.dnsServers.begin(); it != connectStatus.vpnAdapter.dnsServers.end(); ++it) - dnsServersRoutes_.addRoute(table, *it, "255.255.255.255", connectStatus.vpnAdapter.gatewayIp, connectStatus.vpnAdapter.ifIndex, false); -} \ No newline at end of file +} diff --git a/backend/windows/windscribe_service/split_tunneling/split_tunneling.cpp b/backend/windows/windscribe_service/split_tunneling/split_tunneling.cpp index 5a619c9ae..0f08d87e3 100644 --- a/backend/windows/windscribe_service/split_tunneling/split_tunneling.cpp +++ b/backend/windows/windscribe_service/split_tunneling/split_tunneling.cpp @@ -12,7 +12,11 @@ SplitTunneling::SplitTunneling(FirewallFilter& firewallFilter, FwpmWrapper& fwmp { connectStatus_.isConnected = false; detectWindscribeExecutables(); - firewallFilter_.setWindscribeAppsIds(windscribeExecutablesIds_); + + AppsIds appIds; + appIds.addFrom(windscribeMainExecutableIds_); + appIds.addFrom(windscribeToolsExecutablesIds_); + firewallFilter_.setWindscribeAppsIds(appIds); } SplitTunneling::~SplitTunneling() @@ -65,17 +69,25 @@ void SplitTunneling::detectWindscribeExecutables() return; } - std::vector windscribeExeFiles; + std::vector windscribeToolsExeFiles; + std::vector mainWindscribeExefile; do { if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - std::wstring f = exePath + L"\\" + ffd.cFileName; - windscribeExeFiles.push_back(f); + std::wstring fileName = ffd.cFileName; + std::wstring fullPath = exePath + L"\\" + ffd.cFileName; + + if (fileName == L"Windscribe.exe") { + mainWindscribeExefile.push_back(fullPath); + } else if (fileName != L"windscribectrld.exe") { // skip windscribectrld.exe + windscribeToolsExeFiles.push_back(fullPath); + } } } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); - windscribeExecutablesIds_.setFromList(windscribeExeFiles); + windscribeMainExecutableIds_.setFromList(mainWindscribeExefile); + windscribeToolsExecutablesIds_.setFromList(windscribeToolsExeFiles); } bool SplitTunneling::updateState() @@ -112,10 +124,10 @@ bool SplitTunneling::updateState() if (isExclude_) { hostnamesManager_.enable(connectStatus_.defaultAdapter.gatewayIp, connectStatus_.defaultAdapter.ifIndex); } else { - appsIds.addFrom(windscribeExecutablesIds_); + appsIds.addFrom(windscribeToolsExecutablesIds_); hostnamesManager_.enable(connectStatus_.vpnAdapter.gatewayIp, connectStatus_.vpnAdapter.ifIndex); } - calloutFilter_.enable(localIp, vpnIp, appsIds, isExclude_, isAllowLanTraffic_); + calloutFilter_.enable(localIp, vpnIp, windscribeMainExecutableIds_, appsIds, isExclude_, isAllowLanTraffic_); } else { calloutFilter_.disable(); hostnamesManager_.disable(); diff --git a/backend/windows/windscribe_service/split_tunneling/split_tunneling.h b/backend/windows/windscribe_service/split_tunneling/split_tunneling.h index 96d49d464..cca5d87d9 100644 --- a/backend/windows/windscribe_service/split_tunneling/split_tunneling.h +++ b/backend/windows/windscribe_service/split_tunneling/split_tunneling.h @@ -28,7 +28,9 @@ class SplitTunneling HostnamesManager hostnamesManager_; SplitTunnelServiceManager splitTunnelServiceManager_; - AppsIds windscribeExecutablesIds_; + AppsIds windscribeMainExecutableIds_; // Windscribe.exe + AppsIds windscribeToolsExecutablesIds_; // all other executables in the Windscribe app folder except Windscribe.exe + CMD_CONNECT_STATUS connectStatus_; bool isSplitTunnelEnabled_ = false; bool isExclude_ = false; diff --git a/backend/windows/windscribe_service/utils.cpp b/backend/windows/windscribe_service/utils.cpp index 5a6c49a7b..5708b9aaf 100644 --- a/backend/windows/windscribe_service/utils.cpp +++ b/backend/windows/windscribe_service/utils.cpp @@ -437,7 +437,7 @@ bool addFilterV4(HANDLE engineHandle, std::vector *filterId, FWP_ACTION_ condition.fieldKey = FWPM_CONDITION_ALE_APP_ID; condition.matchType = FWP_MATCH_EQUAL; condition.conditionValue.type = FWP_BYTE_BLOB_TYPE; - condition.conditionValue.byteBlob = (*appsIds).getAppId(i); + condition.conditionValue.byteBlob = (FWP_BYTE_BLOB *)(*appsIds).getAppId(i); conditions.push_back(condition); } } @@ -523,4 +523,16 @@ bool addFilterV6(HANDLE engineHandle, std::vector *filterId, FWP_ACTION_ return success; } +std::wstring getSystemDir() +{ + wchar_t path[MAX_PATH]; + UINT result = ::GetSystemDirectory(path, MAX_PATH); + if (result == 0 || result >= MAX_PATH) { + Logger::instance().out("GetSystemDir failed (%lu)", ::GetLastError()); + return std::wstring(L"C:\\Windows\\System32"); + } + + return std::wstring(path); +} + } diff --git a/backend/windows/windscribe_service/utils.h b/backend/windows/windscribe_service/utils.h index b7eaa5a99..4ddb6cd35 100644 --- a/backend/windows/windscribe_service/utils.h +++ b/backend/windows/windscribe_service/utils.h @@ -23,6 +23,7 @@ namespace Utils std::wstring guidToStr(const GUID &guid); std::wstring getExePath(); std::wstring getDirPathFromFullPath(std::wstring &fullPath); + std::wstring getSystemDir(); bool isValidFileName(std::wstring &filename); bool isFileExists(const wchar_t *path); bool noSpacesInString(std::wstring &str); diff --git a/backend/windows/windscribe_service/windscribe_service.cpp b/backend/windows/windscribe_service/windscribe_service.cpp index 0a38cab21..5aa34201c 100644 --- a/backend/windows/windscribe_service/windscribe_service.cpp +++ b/backend/windows/windscribe_service/windscribe_service.cpp @@ -1,32 +1,33 @@ #include "all_headers.h" -#include "split_tunneling/split_tunneling.h" -#include "ipv6_firewall.h" + +#include + +#include "../../../client/common/utils/crashhandler.h" +#include "../changeics/icsmanager.h" +#include "cleardns_on_tap.h" +#include "close_tcp_connections.h" #include "dns_firewall.h" +#include "executecmd.h" #include "firewallfilter.h" -#include "logger.h" -#include "ipc/servicecommunication.h" -#include "../changeics/icsmanager.h" -#include "sys_ipv6_controller.h" -#include "hostsedit.h" +#include "fwpm_wrapper.h" #include "get_active_processes.h" -#include "pipe_for_process.h" -#include "executecmd.h" -#include "reinstall_wan_ikev2.h" -#include "close_tcp_connections.h" -#include "cleardns_on_tap.h" -#include "utils.h" -#include "registry.h" +#include "hostsedit.h" #include "ikev2ipsec.h" #include "ikev2route.h" #include "ioutils.h" -#include "ovpn.h" #include "ipc/serialize_structs.h" -#include "fwpm_wrapper.h" +#include "ipc/servicecommunication.h" +#include "ipv6_firewall.h" +#include "logger.h" +#include "ovpn.h" +#include "registry.h" +#include "reinstall_tun_drivers.h" +#include "reinstall_wan_ikev2.h" #include "remove_windscribe_network_profiles.h" +#include "split_tunneling/split_tunneling.h" +#include "sys_ipv6_controller.h" +#include "utils.h" #include "wireguard/wireguardcontroller.h" -#include "reinstall_tun_drivers.h" -#include -#include "../../../client/common/utils/crashhandler.h" #define SERVICE_NAME (L"WindscribeService") #define SERVICE_PIPE_NAME (L"\\\\.\\pipe\\WindscribeService") @@ -101,7 +102,7 @@ int main(int argc, char *argv[]) CloseHandle(hThread); CloseHandle (g_ServiceStopEvent); #else - + SERVICE_TABLE_ENTRY serviceTable[] = { { (LPWSTR)SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)serviceMain }, @@ -117,20 +118,20 @@ int main(int argc, char *argv[]) return 0; } -BOOL isElevated() +BOOL isElevated() { BOOL fRet = FALSE; HANDLE hToken = NULL; - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { TOKEN_ELEVATION Elevation; DWORD cbSize = sizeof(TOKEN_ELEVATION); - if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) + if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) { fRet = Elevation.TokenIsElevated; } } - if (hToken) + if (hToken) { CloseHandle(hToken); } @@ -263,7 +264,7 @@ VOID WINAPI serviceCtrlHandler(DWORD CtrlCode) BOOL CreateDACL(SECURITY_ATTRIBUTES *pSA) { - TCHAR * szSD = TEXT("D:") // Discretionary ACL + const TCHAR * szSD = TEXT("D:") // Discretionary ACL TEXT("(D;OICI;GA;;;AN)") // Deny access to anonymous logon TEXT("(A;OICI;GRGWGX;;;BG)") // Allow access to built-in guests TEXT("(A;OICI;GRGWGX;;;AU)") // Allow read/write/execute to authenticated users @@ -272,7 +273,7 @@ BOOL CreateDACL(SECURITY_ATTRIBUTES *pSA) if (NULL == pSA) return FALSE; - return ConvertStringSecurityDescriptorToSecurityDescriptor(szSD, SDDL_REVISION_1, &(pSA->lpSecurityDescriptor), NULL); + return ConvertStringSecurityDescriptorToSecurityDescriptor(szSD, SDDL_REVISION_1, &(pSA->lpSecurityDescriptor), NULL); } HANDLE CreatePipe() @@ -542,7 +543,7 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I else if (cmdId == AA_COMMAND_ENUM_PROCESSES) { Logger::instance().out(L"AA_COMMAND_ENUM_PROCESSES"); - + std::vector list = getActiveProcesses.getList(); size_t overallCharactersCount = 0; @@ -566,7 +567,7 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I } mpr.additionalString = std::string(v.begin(), v.end()); } - + mpr.success = true; } else if (cmdId == AA_COMMAND_TASK_KILL) @@ -574,10 +575,8 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I CMD_TASK_KILL cmdTaskKill; ia >> cmdTaskKill; - wchar_t killCmd[MAX_PATH]; - wcscpy(killCmd, L"taskkill /f /t /im "); - wcscat(killCmd, cmdTaskKill.szExecutableName.c_str()); - Logger::instance().out(L"AA_COMMAND_TASK_KILL, cmd=%s", killCmd); + std::wstring killCmd = Utils::getSystemDir() + L"\\taskkill.exe /f /t /im " + cmdTaskKill.szExecutableName; + Logger::instance().out(L"AA_COMMAND_TASK_KILL, cmd=%s", killCmd.c_str()); mpr = ExecuteCmd::instance().executeBlockingCmd(killCmd); } else if (cmdId == AA_COMMAND_RESET_TAP) @@ -585,17 +584,13 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I CMD_RESET_TAP cmdResetTap; ia >> cmdResetTap; - wchar_t resetCmd[MAX_PATH]; - wcscpy(resetCmd, L"wmic path win32_networkadapter where Description=\""); - wcscat(resetCmd, cmdResetTap.szTapName.c_str()); - wcscat(resetCmd, L"\" call disable"); - Logger::instance().out(L"AA_COMMAND_RESET_TAP, cmd1=%s", resetCmd); + std::wstring baseCmd = Utils::getSystemDir() + L"\\wbem\\wmic.exe path win32_networkadapter where Description=\"" + cmdResetTap.szTapName + L"\""; + std::wstring resetCmd = baseCmd + L" call disable"; + Logger::instance().out(L"AA_COMMAND_RESET_TAP, cmd1=%s", resetCmd.c_str()); mpr = ExecuteCmd::instance().executeBlockingCmd(resetCmd); - wcscpy(resetCmd, L"wmic path win32_networkadapter where Description=\""); - wcscat(resetCmd, cmdResetTap.szTapName.c_str()); - wcscat(resetCmd, L"\" call enable"); - Logger::instance().out(L"AA_COMMAND_RESET_TAP, cmd2=%s", resetCmd); + resetCmd = baseCmd + L" call enable"; + Logger::instance().out(L"AA_COMMAND_RESET_TAP, cmd2=%s", resetCmd.c_str()); mpr = ExecuteCmd::instance().executeBlockingCmd(resetCmd); } else if (cmdId == AA_COMMAND_SET_METRIC) @@ -603,15 +598,9 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I CMD_SET_METRIC cmdSetMetric; ia >> cmdSetMetric; - wchar_t setMetricCmd[MAX_PATH]; - wcscpy(setMetricCmd, L"netsh int "); - wcscat(setMetricCmd, cmdSetMetric.szInterfaceType.c_str()); - wcscat(setMetricCmd, L" set interface interface=\""); - wcscat(setMetricCmd, cmdSetMetric.szInterfaceName.c_str()); - wcscat(setMetricCmd, L"\" metric="); - wcscat(setMetricCmd, cmdSetMetric.szMetricNumber.c_str()); - - Logger::instance().out(L"AA_COMMAND_SET_METRIC, cmd=%s", setMetricCmd); + std::wstring setMetricCmd = Utils::getSystemDir() + L"\\netsh.exe int " + cmdSetMetric.szInterfaceType + L" set interface interface=\"" + + cmdSetMetric.szInterfaceName + L"\" metric=" + cmdSetMetric.szMetricNumber; + Logger::instance().out(L"AA_COMMAND_SET_METRIC, cmd=%s", setMetricCmd.c_str()); mpr = ExecuteCmd::instance().executeBlockingCmd(setMetricCmd); } else if (cmdId == AA_COMMAND_WMIC_ENABLE) @@ -619,12 +608,8 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I CMD_WMIC_ENABLE cmdWmicEnable; ia >> cmdWmicEnable; - wchar_t wmicCmd[MAX_PATH]; - wcscpy(wmicCmd, L"wmic path win32_networkadapter where description=\""); - wcscat(wmicCmd, cmdWmicEnable.szAdapterName.c_str()); - wcscat(wmicCmd, L"\" call enable"); - - Logger::instance().out(L"AA_COMMAND_WMIC_ENABLE, cmd=%s", wmicCmd); + std::wstring wmicCmd = Utils::getSystemDir() + L"\\wbem\\wmic.exe path win32_networkadapter where description=\"" + cmdWmicEnable.szAdapterName + L"\" call enable"; + Logger::instance().out(L"AA_COMMAND_WMIC_ENABLE, cmd=%s", wmicCmd.c_str()); mpr = ExecuteCmd::instance().executeBlockingCmd(wmicCmd); } else if (cmdId == AA_COMMAND_WMIC_GET_CONFIG_ERROR_CODE) @@ -632,12 +617,8 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I CMD_WMIC_GET_CONFIG_ERROR_CODE cmdWmicGetConfigErrorCode; ia >> cmdWmicGetConfigErrorCode; - wchar_t wmicCmd[MAX_PATH]; - wcscpy(wmicCmd, L"wmic path win32_networkadapter where description=\""); - wcscat(wmicCmd, cmdWmicGetConfigErrorCode.szAdapterName.c_str()); - wcscat(wmicCmd, L"\" get ConfigManagerErrorCode"); - - Logger::instance().out(L"AA_COMMAND_WMIC_GET_CONFIG_ERROR_CODE, cmd=%s", wmicCmd); + std::wstring wmicCmd = Utils::getSystemDir() + L"\\wbem\\wmic.exe path win32_networkadapter where description=\"" + cmdWmicGetConfigErrorCode.szAdapterName + L"\" get ConfigManagerErrorCode"; + Logger::instance().out(L"AA_COMMAND_WMIC_GET_CONFIG_ERROR_CODE, cmd=%s", wmicCmd.c_str()); mpr = ExecuteCmd::instance().executeBlockingCmd(wmicCmd); } else if (cmdId == AA_COMMAND_CLEAR_DNS_ON_TAP) @@ -650,30 +631,21 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I { Logger::instance().out(L"AA_COMMAND_ENABLE_BFE"); - wchar_t bfeCmd[MAX_PATH]; - wcscpy(bfeCmd, L"sc config BFE start= auto"); - mpr = ExecuteCmd::instance().executeBlockingCmd(bfeCmd); - wcscpy(bfeCmd, L"sc start BFE"); - mpr = ExecuteCmd::instance().executeBlockingCmd(bfeCmd); + std::wstring exe = Utils::getSystemDir() + L"\\sc.exe"; + mpr = ExecuteCmd::instance().executeBlockingCmd(exe + L" config BFE start= auto"); + mpr = ExecuteCmd::instance().executeBlockingCmd(exe + L" start BFE"); } else if (cmdId == AA_COMMAND_RESET_AND_START_RAS) { Logger::instance().out(L"AA_COMMAND_RESET_AND_START_RAS"); - wchar_t serviceCmd[MAX_PATH]; - wcscpy(serviceCmd, L"sc config RasMan start= demand"); - mpr = ExecuteCmd::instance().executeBlockingCmd(serviceCmd); - wcscpy(serviceCmd, L"sc stop RasMan"); - mpr = ExecuteCmd::instance().executeBlockingCmd(serviceCmd); - wcscpy(serviceCmd, L"sc start RasMan"); - mpr = ExecuteCmd::instance().executeBlockingCmd(serviceCmd); - - wcscpy(serviceCmd, L"sc config SstpSvc start= demand"); - mpr = ExecuteCmd::instance().executeBlockingCmd(serviceCmd); - wcscpy(serviceCmd, L"sc stop SstpSvc"); - mpr = ExecuteCmd::instance().executeBlockingCmd(serviceCmd); - wcscpy(serviceCmd, L"sc start SstpSvc"); - mpr = ExecuteCmd::instance().executeBlockingCmd(serviceCmd); + std::wstring exe = Utils::getSystemDir() + L"\\sc.exe"; + mpr = ExecuteCmd::instance().executeBlockingCmd(exe + L" config RasMan start= demand"); + mpr = ExecuteCmd::instance().executeBlockingCmd(exe + L" stop RasMan"); + mpr = ExecuteCmd::instance().executeBlockingCmd(exe + L" start RasMan"); + mpr = ExecuteCmd::instance().executeBlockingCmd(exe + L" config SstpSvc start= demand"); + mpr = ExecuteCmd::instance().executeBlockingCmd(exe + L" stop SstpSvc"); + mpr = ExecuteCmd::instance().executeBlockingCmd(exe + L" start SstpSvc"); } else if (cmdId == AA_COMMAND_RUN_OPENVPN) { @@ -685,7 +657,6 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I Utils::noSpacesInString(cmdRunOpenVpn.szHttpProxy) && Utils::noSpacesInString(cmdRunOpenVpn.szSocksProxy)) { - std::wstring filename; int ret = OVPN::writeOVPNFile(filename, cmdRunOpenVpn.szConfig); if (ret) { @@ -703,9 +674,7 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I strCmd += L" --socks-proxy " + cmdRunOpenVpn.szSocksProxy + L" " + std::to_wstring(cmdRunOpenVpn.socksPortNumber); } - wchar_t szWorkingDir[MAX_PATH]; - wcscpy(szWorkingDir, Utils::getDirPathFromFullPath(filename).c_str()); - mpr = ExecuteCmd::instance().executeUnblockingCmd(strCmd.c_str(), L"", szWorkingDir); + mpr = ExecuteCmd::instance().executeUnblockingCmd(strCmd.c_str(), L"", Utils::getDirPathFromFullPath(filename)); } } else @@ -718,32 +687,27 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I CMD_WHITELIST_PORTS cmdWhitelistPorts; ia >> cmdWhitelistPorts; - wchar_t szBuf[1024]; - std::wstring strCmd = L"netsh advfirewall firewall add rule name=\"WindscribeStaticIpTcp\" protocol=TCP dir=in localport=\""; + std::wstring strCmd = Utils::getSystemDir() + L"\\netsh.exe advfirewall firewall add rule name=\"WindscribeStaticIpTcp\" protocol=TCP dir=in localport=\""; strCmd += cmdWhitelistPorts.ports; strCmd += L"\" action=allow"; - wcscpy(szBuf, strCmd.c_str()); - mpr = ExecuteCmd::instance().executeBlockingCmd(szBuf); Logger::instance().out(L"AA_COMMAND_WHITELIST_PORTS, cmd=%s", strCmd.c_str()); + mpr = ExecuteCmd::instance().executeBlockingCmd(strCmd); - strCmd = L"netsh advfirewall firewall add rule name=\"WindscribeStaticIpUdp\" protocol=UDP dir=in localport=\""; + strCmd = Utils::getSystemDir() + L"\\netsh.exe advfirewall firewall add rule name=\"WindscribeStaticIpUdp\" protocol=UDP dir=in localport=\""; strCmd += cmdWhitelistPorts.ports; strCmd += L"\" action=allow"; - wcscpy(szBuf, strCmd.c_str()); - mpr = ExecuteCmd::instance().executeBlockingCmd(szBuf); Logger::instance().out(L"AA_COMMAND_WHITELIST_PORTS, cmd=%s", strCmd.c_str()); + mpr = ExecuteCmd::instance().executeBlockingCmd(strCmd); } else if (cmdId == AA_COMMAND_DELETE_WHITELIST_PORTS) { - wchar_t szBuf[1024]; - std::wstring strCmd = L"netsh advfirewall firewall delete rule name=\"WindscribeStaticIpTcp\" dir=in"; - wcscpy(szBuf, strCmd.c_str()); - mpr = ExecuteCmd::instance().executeBlockingCmd(szBuf); + std::wstring strCmd = Utils::getSystemDir() + L"\\netsh.exe advfirewall firewall delete rule name=\"WindscribeStaticIpTcp\" dir=in"; Logger::instance().out(L"AA_COMMAND_DELETE_WHITELIST_PORTS, cmd=%s", strCmd.c_str()); - strCmd = L"netsh advfirewall firewall delete rule name=\"WindscribeStaticIpUdp\" dir=in"; - wcscpy(szBuf, strCmd.c_str()); - mpr = ExecuteCmd::instance().executeBlockingCmd(szBuf); + mpr = ExecuteCmd::instance().executeBlockingCmd(strCmd); + + strCmd = Utils::getSystemDir() + L"\\netsh.exe advfirewall firewall delete rule name=\"WindscribeStaticIpUdp\" dir=in"; Logger::instance().out(L"AA_COMMAND_DELETE_WHITELIST_PORTS, cmd=%s", strCmd.c_str()); + mpr = ExecuteCmd::instance().executeBlockingCmd(strCmd); } else if (cmdId == AA_COMMAND_SET_MAC_ADDRESS_REGISTRY_VALUE_SZ) { @@ -773,7 +737,7 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I std::wstring keyPath = L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\" + cmdRemoveMacAddressRegistryProperty.szInterfaceName; wchar_t keyPathSz[128]; - wcscpy(keyPathSz, keyPath.c_str()); + wcsncpy_s(keyPathSz, 128, keyPath.c_str(), _TRUNCATE); bool success1 = Registry::regDeleteProperty(HKEY_LOCAL_MACHINE, keyPathSz, propertyName); bool success2 = false; @@ -839,7 +803,7 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I cmdSplitTunnelingSettings.ips, cmdSplitTunnelingSettings.hosts, cmdSplitTunnelingSettings.isAllowLanTraffic); - + g_SplitTunnelingPars.isEnabled = cmdSplitTunnelingSettings.isActive; g_SplitTunnelingPars.isExclude = cmdSplitTunnelingSettings.isExclude; g_SplitTunnelingPars.apps = cmdSplitTunnelingSettings.files; @@ -859,20 +823,10 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I CMD_CONNECTED_DNS cmdDnsWhileConnected; ia >> cmdDnsWhileConnected; - wchar_t szBuf[1024]; - wcscpy(szBuf, L"netsh interface ipv4 set dns \""); - wcscat(szBuf, std::to_wstring(cmdDnsWhileConnected.ifIndex).c_str()); - wcscat(szBuf, L"\" static "); - wcscat(szBuf, cmdDnsWhileConnected.szDnsIpAddress.c_str()); - mpr = ExecuteCmd::instance().executeBlockingCmd(szBuf); - - wchar_t logBuf[1024]; - wcscpy(logBuf, L"AA_COMMAND_CONNECTED_DNS: "); - wcscat(logBuf, szBuf); - wcscat(logBuf, L" "); - wcscat(logBuf, mpr.success ? L"Success" : L"Failure"); - wcscat(logBuf, L" "); - wcscat(logBuf, std::to_wstring(mpr.exitCode).c_str()); + std::wstring netshCmd = Utils::getSystemDir() + L"\\netsh.exe interface ipv4 set dns \"" + std::to_wstring(cmdDnsWhileConnected.ifIndex) + L"\" static " + cmdDnsWhileConnected.szDnsIpAddress; + mpr = ExecuteCmd::instance().executeBlockingCmd(netshCmd); + + std::wstring logBuf = L"AA_COMMAND_CONNECTED_DNS: " + netshCmd + L" " + (mpr.success ? L"Success" : L"Failure") + L" " + std::to_wstring(mpr.exitCode); Logger::instance().out(logBuf); } else if (cmdId == AA_COMMAND_ADD_IKEV2_DEFAULT_ROUTE) @@ -891,26 +845,15 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I CMD_CHANGE_MTU cmdChangeMtu; ia >> cmdChangeMtu; - std::wstring storePersistent = L"active"; - if (cmdChangeMtu.storePersistent) - { - storePersistent = L"persistent"; + std::wstring netshCmd = Utils::getSystemDir() + L"\\netsh.exe interface ipv4 set subinterface \"" + cmdChangeMtu.szAdapterName + L"\" mtu=" + std::to_wstring(cmdChangeMtu.mtu) + L" store="; + if (cmdChangeMtu.storePersistent) { + netshCmd += L"persistent"; + } else { + netshCmd += L"active"; } - wchar_t szBuf[1024]; - wcscpy(szBuf, L"netsh interface ipv4 set subinterface \""); - wcscat(szBuf, cmdChangeMtu.szAdapterName.c_str()); - wcscat(szBuf, L"\" mtu="); - wcscat(szBuf, std::to_wstring(cmdChangeMtu.mtu).c_str()); - wcscat(szBuf, L" store="); - wcscat(szBuf, storePersistent.c_str()); - mpr = ExecuteCmd::instance().executeBlockingCmd(szBuf); - - wchar_t logBuf[1024]; - wcscpy(logBuf, L"AA_COMMAND_CHANGE_MTU: "); - wcscat(logBuf, szBuf); - Logger::instance().out(logBuf); - + Logger::instance().out(L"AA_COMMAND_CHANGE_MTU: " + netshCmd); + mpr = ExecuteCmd::instance().executeBlockingCmd(netshCmd); mpr.success = true; } else if (cmdId == AA_COMMAND_SET_IKEV2_IPSEC_PARAMETERS) @@ -949,7 +892,7 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I mpr.success = false; } } - else if (cmdId == AA_COMMAND_REINSTALL_TAP_DRIVER) + else if (cmdId == AA_COMMAND_REINSTALL_TAP_DRIVER) { CMD_REINSTALL_TUN_DRIVER cmdReinstallTunDriver; ia >> cmdReinstallTunDriver; @@ -958,7 +901,7 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I { mpr.success = true; } - else + else { mpr.success = false; } @@ -977,7 +920,7 @@ MessagePacketResult processMessagePacket(int cmdId, const std::string &packet, I mpr.success = false; } } - + return mpr; } diff --git a/backend/windows/windscribe_service/wireguard/wireguardcontroller.cpp b/backend/windows/windscribe_service/wireguard/wireguardcontroller.cpp index 038a87760..f6e8e4c7f 100644 --- a/backend/windows/windscribe_service/wireguard/wireguardcontroller.cpp +++ b/backend/windows/windscribe_service/wireguard/wireguardcontroller.cpp @@ -107,10 +107,8 @@ bool WireGuardController::deleteService() if (!bServiceDeleted && !exeName_.empty()) { serviceName_.clear(); - wchar_t killCmd[MAX_PATH]; - wcscpy_s(killCmd, L"taskkill /f /t /im "); - wcscat_s(killCmd, exeName_.c_str()); Logger::instance().out("WireGuardController::deleteService - task killing the WireGuard service instance"); + std::wstring killCmd = Utils::getSystemDir() + L"\\taskkill.exe /f /t /im " + exeName_; ExecuteCmd::instance().executeBlockingCmd(killCmd); } diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 12de3ff18..320ba51f1 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -117,15 +117,13 @@ if (APPLE) add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory $/../Helpers) add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${WINDSCRIBE_BUILD_LIBS_PATH}/openvpn/openvpn $/../Helpers/windscribeopenvpn) - add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${WINDSCRIBE_BUILD_LIBS_PATH}/stunnel/stunnel $/../Helpers/windscribestunnel) add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${WINDSCRIBE_BUILD_LIBS_PATH}/wireguard/windscribewireguard $/../Helpers/windscribewireguard) add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${WINDSCRIBE_BUILD_LIBS_PATH}/ctrld/ctrld $/../Helpers/windscribectrld) add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${CMAKE_CURRENT_SOURCE_DIR}/../backend/mac/wstunnel/windscribewstunnel $/../Helpers/windscribewstunnel) + ${WINDSCRIBE_BUILD_LIBS_PATH}/wstunnel/windscribewstunnel $/../Helpers/windscribewstunnel) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../backend/mac/provisioning_profile/embedded.provisionprofile") add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different diff --git a/client/common/changelog.txt b/client/common/changelog.txt index de701168c..27d0ba8ac 100644 --- a/client/common/changelog.txt +++ b/client/common/changelog.txt @@ -1,3 +1,19 @@ +2.7.10 (07/09/2023) +All: + * Added anti-censorship feature: use domain fronting via CDN for API requests. #688 + * Added new in-house Stealth/Wstunnel application. #718 + * Fixed app may open locations screen to a random tab. #656 + * Fixed "All protocols failed" prompt doesn't show. #712 +Windows: + * Added additional logging to diagnose service startup failure. #704 + * Fixed (reduced) tunnel test time when using OpenVPN-based protocols. #109 + * Fixed no DNS connectivity with custom DoH/DoT resolver and inclusive split tunneling. #710 + * Fixed helper security vulnerability when app installed to custom folder. #719 +macOS: + * Fixed DNS failures with firewall enabled on macOS 14 Sonoma. #714 + * Fixed Stealth/Wstunnel sometimes can't connect. #718 + + 2.7.9 (08/08/2023) All: * Added anti-censorship toggle in preferences. #695 diff --git a/client/common/utils/dga_parameters.h b/client/common/utils/dga_parameters.h index 4325bd983..858e5ae61 100644 --- a/client/common/utils/dga_parameters.h +++ b/client/common/utils/dga_parameters.h @@ -31,5 +31,8 @@ #define PAR_ECH_CONFIG_DOMAIN 800 #define PAR_ECH_DOMAIN 900 +#define PAR_CDN_BACKEND_DOMAIN 1000 +#define PAR_CDN_FRONTEND_DOMAIN 1001 + #endif // PARAMETERS_H diff --git a/client/common/utils/win32handle.h b/client/common/utils/win32handle.h index 4acfa2c4d..6c8728a04 100644 --- a/client/common/utils/win32handle.h +++ b/client/common/utils/win32handle.h @@ -11,19 +11,20 @@ class Win32Handle explicit Win32Handle(HANDLE hWin32Handle = nullptr) : win32Handle_(hWin32Handle) {} - ~Win32Handle(void) { + ~Win32Handle() { closeHandle(); } - bool isValid(void) const { + bool isValid() const { return ((win32Handle_ != nullptr) && (win32Handle_ != INVALID_HANDLE_VALUE)); } - HANDLE getHandle(void) const { return win32Handle_; } + HANDLE getHandle() const { return win32Handle_; } + PHANDLE data() { return &win32Handle_; } void setHandle(HANDLE hNewHandle); - void closeHandle(void); - HANDLE release(void); + void closeHandle(); + HANDLE release(); DWORD wait(DWORD dwTimeout, BOOL bAlertable = FALSE) const; bool isSignaled() const; @@ -32,7 +33,7 @@ class Win32Handle HANDLE win32Handle_; }; -inline void Win32Handle::closeHandle(void) +inline void Win32Handle::closeHandle() { if (isValid()) { ::CloseHandle(win32Handle_); @@ -40,7 +41,7 @@ inline void Win32Handle::closeHandle(void) } } -inline HANDLE Win32Handle::release(void) +inline HANDLE Win32Handle::release() { HANDLE hTemp = win32Handle_; win32Handle_ = nullptr; diff --git a/client/common/version/windscribe_version.h b/client/common/version/windscribe_version.h index 0d6231fb6..60a189146 100644 --- a/client/common/version/windscribe_version.h +++ b/client/common/version/windscribe_version.h @@ -2,7 +2,7 @@ #define WINDSCRIBE_MAJOR_VERSION 2 #define WINDSCRIBE_MINOR_VERSION 7 -#define WINDSCRIBE_BUILD_VERSION 9 +#define WINDSCRIBE_BUILD_VERSION 10 // only one of these should be enabled; neither -> stable //#define WINDSCRIBE_IS_BETA diff --git a/client/engine/engine/connectionmanager/connectionmanager.cpp b/client/engine/engine/connectionmanager/connectionmanager.cpp index 7db5bed70..ecddb2b2e 100644 --- a/client/engine/engine/connectionmanager/connectionmanager.cpp +++ b/client/engine/engine/connectionmanager/connectionmanager.cpp @@ -74,11 +74,10 @@ ConnectionManager::ConnectionManager(QObject *parent, IHelper *helper, INetworkD connect(&connectingTimer_, &QTimer::timeout, this, &ConnectionManager::onConnectingTimeout); stunnelManager_ = new StunnelManager(this, helper); - connect(stunnelManager_, &StunnelManager::stunnelFinished, this, &ConnectionManager::onStunnelFinishedBeforeConnection); + connect(stunnelManager_, &StunnelManager::stunnelStarted, this, &ConnectionManager::onWstunnelStarted); wstunnelManager_ = new WstunnelManager(this, helper); connect(wstunnelManager_, &WstunnelManager::wstunnelStarted, this, &ConnectionManager::onWstunnelStarted); - connect(wstunnelManager_, &WstunnelManager::wstunnelFinished, this, &ConnectionManager::onWstunnelFinishedBeforeConnection); ctrldManager_ = CrossPlatformObjectFactory::createCtrldManager(this, helper, false); @@ -854,24 +853,6 @@ void ConnectionManager::onTimerReconnection() timerReconnection_.stop(); } -void ConnectionManager::onStunnelFinishedBeforeConnection() -{ - state_ = STATE_AUTO_DISCONNECT; - if (connector_) - connector_->startDisconnect(); - else - onConnectionDisconnected(); -} - -void ConnectionManager::onWstunnelFinishedBeforeConnection() -{ - state_ = STATE_AUTO_DISCONNECT; - if (connector_) - connector_->startDisconnect(); - else - onConnectionDisconnected(); -} - void ConnectionManager::onWstunnelStarted() { doConnectPart3(); @@ -950,17 +931,6 @@ void ConnectionManager::doConnectPart2() if (currentConnectionDescr_.connectionNodeType == CONNECTION_NODE_DEFAULT || currentConnectionDescr_.connectionNodeType == CONNECTION_NODE_STATIC_IPS) { - if (currentConnectionDescr_.protocol == types::Protocol::STUNNEL) - { - bool bStunnelConfigSuccess = stunnelManager_->setConfig(currentConnectionDescr_.ip, currentConnectionDescr_.port); - if (!bStunnelConfigSuccess) - { - qCDebug(LOG_CONNECTION) << "Failed create config for stunnel"; - WS_ASSERT(false); - return; - } - } - if (currentConnectionDescr_.protocol.isOpenVpnProtocol()) { @@ -988,33 +958,36 @@ void ConnectionManager::doConnectPart2() qCDebug(LOG_PACKET_SIZE) << "Packet size mode auto - using default MSS (ConnectionManager)"; } - uint portForStunnelOrWStunnel = currentConnectionDescr_.protocol.isStunnelOrWStunnelProtocol() ? - (currentConnectionDescr_.protocol == types::Protocol::STUNNEL ? stunnelManager_->getStunnelPort() : wstunnelManager_->getPort()) : 0; + uint localPort = 0; + if (currentConnectionDescr_.protocol.isStunnelOrWStunnelProtocol()) { + if (currentConnectionDescr_.protocol == types::Protocol::STUNNEL) { + localPort = stunnelManager_->getPort(); + } else { + localPort = wstunnelManager_->getPort(); + } + } - const bool bOvpnSuccess = makeOVPNFile_->generate(lastOvpnConfig_, currentConnectionDescr_.ip, currentConnectionDescr_.protocol, - currentConnectionDescr_.port, portForStunnelOrWStunnel, mss, defaultAdapterInfo_.gateway(), - currentConnectionDescr_.verifyX509name, connectedDnsInfo_.type == CONNECTED_DNS_TYPE_ROBERT ? "" : ctrldManager_->listenIp()); - if (!bOvpnSuccess ) - { + const bool bOvpnSuccess = makeOVPNFile_->generate( + lastOvpnConfig_, currentConnectionDescr_.ip, currentConnectionDescr_.protocol, + currentConnectionDescr_.port, localPort, mss, defaultAdapterInfo_.gateway(), + currentConnectionDescr_.verifyX509name, ""); + if (!bOvpnSuccess) { qCDebug(LOG_CONNECTION) << "Failed create ovpn config"; WS_ASSERT(false); return; } - if (currentConnectionDescr_.protocol == types::Protocol::STUNNEL) - { - if(!stunnelManager_->runProcess()) - { + if (currentConnectionDescr_.protocol == types::Protocol::STUNNEL) { + if (!stunnelManager_->runProcess(currentConnectionDescr_.ip, currentConnectionDescr_.port)) { state_ = STATE_DISCONNECTED; timerReconnection_.stop(); Q_EMIT errorDuringConnection(CONNECT_ERROR::EXE_VERIFY_STUNNEL_ERROR); return; } - } - else if (currentConnectionDescr_.protocol == types::Protocol::WSTUNNEL) - { - if (!wstunnelManager_->runProcess(currentConnectionDescr_.ip, currentConnectionDescr_.port, false)) - { + // call doConnectPart2 in onWstunnelStarted slot + return; + } else if (currentConnectionDescr_.protocol == types::Protocol::WSTUNNEL) { + if (!wstunnelManager_->runProcess(currentConnectionDescr_.ip, currentConnectionDescr_.port)) { state_ = STATE_DISCONNECTED; timerReconnection_.stop(); Q_EMIT errorDuringConnection(CONNECT_ERROR::EXE_VERIFY_WSTUNNEL_ERROR); @@ -1086,12 +1059,23 @@ void ConnectionManager::doConnectPart3() { WireGuardConfig* pConfig = (currentConnectionDescr_.connectionNodeType == CONNECTION_NODE_CUSTOM_CONFIG ? currentConnectionDescr_.wgCustomConfig.get() : &wireGuardConfig_); WS_ASSERT(pConfig != nullptr); - Q_EMIT connectingToHostname(currentConnectionDescr_.hostname, currentConnectionDescr_.ip, - (connectedDnsInfo_.type == CONNECTED_DNS_TYPE_ROBERT) ? pConfig->clientDnsAddress() : ctrldManager_->listenIp()); + + // For WG protocol we need to add upStream1 adrress if it's custom ip. Otherwise on Windows WG may not connect. + QStringList dnsIps; + if (connectedDnsInfo_.type == CONNECTED_DNS_TYPE_ROBERT) { + dnsIps << pConfig->clientDnsAddress(); + } else { + if (IpValidation::isIp(connectedDnsInfo_.upStream1)) { + dnsIps << connectedDnsInfo_.upStream1; + } + dnsIps << ctrldManager_->listenIp(); + } + + Q_EMIT connectingToHostname(currentConnectionDescr_.hostname, currentConnectionDescr_.ip, dnsIps); } else { - Q_EMIT connectingToHostname(currentConnectionDescr_.hostname, currentConnectionDescr_.ip, ""); + Q_EMIT connectingToHostname(currentConnectionDescr_.hostname, currentConnectionDescr_.ip, QStringList()); } if (currentConnectionDescr_.connectionNodeType == CONNECTION_NODE_CUSTOM_CONFIG) diff --git a/client/engine/engine/connectionmanager/connectionmanager.h b/client/engine/engine/connectionmanager/connectionmanager.h index 147dee214..2a076732a 100644 --- a/client/engine/engine/connectionmanager/connectionmanager.h +++ b/client/engine/engine/connectionmanager/connectionmanager.h @@ -90,7 +90,7 @@ class ConnectionManager : public QObject signals: void connected(); - void connectingToHostname(const QString &hostname, const QString &ip, const QString &dnsServer); + void connectingToHostname(const QString &hostname, const QString &ip, const QStringList &dnsServers); void disconnected(DISCONNECT_REASON reason); void errorDuringConnection(CONNECT_ERROR errorCode); void reconnecting(); @@ -126,8 +126,6 @@ private slots: void onConnectTrigger(); void onConnectingTimeout(); - void onStunnelFinishedBeforeConnection(); - void onWstunnelFinishedBeforeConnection(); void onWstunnelStarted(); void onTunnelTestsFinished(bool bSuccess, const QString &ipAddress); diff --git a/client/engine/engine/connectionmanager/openvpnconnection.cpp b/client/engine/engine/connectionmanager/openvpnconnection.cpp index cefdbaddd..f0dcd8b34 100644 --- a/client/engine/engine/connectionmanager/openvpnconnection.cpp +++ b/client/engine/engine/connectionmanager/openvpnconnection.cpp @@ -206,6 +206,7 @@ void OpenVPNConnection::onKillControllerTimer() helper_posix->executeTaskKill(kTargetOpenVpn); #endif + setCurrentStateAndEmitDisconnected(STATUS_DISCONNECTED); } void OpenVPNConnection::funcRunOpenVPN() diff --git a/client/engine/engine/connectionmanager/stunnelmanager.cpp b/client/engine/engine/connectionmanager/stunnelmanager.cpp index 4c2381f43..6c1704ed8 100644 --- a/client/engine/engine/connectionmanager/stunnelmanager.cpp +++ b/client/engine/engine/connectionmanager/stunnelmanager.cpp @@ -11,35 +11,29 @@ #include "utils/extraconfig.h" StunnelManager::StunnelManager(QObject *parent, IHelper *helper) - : QObject(parent), helper_(helper), bProcessStarted_(false), portForStunnel_(0) + : QObject(parent), helper_(helper), port_(0), bProcessStarted_(false) { #if defined Q_OS_WIN process_ = new QProcess(this); - connect(process_, SIGNAL(finished(int)), SLOT(onStunnelProcessFinished())); + connect(process_, &QProcess::started, this, &StunnelManager::onProcessStarted); + connect(process_, &QProcess::finished, this, &StunnelManager::onProcessFinished); + connect(process_, &QProcess::readyReadStandardOutput, this, &StunnelManager::onProcessReadyRead); + connect(process_, &QProcess::errorOccurred, this, &StunnelManager::onProcessErrorOccurred); + process_->setProcessChannelMode(QProcess::MergedChannels); - stunnelExePath_ = QCoreApplication::applicationDirPath() + "/tstunnel.exe"; - - QString strPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); - QDir dir(strPath); - dir.mkpath(strPath); - path_ = strPath + "/stunnel.conf"; + stunnelExePath_ = QCoreApplication::applicationDirPath() + "/windscribewstunnel.exe"; #endif } StunnelManager::~StunnelManager() { killProcess(); - -#if defined Q_OS_WIN - if (QFile::exists(path_)) { - QFile::remove(path_); - } -#endif } -bool StunnelManager::runProcess() +bool StunnelManager::runProcess(const QString &hostname, unsigned int port) { bool ret = false; + bool extraPadding = ExtraConfig::instance().getStealthExtraTLSPadding(); #if defined(Q_OS_WIN) ExecutableSignature sigCheck; @@ -48,43 +42,41 @@ bool StunnelManager::runProcess() return false; } - bProcessStarted_ = true; QStringList args; args << path_; + QString addr = QString("127.0.0.1:%1").arg(port_); + QString hostaddr = QString("https://%1:%2").arg(hostname).arg(port); + args << "--listenAddress" << addr; + args << "--remoteAddress" << hostaddr; + args << "--logFilePath" << ""; + args << "--tunnelType" << "2"; + if (extraPadding) { + args << "--extraTlsPadding"; + } + process_->start(stunnelExePath_, args); ret = true; #else Helper_posix *helper_posix = dynamic_cast(helper_); - ret = !helper_posix->startStunnel(); -#endif - qCDebug(LOG_BASIC) << "stunnel started on port " << portForStunnel_; - return ret; -} - -bool StunnelManager::setConfig(const QString &hostname, uint port) -{ - killProcess(); -#if defined(Q_OS_WIN) - if (makeConfigFile(hostname, port)) { - return true; - } else { - return false; + ret = !helper_posix->startStunnel(hostname, port, port_, extraPadding); + if (ret) { + emit stunnelStarted(); } -#else - portForStunnel_ = AvailablePort::getAvailablePort(DEFAULT_PORT); - bool extraPadding = ExtraConfig::instance().getStealthExtraTLSPadding(); - - Helper_posix *helper_posix = dynamic_cast(helper_); - return !helper_posix->configureStunnel(hostname, port, portForStunnel_ ,extraPadding); #endif + if (ret) { + qCDebug(LOG_BASIC) << "stunnel started on port " << port_; + } else { + qCDebug(LOG_BASIC) << "stunnel failed to start"; + } + bProcessStarted_ = ret; + return ret; } void StunnelManager::killProcess() { #if defined(Q_OS_WIN) if (bProcessStarted_) { - bProcessStarted_ = false; process_->close(); process_->waitForFinished(-1); } @@ -92,15 +84,23 @@ void StunnelManager::killProcess() Helper_posix *helper_posix = dynamic_cast(helper_); helper_posix->executeTaskKill(kTargetStunnel); #endif + bProcessStarted_ = false; qCDebug(LOG_BASIC) << "stunnel stopped"; } -unsigned int StunnelManager::getStunnelPort() +unsigned int StunnelManager::getPort() +{ + port_ = AvailablePort::getAvailablePort(kDefaultPort); + return port_; +} + +void StunnelManager::onProcessStarted() { - return portForStunnel_; + qCDebug(LOG_BASIC) << "stunnel started"; + emit stunnelStarted(); } -void StunnelManager::onStunnelProcessFinished() +void StunnelManager::onProcessFinished() { #ifdef Q_OS_WIN if (bProcessStarted_) { @@ -109,40 +109,18 @@ void StunnelManager::onStunnelProcessFinished() emit stunnelFinished(); } #endif + bProcessStarted_ = false; } -#ifdef Q_OS_WIN -bool StunnelManager::makeConfigFile(const QString &hostname, uint port) +void StunnelManager::onProcessErrorOccurred(QProcess::ProcessError /*error*/) { - QFile file(path_); - if (file.open(QIODevice::WriteOnly)) { - file.resize(0); - - portForStunnel_ = AvailablePort::getAvailablePort(DEFAULT_PORT); - - QString str; - str = "[openvpn]\r\n"; - file.write(str.toLocal8Bit()); - str = "client = yes\r\n"; - file.write(str.toLocal8Bit()); - str = QString("accept = 127.0.0.1:%1\r\n").arg(portForStunnel_); - file.write(str.toLocal8Bit()); - str = "connect = " + hostname + ":" + QString::number(port) + "\r\n"; - file.write(str.toLocal8Bit()); - if (ExtraConfig::instance().getStealthExtraTLSPadding()) { - str = "options = TLSEXT_PADDING\r\noptions = TLSEXT_PADDING_SUPER\r\n"; - file.write(str.toLocal8Bit()); - } - - file.close(); + qCDebug(LOG_BASIC) << "stunnel process error:" << process_->errorString(); +} - qCDebug(LOG_BASIC) << "Used for stunnel:" << portForStunnel_; - //qCDebug(LOG_BASIC) << "Stunnel config file: " << file.fileName(); - return true; - } else { - qCDebug(LOG_BASIC) << "Can't create stunnel config file"; +void StunnelManager::onProcessReadyRead() +{ + QStringList strs = QString(process_->readAll()).split("\n", Qt::SkipEmptyParts); + for (auto str : strs) { + qCDebug(LOG_WSTUNNEL) << str; } - return false; } -#endif - diff --git a/client/engine/engine/connectionmanager/stunnelmanager.h b/client/engine/engine/connectionmanager/stunnelmanager.h index 63954cdbe..b73b8ff1d 100644 --- a/client/engine/engine/connectionmanager/stunnelmanager.h +++ b/client/engine/engine/connectionmanager/stunnelmanager.h @@ -11,30 +11,28 @@ class StunnelManager : public QObject explicit StunnelManager(QObject *parent, IHelper *helper); virtual ~StunnelManager(); - bool setConfig(const QString &hostname, uint port); - bool runProcess(); + bool runProcess(const QString &hostname, unsigned int port); void killProcess(); - unsigned int getStunnelPort(); + unsigned int getPort(); signals: + void stunnelStarted(); void stunnelFinished(); private slots: - void onStunnelProcessFinished(); + void onProcessStarted(); + void onProcessFinished(); + void onProcessReadyRead(); + void onProcessErrorOccurred(QProcess::ProcessError error); private: - static constexpr unsigned int DEFAULT_PORT = 1194; + static constexpr unsigned int kDefaultPort = 1194; IHelper *helper_; - unsigned int portForStunnel_; + unsigned int port_; bool bProcessStarted_; - -#ifdef Q_OS_WIN QString path_; - QProcess *process_; - QString stunnelExePath_; - - bool makeConfigFile(const QString &hostname, uint port); -#endif + QProcess *process_; + QString stunnelExePath_; }; diff --git a/client/engine/engine/connectionmanager/testvpntunnel.cpp b/client/engine/engine/connectionmanager/testvpntunnel.cpp index 94149a3bf..5b761c349 100644 --- a/client/engine/engine/connectionmanager/testvpntunnel.cpp +++ b/client/engine/engine/connectionmanager/testvpntunnel.cpp @@ -42,35 +42,42 @@ void TestVPNTunnel::startTestImpl() { timeouts_.clear(); - bool advParamExists; + doCustomTunnelTest_ = false; + bool advParamExists; int attempts = ExtraConfig::instance().getTunnelTestAttempts(advParamExists); - if (!advParamExists) { - attempts = 3; - } else { + if (advParamExists) { + if (attempts == 0) { + // Do not emit result directly here, callers may not be ready for callback before startTests() returns. + QTimer::singleShot(1, this, &TestVPNTunnel::onTestsSkipped); + return; + } doCustomTunnelTest_ = true; } - if (attempts == 0) { - // Do not emit result directly here, callers may not be ready for callback before startTests() returns. - QTimer::singleShot(1, this, &TestVPNTunnel::onTestsSkipped); - return; - } int timeout = ExtraConfig::instance().getTunnelTestTimeout(advParamExists); - if (!advParamExists) { - int timeout = PING_TEST_TIMEOUT_1; - for (int i = 0; i < attempts; i++) - { - timeouts_ << timeout; - if (timeout < PING_TEST_TIMEOUT_3) - { - timeout *= 2; - } - } - } else { + if (advParamExists) { doCustomTunnelTest_ = true; timeouts_.fill(timeout, attempts); } + else { + // There is a delay when using OpenVPN+wintun preventing DNS resolution once the tunnel is up. + // The delay also occurs when using the vanilla OpenVPN client. We tried experimenting with + // the various settings for the --ip-win32 OpenVPN parameter, but none helped. Increasing the + // initial tunnel test timeout appears to dramatically improve the tunnel test time. The test + // was taking ~5.5s before the change, and is now taking ~3-3.5s. Verified on x86_64 and arm64 + // Windows 10/11. + if (protocol_.isOpenVpnProtocol()) { + timeouts_ << 5000; + timeouts_ << 10000; + timeouts_ << 15000; + } + else { + timeouts_ << 2000; + timeouts_ << 4000; + timeouts_ << 8000; + } + } testRetryDelay_ = ExtraConfig::instance().getTunnelTestRetryDelay(advParamExists); if (!advParamExists) { @@ -209,4 +216,3 @@ void TestVPNTunnel::onTestsSkipped() qCDebug(LOG_CONNECTION) << "Tunnel tests disabled"; emit testsFinished(true, ""); } - diff --git a/client/engine/engine/connectionmanager/testvpntunnel.h b/client/engine/engine/connectionmanager/testvpntunnel.h index d01fa3286..c4773097d 100644 --- a/client/engine/engine/connectionmanager/testvpntunnel.h +++ b/client/engine/engine/connectionmanager/testvpntunnel.h @@ -40,11 +40,6 @@ private slots: bool doCustomTunnelTest_; QElapsedTimer elapsedOverallTimer_; - enum { - PING_TEST_TIMEOUT_1 = 2000, - PING_TEST_TIMEOUT_2 = 4000, - PING_TEST_TIMEOUT_3 = 8000 - }; QVector timeouts_; types::Protocol protocol_; diff --git a/client/engine/engine/connectionmanager/wireguardconnection_win.cpp b/client/engine/engine/connectionmanager/wireguardconnection_win.cpp index faceb2566..57ba73f77 100644 --- a/client/engine/engine/connectionmanager/wireguardconnection_win.cpp +++ b/client/engine/engine/connectionmanager/wireguardconnection_win.cpp @@ -63,7 +63,6 @@ void WireGuardConnection::startConnect(const QString &configPathOrUrl, const QSt Q_UNUSED(proxySettings); Q_UNUSED(isEnableIkev2Compression); Q_UNUSED(isCustomConfig); - Q_UNUSED(overrideDnsIp); WS_ASSERT(helper_ != nullptr); WS_ASSERT(wireGuardConfig != nullptr); @@ -76,7 +75,13 @@ void WireGuardConnection::startConnect(const QString &configPathOrUrl, const QSt connectedSignalEmited_ = false; isAutomaticConnectionMode_ = isAutomaticConnectionMode; - wireGuardConfig_ = wireGuardConfig; + wireGuardConfig_ = *wireGuardConfig; + + // override the DNS if we are using custom + if (!overrideDnsIp.isEmpty()) { + wireGuardConfig_.setClientDnsAddress(overrideDnsIp); + } + ::ResetEvent(stopThreadEvent_.getHandle()); start(LowPriority); @@ -141,7 +146,7 @@ void WireGuardConnection::run() // If there was a running instance of the wireguard service, the helper (startWireGuard call) will // have stopped it and it will have deleted the existing config file. Therefore, don't create our // new config file until we're sure the wireguard service is stopped. - if (!wireGuardConfig_->generateConfigFile(configFile)) { + if (!wireGuardConfig_.generateConfigFile(configFile)) { emit error(CONNECT_ERROR::WIREGUARD_CONNECTION_ERROR); emit disconnected(); return; diff --git a/client/engine/engine/connectionmanager/wireguardconnection_win.h b/client/engine/engine/connectionmanager/wireguardconnection_win.h index f70f01778..c36481f8b 100644 --- a/client/engine/engine/connectionmanager/wireguardconnection_win.h +++ b/client/engine/engine/connectionmanager/wireguardconnection_win.h @@ -2,6 +2,7 @@ #include +#include "engine/wireguardconfig/wireguardconfig.h" #include "iconnection.h" #include "engine/helper/helper_win.h" #include "wireguardringlogger.h" @@ -46,7 +47,7 @@ private Q_SLOTS: static constexpr int kTimeoutForAutomatic = 20000; // 20s timeout for the automatic connection mode Helper_win* const helper_; - const WireGuardConfig* wireGuardConfig_ = nullptr; + WireGuardConfig wireGuardConfig_; bool connectedSignalEmited_ = false; bool isAutomaticConnectionMode_ = false; diff --git a/client/engine/engine/connectionmanager/wstunnelmanager.cpp b/client/engine/engine/connectionmanager/wstunnelmanager.cpp index be92ae51b..6a384c822 100644 --- a/client/engine/engine/connectionmanager/wstunnelmanager.cpp +++ b/client/engine/engine/connectionmanager/wstunnelmanager.cpp @@ -11,17 +11,17 @@ WstunnelManager::WstunnelManager(QObject *parent, IHelper *helper) - : QObject(parent), helper_(helper), bProcessStarted_(false), bFirstMarketLineAfterStart_(false), port_(0) + : QObject(parent), helper_(helper), bProcessStarted_(false), port_(0) { #if defined Q_OS_WIN process_ = new QProcess(this); - connect(process_, SIGNAL(started()), SLOT(onProcessStarted())); - connect(process_, SIGNAL(finished(int)), SLOT(onProcessFinished())); - connect(process_, SIGNAL(readyReadStandardOutput()), SLOT(onReadyReadStandardOutput())); - connect(process_, SIGNAL(errorOccurred(QProcess::ProcessError)), SLOT(onProcessErrorOccurred(QProcess::ProcessError))); - process_->setProcessChannelMode(QProcess::MergedChannels); + connect(process_, &QProcess::started, this, &WstunnelManager::onProcessStarted); + connect(process_, &QProcess::finished, this, &WstunnelManager::onProcessFinished); + connect(process_, &QProcess::readyReadStandardOutput, this, &WstunnelManager::onProcessReadyRead); + connect(process_, &QProcess::errorOccurred, this, &WstunnelManager::onProcessErrorOccurred); - wstunnelExePath_ = QCoreApplication::applicationDirPath() + "/wstunnel.exe"; + process_->setProcessChannelMode(QProcess::MergedChannels); + wstunnelExePath_ = QCoreApplication::applicationDirPath() + "/windscribewstunnel.exe"; #endif } @@ -30,7 +30,7 @@ WstunnelManager::~WstunnelManager() killProcess(); } -bool WstunnelManager::runProcess(const QString &hostname, unsigned int port, bool isUdp) +bool WstunnelManager::runProcess(const QString &hostname, unsigned int port) { bool ret = false; #if defined(Q_OS_WIN) @@ -41,25 +41,28 @@ bool WstunnelManager::runProcess(const QString &hostname, unsigned int port, boo return false; } - inputArr_.clear(); - bFirstMarketLineAfterStart_ = true; - bProcessStarted_ = true; QStringList args; - QString addr = QString("127.0.0.1:%1:127.0.0.1:1194").arg(port_); - QString hostaddr = QString("wss://%1:%2").arg(hostname).arg(port); - args << "--localToRemote" << addr << hostaddr << "--verbose" << "--upgradePathPrefix=/"; - if (isUdp) - { - args << "--udp"; - } + QString addr = QString("127.0.0.1:%1").arg(port_); + QString hostaddr = QString("wss://%1:%2/tcp/127.0.0.1/1194").arg(hostname).arg(port); + args << "--listenAddress" << addr; + args << "--remoteAddress" << hostaddr; + args << "--logFilePath" << ""; process_->start(wstunnelExePath_, args); ret = true; #else Helper_posix *helper_posix = dynamic_cast(helper_); - ret = !helper_posix->startWstunnel(hostname, port, isUdp, port_); - emit wstunnelStarted(); + ret = !helper_posix->startWstunnel(hostname, port, port_); + if (ret) { + emit wstunnelStarted(); + } #endif - qCDebug(LOG_BASIC) << "wstunnel started on port " << port_; + if (ret) { + qCDebug(LOG_BASIC) << "wstunnel started on port " << port_; + } else { + qCDebug(LOG_BASIC) << "wstunnel failed to start"; + } + + bProcessStarted_ = ret; return ret; } @@ -68,7 +71,6 @@ void WstunnelManager::killProcess() #if defined(Q_OS_WIN) if (bProcessStarted_) { - bProcessStarted_ = false; process_->close(); process_->waitForFinished(-1); } @@ -76,18 +78,20 @@ void WstunnelManager::killProcess() Helper_posix *helper_posix = dynamic_cast(helper_); helper_posix->executeTaskKill(kTargetWStunnel); #endif + bProcessStarted_ = false; qCDebug(LOG_BASIC) << "wstunnel stopped"; } unsigned int WstunnelManager::getPort() { - port_ = AvailablePort::getAvailablePort(DEFAULT_PORT); + port_ = AvailablePort::getAvailablePort(kDefaultPort); return port_; } void WstunnelManager::onProcessStarted() { qCDebug(LOG_WSTUNNEL) << "wstunnel started"; + emit wstunnelStarted(); } void WstunnelManager::onProcessFinished() @@ -100,35 +104,7 @@ void WstunnelManager::onProcessFinished() emit wstunnelFinished(); } #endif -} - -void WstunnelManager::onReadyReadStandardOutput() -{ - inputArr_.append(process_->readAll()); - bool bSuccess = true; - int length; - while (true) - { - QString str = getNextStringFromInputBuffer(bSuccess, length); - if (bSuccess) - { - inputArr_.remove(0, length); - qCDebug(LOG_WSTUNNEL) << str; - - if (bFirstMarketLineAfterStart_) - { - if (str.contains("WAIT for tcp connection on")) - { - bFirstMarketLineAfterStart_ = false; - emit wstunnelStarted(); - } - } - } - else - { - break; - } - }; + bProcessStarted_ = false; } void WstunnelManager::onProcessErrorOccurred(QProcess::ProcessError /*error*/) @@ -136,22 +112,10 @@ void WstunnelManager::onProcessErrorOccurred(QProcess::ProcessError /*error*/) qCDebug(LOG_WSTUNNEL) << "wstunnel process error:" << process_->errorString(); } -QString WstunnelManager::getNextStringFromInputBuffer(bool &bSuccess, int &outSize) +void WstunnelManager::onProcessReadyRead() { - QString str; - bSuccess = false; - outSize = 0; - for (int i = 0; i < inputArr_.size(); ++i) - { - if (inputArr_[i] == '\n') - { - bSuccess = true; - outSize = i + 1; - return str.trimmed(); - } - str += inputArr_[i]; + QStringList strs = QString(process_->readAll()).split("\n", Qt::SkipEmptyParts); + for (auto str : strs) { + qCDebug(LOG_WSTUNNEL) << str; } - - return QString(); } - diff --git a/client/engine/engine/connectionmanager/wstunnelmanager.h b/client/engine/engine/connectionmanager/wstunnelmanager.h index 3c5cf36f3..269990efa 100644 --- a/client/engine/engine/connectionmanager/wstunnelmanager.h +++ b/client/engine/engine/connectionmanager/wstunnelmanager.h @@ -11,7 +11,7 @@ class WstunnelManager : public QObject explicit WstunnelManager(QObject *parent, IHelper *helper); virtual ~WstunnelManager(); - bool runProcess(const QString &hostname, unsigned int port, bool isUdp); + bool runProcess(const QString &hostname, unsigned int port); void killProcess(); unsigned int getPort(); @@ -23,20 +23,15 @@ class WstunnelManager : public QObject private slots: void onProcessStarted(); void onProcessFinished(); - void onReadyReadStandardOutput(); + void onProcessReadyRead(); void onProcessErrorOccurred(QProcess::ProcessError error); private: + static constexpr unsigned int kDefaultPort = 1194; + IHelper *helper_; - QProcess *process_; - QString wstunnelExePath_; + QProcess *process_; + QString wstunnelExePath_; bool bProcessStarted_; - QByteArray inputArr_; - bool bFirstMarketLineAfterStart_; - - static constexpr unsigned int DEFAULT_PORT = 1194; unsigned int port_; - - QString getNextStringFromInputBuffer(bool &bSuccess, int &outSize); - }; diff --git a/client/engine/engine/engine.cpp b/client/engine/engine/engine.cpp index 37d8a20be..3d457c4ac 100644 --- a/client/engine/engine/engine.cpp +++ b/client/engine/engine/engine.cpp @@ -600,7 +600,7 @@ void Engine::initPart2() connect(connectionManager_, SIGNAL(statisticsUpdated(quint64,quint64, bool)), SLOT(onConnectionManagerStatisticsUpdated(quint64,quint64, bool))); connect(connectionManager_, SIGNAL(interfaceUpdated(QString)), SLOT(onConnectionManagerInterfaceUpdated(QString))); connect(connectionManager_, SIGNAL(testTunnelResult(bool, QString)), SLOT(onConnectionManagerTestTunnelResult(bool, QString))); - connect(connectionManager_, SIGNAL(connectingToHostname(QString, QString, QString)), SLOT(onConnectionManagerConnectingToHostname(QString, QString, QString))); + connect(connectionManager_, SIGNAL(connectingToHostname(QString, QString, QStringList)), SLOT(onConnectionManagerConnectingToHostname(QString, QString, QStringList))); connect(connectionManager_, &ConnectionManager::protocolPortChanged, this, &Engine::onConnectionManagerProtocolPortChanged); connect(connectionManager_, SIGNAL(internetConnectivityChanged(bool)), SLOT(onConnectionManagerInternetConnectivityChanged(bool))); connect(connectionManager_, SIGNAL(wireGuardAtKeyLimit()), SLOT(onConnectionManagerWireGuardAtKeyLimit())); @@ -1338,9 +1338,10 @@ void Engine::onConnectionManagerConnected() locationId_.isCustomConfigsLocation()); } + // For Windows we should to set the custom dns for the adapter explicitly except WireGuard protocol #ifdef Q_OS_WIN Helper_win *helper_win = dynamic_cast(helper_); - if (connectionManager_->connectedDnsInfo().type == CONNECTED_DNS_TYPE_CUSTOM) + if (connectionManager_->connectedDnsInfo().type == CONNECTED_DNS_TYPE_CUSTOM && connectionManager_->currentProtocol() != types::Protocol::WIREGUARD) { WS_ASSERT(connectionManager_->getVpnAdapterInfo().dnsServers().count() == 1); if (!helper_win->setCustomDnsWhileConnected( connectionManager_->getVpnAdapterInfo().ifIndex(), @@ -1608,21 +1609,21 @@ void Engine::onConnectionManagerInterfaceUpdated(const QString &interfaceName) #endif } -void Engine::onConnectionManagerConnectingToHostname(const QString &hostname, const QString &ip, const QString &dnsServer) +void Engine::onConnectionManagerConnectingToHostname(const QString &hostname, const QString &ip, const QStringList &dnsServers) { lastConnectingHostname_ = hostname; connectStateController_->setConnectingState(locationId_); qCDebug(LOG_BASIC) << "Whitelist connecting ip:" << ip; - if (!dnsServer.isEmpty()) + if (!dnsServers.isEmpty()) { - qCDebug(LOG_BASIC) << "Whitelist DNS-server ip:" << dnsServer; + qCDebug(LOG_BASIC) << "Whitelist DNS-server ip:" << dnsServers; } bool bChanged1 = false; firewallExceptions_.setConnectingIp(ip, bChanged1); bool bChanged2 = false; - firewallExceptions_.setDNSServerIp(dnsServer, bChanged2); + firewallExceptions_.setDNSServers(dnsServers, bChanged2); if (bChanged1 || bChanged2) { updateFirewallSettings(); @@ -2381,7 +2382,7 @@ void Engine::doDisconnectRestoreStuff() bool bChanged; firewallExceptions_.setConnectingIp("", bChanged); - firewallExceptions_.setDNSServerIp("", bChanged); + firewallExceptions_.setDNSServers(QStringList(), bChanged); if (firewallController_->firewallActualState()) { firewallController_->firewallOn( diff --git a/client/engine/engine/engine.h b/client/engine/engine/engine.h index 1e7ef63e4..0f5f39faf 100644 --- a/client/engine/engine/engine.h +++ b/client/engine/engine/engine.h @@ -247,7 +247,7 @@ private slots: void onConnectionManagerInternetConnectivityChanged(bool connectivity); void onConnectionManagerStatisticsUpdated(quint64 bytesIn, quint64 bytesOut, bool isTotalBytes); void onConnectionManagerInterfaceUpdated(const QString &interfaceName); - void onConnectionManagerConnectingToHostname(const QString &hostname, const QString &ip, const QString &dnsServer); + void onConnectionManagerConnectingToHostname(const QString &hostname, const QString &ip, const QStringList &dnsServers); void onConnectionManagerProtocolPortChanged(const types::Protocol &protocol, const uint port); void onConnectionManagerTestTunnelResult(bool success, const QString & ipAddress); void onConnectionManagerWireGuardAtKeyLimit(); diff --git a/client/engine/engine/failover/CMakeLists.txt b/client/engine/engine/failover/CMakeLists.txt index 23522f91e..b3b8737dd 100644 --- a/client/engine/engine/failover/CMakeLists.txt +++ b/client/engine/engine/failover/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(engine PRIVATE failovers/echfailover.h failovers/hardcodeddomainfailover.h failovers/randomdomainfailover.h + failovers/cdndomainfailover.h ifailovercontainer.h failovercontainer.cpp failovercontainer.h diff --git a/client/engine/engine/failover/basefailover.h b/client/engine/engine/failover/basefailover.h index 7a472530a..83c1b1ce2 100644 --- a/client/engine/engine/failover/basefailover.h +++ b/client/engine/engine/failover/basefailover.h @@ -13,6 +13,7 @@ class FailoverData { public: explicit FailoverData(const QString &domain) : domain_(domain) {} + explicit FailoverData(const QString &domain, const QString &sniDomain) : domain_(domain), sniDomain_(sniDomain) {} explicit FailoverData(const QString &domain, const QString &echConfig, int ttl) : domain_(domain), echConfig_(echConfig), ttl_(ttl) { @@ -21,6 +22,7 @@ class FailoverData { QString domain() const { return domain_; } QString echConfig() const { return echConfig_; } + QString sniDomain() const { return sniDomain_; } bool isExpired() const { WS_ASSERT(!echConfig_.isEmpty()); @@ -39,6 +41,7 @@ class FailoverData { private: QString domain_; + QString sniDomain_; // empty if no SNI spoofing / domain fronting QString echConfig_; // empty if it does not support ECH int ttl_; // TTL in seconds QElapsedTimer elapsedTimer_; diff --git a/client/engine/engine/failover/failovercontainer.cpp b/client/engine/engine/failover/failovercontainer.cpp index 7dad1d8a9..30f2789b0 100644 --- a/client/engine/engine/failover/failovercontainer.cpp +++ b/client/engine/engine/failover/failovercontainer.cpp @@ -6,6 +6,7 @@ #include "failovers/echfailover.h" #include "failovers/hardcodeddomainfailover.h" #include "failovers/randomdomainfailover.h" +#include "failovers/cdndomainfailover.h" #include "utils/hardcodedsettings.h" #include "utils/dga_library.h" #include "utils/logger.h" @@ -17,6 +18,7 @@ // Attention: do not change the unique identifiers of failover. By adding a new failover generate a new unique identifier #define FAILOVER_DEFAULT_HARDCODED "300fa426-4640-4a3f-b95c-1f0277462358" #define FAILOVER_BACKUP_HARDCODED "83e64a18-31bb-4d26-956a-ade58a5df0b9" +#define FAILOVER_CDN_HARDCODED "64e5c2e1-829b-4f6a-a3a3-a37c762778c6" #define FAILOVER_ECH_CLOUFLARE_1 "3e60e3d5-d379-46cc-a9a0-d9f04f47999a" #define FAILOVER_ECH_CLOUFLARE_2 "ee195090-f5e8-4ae0-9142-ca0961a43173" @@ -52,6 +54,7 @@ FailoverContainer::FailoverContainer(QObject *parent, NetworkAccessManager *netw // Don't use other failovers for the staging functionality, as the hashed domains will hit the production environment. if (!AppVersion::instance().isStaging()) { + failovers_ << FAILOVER_BACKUP_HARDCODED; failovers_ << FAILOVER_DYNAMIC_CLOUDFLARE_1; @@ -81,6 +84,8 @@ FailoverContainer::FailoverContainer(QObject *parent, NetworkAccessManager *netw failovers_ << FAILOVER_ACCESS_IP_2; failovers_ << FAILOVER_ACCESS_IP_1; } + + failovers_ << FAILOVER_CDN_HARDCODED; } resetImpl(); @@ -194,6 +199,11 @@ QSharedPointer FailoverContainer::failoverById(const QString &fail if (dga.load()) { return QSharedPointer(new AccessIpsFailover(this, FAILOVER_ACCESS_IP_2, networkAccessManager_, dga.getParameter(PAR_API_ACCESS_IP2))); } + } else if (failoverUniqueId == FAILOVER_CDN_HARDCODED) { + DgaLibrary dga; + if (dga.load()) { + return QSharedPointer(new CdnDomainFailover(this, FAILOVER_CDN_HARDCODED, dga.getParameter(PAR_CDN_BACKEND_DOMAIN), dga.getParameter(PAR_CDN_FRONTEND_DOMAIN))); + } } return nullptr; diff --git a/client/engine/engine/failover/failovers/cdndomainfailover.h b/client/engine/engine/failover/failovers/cdndomainfailover.h new file mode 100644 index 000000000..50316baec --- /dev/null +++ b/client/engine/engine/failover/failovers/cdndomainfailover.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../basefailover.h" + +namespace failover { + +class CdnDomainFailover : public BaseFailover +{ + Q_OBJECT +public: + explicit CdnDomainFailover(QObject *parent, const QString &uniqueId, const QString &domain, const QString &sniDomain) : BaseFailover(parent, uniqueId), + domain_(domain), sniDomain_(sniDomain) {} + + void getData(bool /*bIgnoreSslErrors*/) override + { + emit finished(QVector() << FailoverData(domain_, sniDomain_)); + } + + QString name() const override + { + // the domain name has been reduced to 3 characters for log security + return "cdn: " + domain_.left(3); + } + +private: + QString domain_; + QString sniDomain_; +}; + +} // namespace failover diff --git a/client/engine/engine/firewall/firewallcontroller_mac.cpp b/client/engine/engine/firewall/firewallcontroller_mac.cpp index 952f950c6..c67f10bc0 100644 --- a/client/engine/engine/firewall/firewallcontroller_mac.cpp +++ b/client/engine/engine/firewall/firewallcontroller_mac.cpp @@ -272,7 +272,7 @@ void FirewallController_mac::getFirewallStateFromPfctl(FirewallState &outState) if (ret && !output.isEmpty()) { QStringList rules = output.split("\n"); if (rules.size() > 0) { - QStringList words = rules[0].split(" "); + QStringList words = rules[1].split(" "); if (words.size() >= 10) { // pass out quick on [interface] outState.interfaceToSkip = words[4]; @@ -345,6 +345,9 @@ QString FirewallController_mac::generatePfConf(const QString &connectingIp, cons pf += "anchor \"com.apple/*\"\n"; pf += "load anchor \"com.apple\" from \"/etc/pf.anchors/com.apple\"\n"; + // block everything + pf += "block all\n"; + // skip awdl and p2p interfaces (awdl Apple Wireless Direct Link and p2p related to AWDL features) for (const auto &interface : awdl_p2p_interfaces_) pf += "pass quick on " + interface + "\n"; @@ -369,9 +372,6 @@ QString FirewallController_mac::generatePfConf(const QString &connectingIp, cons // always allow esp/gre pf += "pass proto {esp, gre} from any to any\n"; - // block everything - pf += "block all\n"; - // add Windscribe rules pf += "table persist {"; for (auto &ip : ips) @@ -439,6 +439,8 @@ QStringList FirewallController_mac::vpnTrafficRules(const QString &connectingIp, QStringList rules; if (!interfaceToSkip.isEmpty()) { + rules += "pass on " + interfaceToSkip; + if (!bIsCustomConfig) { // Allow local addresses QList localAddrs = getLocalAddresses(interfaceToSkip); diff --git a/client/engine/engine/firewall/firewallexceptions.cpp b/client/engine/engine/firewall/firewallexceptions.cpp index f43eceef9..8c8bf4ed2 100644 --- a/client/engine/engine/firewall/firewallexceptions.cpp +++ b/client/engine/engine/firewall/firewallexceptions.cpp @@ -42,10 +42,10 @@ void FirewallExceptions::setConnectingIp(const QString &connectingIp, bool &bCha } } -void FirewallExceptions::setDNSServerIp(const QString &dnsIp, bool &bChanged) +void FirewallExceptions::setDNSServers(const QStringList &ips, bool &bChanged) { - if (dnsIp_ != dnsIp) { - dnsIp_ = dnsIp; + if (dnsIps_ != ips) { + dnsIps_ = ips; bChanged = true; } else { bChanged = false; @@ -99,6 +99,11 @@ QSet FirewallExceptions::getIPAddressesForFirewall() const } } + // we should always add ControlD DNS servers because the ctrld-utility uses them + for (const QString &s : HardcodedSettings::instance().controldDns()) { + ipList.add(s); + } + for (const QString &s : hostIPs_) { if (!s.isEmpty()) { ipList.add(s); @@ -113,9 +118,8 @@ QSet FirewallExceptions::getIPAddressesForFirewall() const ipList.add(remoteIP_); } - if (!dnsIp_.isEmpty()) { - ipList.add(dnsIp_); - } + for (const QString &s : dnsIps_) + ipList.add(s); for (const QString &sl : locationsPingIPs_) { if (!sl.isEmpty()) { diff --git a/client/engine/engine/firewall/firewallexceptions.h b/client/engine/engine/firewall/firewallexceptions.h index 660535e31..790df3653 100644 --- a/client/engine/engine/firewall/firewallexceptions.h +++ b/client/engine/engine/firewall/firewallexceptions.h @@ -13,7 +13,7 @@ class FirewallExceptions void setCustomRemoteIp(const QString &remoteIP, bool &bChanged); void setConnectingIp(const QString &connectingIp, bool &bChanged); - void setDNSServerIp(const QString &dnsIp, bool &bChanged); + void setDNSServers(const QStringList &ips, bool &bChanged); void setDnsPolicy(DNS_POLICY_TYPE dnsPolicy); @@ -32,7 +32,7 @@ class FirewallExceptions QStringList locationsPingIPs_; QStringList customConfigsPingIPs_; QString connectingIp_; - QString dnsIp_; + QStringList dnsIps_; DNS_POLICY_TYPE dnsPolicyType_; }; diff --git a/client/engine/engine/helper/helper_posix.cpp b/client/engine/engine/helper/helper_posix.cpp index 57d3880b5..1350f5654 100644 --- a/client/engine/engine/helper/helper_posix.cpp +++ b/client/engine/engine/helper/helper_posix.cpp @@ -618,7 +618,7 @@ bool Helper_posix::setFirewallOnBoot(bool bEnabled, const QSet &ipTable return runCommand(HELPER_CMD_SET_FIREWALL_ON_BOOT, stream.str(), answer); } -bool Helper_posix::startStunnel() +bool Helper_posix::startStunnel(const QString &hostname, unsigned int port, unsigned int localPort, bool extraPadding) { QMutexLocker locker(&mutex_); @@ -630,26 +630,7 @@ bool Helper_posix::startStunnel() #else WS_ASSERT(false); #endif - cmd.executable = "windscribestunnel"; - - std::stringstream stream; - boost::archive::text_oarchive oa(stream, boost::archive::no_header); - oa << cmd; - - CMD_ANSWER answer; - if (!runCommand(HELPER_CMD_START_STUNNEL, stream.str(), answer) || answer.executed == 0) { - doDisconnectAndReconnect(); - return IHelper::EXECUTE_ERROR; - } - - return IHelper::EXECUTE_SUCCESS; -} - -bool Helper_posix::configureStunnel(const QString &hostname, unsigned int port, unsigned int localPort, bool extraPadding) -{ - QMutexLocker locker(&mutex_); - - CMD_CONFIGURE_STUNNEL cmd; + cmd.executable = "windscribewstunnel"; cmd.hostname = hostname.toStdString(); cmd.port = port; cmd.localPort = localPort; @@ -660,7 +641,7 @@ bool Helper_posix::configureStunnel(const QString &hostname, unsigned int port, oa << cmd; CMD_ANSWER answer; - if (!runCommand(HELPER_CMD_CONFIGURE_STUNNEL, stream.str(), answer) || answer.executed == 0) { + if (!runCommand(HELPER_CMD_START_STUNNEL, stream.str(), answer) || answer.executed == 0) { doDisconnectAndReconnect(); return IHelper::EXECUTE_ERROR; } @@ -668,7 +649,7 @@ bool Helper_posix::configureStunnel(const QString &hostname, unsigned int port, return IHelper::EXECUTE_SUCCESS; } -bool Helper_posix::startWstunnel(const QString &hostname, unsigned int port, bool isUdp, unsigned int localPort) +bool Helper_posix::startWstunnel(const QString &hostname, unsigned int port, unsigned int localPort) { QMutexLocker locker(&mutex_); @@ -683,7 +664,6 @@ bool Helper_posix::startWstunnel(const QString &hostname, unsigned int port, boo cmd.executable = "windscribewstunnel"; cmd.hostname = hostname.toStdString(); cmd.port = port; - cmd.isUdp = isUdp; cmd.localPort = localPort; std::stringstream stream; diff --git a/client/engine/engine/helper/helper_posix.h b/client/engine/engine/helper/helper_posix.h index d5d7ee342..6d3a3c5d3 100644 --- a/client/engine/engine/helper/helper_posix.h +++ b/client/engine/engine/helper/helper_posix.h @@ -53,9 +53,8 @@ class Helper_posix : public IHelper bool setFirewallRules(CmdIpVersion version, const QString &table, const QString &group, const QString &rules); bool getFirewallRules(CmdIpVersion version, const QString &table, const QString &group, QString &rules); bool setFirewallOnBoot(bool bEnabled, const QSet& ipTable); - bool startStunnel(); - bool configureStunnel(const QString &hostname, unsigned int port, unsigned int localPort, bool extraPadding); - bool startWstunnel(const QString &hostname, unsigned int port, bool isUdp, unsigned int localPort); + bool startStunnel(const QString &hostname, unsigned int port, unsigned int localPort, bool extraPadding); + bool startWstunnel(const QString &hostname, unsigned int port, unsigned int localPort); protected: void run() override; diff --git a/client/engine/engine/networkaccessmanager/curlnetworkmanager_impl.cpp b/client/engine/engine/networkaccessmanager/curlnetworkmanager_impl.cpp index c374904f7..1b0e23bd6 100644 --- a/client/engine/engine/networkaccessmanager/curlnetworkmanager_impl.cpp +++ b/client/engine/engine/networkaccessmanager/curlnetworkmanager_impl.cpp @@ -79,6 +79,17 @@ bool CurlNetworkManagerImpl::setupBasicOptions(RequestInfo *requestInfo, const N struct curl_slist *list = NULL; list = curl_slist_append(list, request.contentTypeHeader().toStdString().c_str()); if (list == NULL) return false; + + if (!request.sniDomain().isEmpty()) { + list = curl_slist_append(list, ("Host: " + request.url().host()).toStdString().c_str()); + if (list == NULL) return false; + + QUrl urlRepl = request.url(); + urlRepl.setHost(request.sniDomain()); + + if (curl_easy_setopt(requestInfo->curlEasyHandle, CURLOPT_URL, urlRepl.toString().toStdString().c_str()) != CURLE_OK) return false; + } + requestInfo->curlLists << list; if (curl_easy_setopt(requestInfo->curlEasyHandle, CURLOPT_HTTPHEADER, list) != CURLE_OK) return false; diff --git a/client/engine/engine/networkaccessmanager/networkaccessmanager.cpp b/client/engine/engine/networkaccessmanager/networkaccessmanager.cpp index 558343f98..5317e5d9a 100644 --- a/client/engine/engine/networkaccessmanager/networkaccessmanager.cpp +++ b/client/engine/engine/networkaccessmanager/networkaccessmanager.cpp @@ -110,6 +110,9 @@ void NetworkAccessManager::handleRequest(quint64 id) onResolved(true, QStringList() << requestData->request.overrideIp(), requestData->id, false, 0); } else { QString hostname = requestData->request.url().host(); + if (!requestData->request.sniDomain().isEmpty()) { + hostname = requestData->request.sniDomain(); + } dnsCache_->resolve(hostname, requestData->id, !requestData->request.isUseDnsCache(), requestData->request.dnsServers(), requestData->request.timeout()); } } diff --git a/client/engine/engine/networkaccessmanager/networkrequest.cpp b/client/engine/engine/networkaccessmanager/networkrequest.cpp index 3bc5f1fef..222662ea9 100644 --- a/client/engine/engine/networkaccessmanager/networkrequest.cpp +++ b/client/engine/engine/networkaccessmanager/networkrequest.cpp @@ -107,6 +107,16 @@ bool NetworkRequest::isExtraTLSPadding() const return bExtraTLSPadding_; } +void NetworkRequest::setSniDomain(const QString &sniDomain) +{ + sniDomain_ = sniDomain; +} + +QString NetworkRequest::sniDomain() const +{ + return sniDomain_; +} + void NetworkRequest::setOverrideIp(const QString &ip) { overrideIp_ = ip; diff --git a/client/engine/engine/networkaccessmanager/networkrequest.h b/client/engine/engine/networkaccessmanager/networkrequest.h index b8ff6f6d2..2bc700593 100644 --- a/client/engine/engine/networkaccessmanager/networkrequest.h +++ b/client/engine/engine/networkaccessmanager/networkrequest.h @@ -32,6 +32,8 @@ class NetworkRequest void setEchConfig(const QString &echConfig); QString echConfig() const; + void setSniDomain(const QString &sniDomain); + QString sniDomain() const; void setExtraTLSPadding(const bool ExtraTLSPadding); bool isExtraTLSPadding() const; @@ -51,6 +53,7 @@ class NetworkRequest QString header_; QStringList dnsServers_; + QString sniDomain_; QString echConfig_; // if not empty, use ECH request // if not empty use specified overrideIp_ to make the request diff --git a/client/engine/engine/serverapi/requestexecuterviafailover.cpp b/client/engine/engine/serverapi/requestexecuterviafailover.cpp index 5c238f588..6303abd9d 100644 --- a/client/engine/engine/serverapi/requestexecuterviafailover.cpp +++ b/client/engine/engine/serverapi/requestexecuterviafailover.cpp @@ -119,6 +119,9 @@ void RequestExecuterViaFailover::executeBaseRequest(const failover::FailoverData if (ExtraConfig::instance().getAPIExtraTLSPadding()) { networkRequest.setExtraTLSPadding(true); } + if (!failoverData.sniDomain().isEmpty()) { + networkRequest.setSniDomain(failoverData.sniDomain()); + } NetworkReply *reply; switch (request_->requestType()) { diff --git a/client/engine/engine/serverapi/serverapi.cpp b/client/engine/engine/serverapi/serverapi.cpp index e1b3b9909..e95f69620 100644 --- a/client/engine/engine/serverapi/serverapi.cpp +++ b/client/engine/engine/serverapi/serverapi.cpp @@ -444,6 +444,9 @@ void ServerAPI::executeRequestImpl(QPointer request, const failover if (ExtraConfig::instance().getAPIExtraTLSPadding()) { networkRequest.setExtraTLSPadding(true); } + if (!failoverData.sniDomain().isEmpty()) { + networkRequest.setSniDomain(failoverData.sniDomain()); + } NetworkReply *reply; switch (request->requestType()) { diff --git a/client/gui/locationswindow/widgetlocations/locationstab.cpp b/client/gui/locationswindow/widgetlocations/locationstab.cpp index b13990ac7..0c1c00007 100644 --- a/client/gui/locationswindow/widgetlocations/locationstab.cpp +++ b/client/gui/locationswindow/widgetlocations/locationstab.cpp @@ -22,6 +22,7 @@ LocationsTab::LocationsTab(QWidget *parent, Preferences *preferences, gui_locati , preferences_(preferences) , locationsModelManager_(locationsModelManager) , curTab_(LOCATION_TAB_ALL_LOCATIONS) + , lastTab_(LOCATION_TAB_ALL_LOCATIONS) , tabPress_(LOCATION_TAB_NONE) , filterText_("") , searchTabSelected_(false) diff --git a/client/gui/translations/ws_desktop_ar.ts b/client/gui/translations/ws_desktop_ar.ts index 12a350567..39c3f184b 100644 --- a/client/gui/translations/ws_desktop_ar.ts +++ b/client/gui/translations/ws_desktop_ar.ts @@ -37,52 +37,52 @@ ConnectWindow::ConnectWindowItem - + No Network Info لا توجد معلومات الشبكة - + Unsecured غير المضمونين - + Secured المضمون - + Connection to Windscribe has been terminated. تم إنهاء الاتصال ب Windscribe. - + transferred in نقل في - + Connected for متصل ل - + transferred نقل - + Firewall جدار حمايه - + Blocks all connectivity in the event of a sudden disconnect يحظر كل الاتصال في حالة انقطاع الاتصال المفاجئ - + Connect to rate الاتصال بالسعر @@ -832,14 +832,14 @@ يرجى الاتصال بالدعم - + Lost connection to the backend process. Recovering... فقد الاتصال بعملية الواجهة الخلفية. يتعافي... - + Select an application حدد تطبيقا @@ -989,18 +989,18 @@ If the problem persists after a restart, please send a debug log and open a supp Preferences - - + + Invalid DNS Settings إعدادات DNS غير صالحة - + 'Connected DNS' was not configured with a valid Upstream 1 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). لم يتم تكوين "DNS المتصل" باستخدام Upstream 1 صالح (IP / DNS عبر HTTPS / TLS). تمت إعادة DNS إلى ROBERT (افتراضي). - + 'Connected DNS' was not configured with a valid Upstream 2 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). لم يتم تكوين "DNS المتصل" باستخدام Upstream 2 صالح (IP / DNS عبر HTTPS / TLS). تمت إعادة DNS إلى ROBERT (افتراضي). @@ -1306,119 +1306,131 @@ If the problem persists after a restart, please send a debug log and open a supp PreferencesWindow::ConnectionWindowItem - - + + Allow LAN Traffic السماح بحركة مرور LAN - + + Terminate Sockets إنهاء المقابس - + + + Circumvent Censorship + + + + Connection اتصال - + Exclusive خاص - + Inclusive شامله - + Off قباله - + Network Options خيارات الشبكة - + Split Tunneling الانقسام النفقي - + Proxy Settings إعدادات الوكيل - + Connects to last used location when the app launches or joins a network. يتصل بآخر موقع مستخدم عند تشغيل التطبيق أو الانضمام إلى شبكة. - + Auto-Connect الاتصال التلقائي - + Control the mode of behavior of the Windscribe firewall. تحكم في وضع سلوك جدار الحماية Windscribe. - + Connection Mode وضع الاتصال - + Automatically choose the VPN protocol, or select one manually. اختر بروتوكول VPN تلقائيا ، أو حدد واحدا يدويا. - + Automatically determine the MTU for your connection, or manually override. تحديد وحدة الإرسال الكبرى تلقائيا لاتصالك، أو تجاوزها يدويا. - + Select the DNS server while connected to Windscribe. حدد خادم DNS أثناء الاتصال ب Windscribe. - + Allow access to local services and printers while connected to Windscribe. السماح بالوصول إلى الخدمات المحلية والطابعات أثناء الاتصال ب Windscribe. - + Spoof your device's physical address (MAC address). انتحال العنوان الفعلي لجهازك (عنوان MAC). - + Close all active TCP sockets when the VPN tunnel is established. أغلق كافة مآخذ توصيل TCP النشطة عند إنشاء نفق VPN. - + Configure your TV, gaming console, or other devices that support proxy servers. قم بتكوين التلفزيون أو وحدة التحكم في الألعاب أو الأجهزة الأخرى التي تدعم الخوادم الوكيلة. - - + + Connect to the VPN even in hostile environment. + + + + + Settings Conflict تعارض الإعدادات - + Disabling Allow LAN Traffic will cause your proxy gateway to stop working. Do you want to disable the proxy? سيؤدي تعطيل السماح بحركة مرور LAN إلى توقف بوابة الوكيل عن العمل. هل تريد تعطيل الوكيل؟ - + LAN traffic is currently blocked by the Windscribe firewall. Do you want to allow LAN traffic to bypass the firewall in order for this feature to work? يتم حظر حركة مرور LAN حاليا بواسطة جدار حماية Windscribe. هل تريد السماح لحركة مرور LAN بتجاوز جدار الحماية حتى تعمل هذه الميزة؟ @@ -2141,9 +2153,13 @@ Connect to a network first نقطة الاتصال الآمنة غير مدعومة بواسطة محول الشبكة. - Secure hotspot is not supported for IKEv2/WireGuard protocol and automatic connection mode. - نقطة الاتصال الآمنة غير مدعومة لبروتوكول IKEv2/WireGuard ووضع الاتصال التلقائي. + نقطة الاتصال الآمنة غير مدعومة لبروتوكول IKEv2/WireGuard ووضع الاتصال التلقائي. + + + + Secure hotspot is not supported for IKEv2 protocol. + diff --git a/client/gui/translations/ws_desktop_cs.ts b/client/gui/translations/ws_desktop_cs.ts index f09611425..a7558d575 100644 --- a/client/gui/translations/ws_desktop_cs.ts +++ b/client/gui/translations/ws_desktop_cs.ts @@ -37,52 +37,52 @@ ConnectWindow::ConnectWindowItem - + No Network Info Žádné informace o síti - + Unsecured Nezabezpečený - + Secured Zabezpečený - + Connection to Windscribe has been terminated. Připojení k Windscribe bylo ukončeno. - + transferred in převedeno do - + Connected for Připojeno pro - + transferred převedený - + Firewall Firewall - + Blocks all connectivity in the event of a sudden disconnect Blokuje veškerou konektivitu v případě náhlého odpojení - + Connect to rate Připojit k sazbě @@ -802,14 +802,14 @@ Nelze spustit updater (Chyba %1). Kontaktujte prosím podporu - + Lost connection to the backend process. Recovering... Došlo ke ztrátě připojení k back-endovému procesu. Uzdravování... - + Select an application Vyberte aplikaci @@ -989,18 +989,18 @@ Pokud problém přetrvává i po restartování, odešlete protokol ladění, ot Preferences - - + + Invalid DNS Settings Neplatná nastavení DNS - + 'Connected DNS' was not configured with a valid Upstream 1 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). "Připojený DNS" nebyl nakonfigurován s platným nadřazeným serverem 1 (IP/DNS-over-HTTPS/TLS). DNS byl vrácen na ROBERT (výchozí). - + 'Connected DNS' was not configured with a valid Upstream 2 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). "Připojený DNS" nebyl nakonfigurován s platným nadřazeným serverem 2 (IP/DNS-over-HTTPS/TLS). DNS byl vrácen na ROBERT (výchozí). @@ -1306,119 +1306,131 @@ Pokud problém přetrvává i po restartování, odešlete protokol ladění, ot PreferencesWindow::ConnectionWindowItem - - + + Allow LAN Traffic Povolit provoz v síti LAN - + + Terminate Sockets Ukončení zásuvek - + + + Circumvent Censorship + + + + Connection Připojení - + Exclusive Výhradní - + Inclusive Zahrnující - + Off Pryč - + Network Options Možnosti sítě - + Split Tunneling Dělené tunelové propojení - + Proxy Settings Nastavení proxy serveru - + Connects to last used location when the app launches or joins a network. Připojí se k naposledy použitému umístění, když se aplikace spustí nebo připojí k síti. - + Auto-Connect Automatické připojení - + Control the mode of behavior of the Windscribe firewall. Ovládejte režim chování brány firewall Windscribe. - + Connection Mode Režim připojení - + Automatically choose the VPN protocol, or select one manually. Automaticky vyberte protokol VPN nebo jej vyberte ručně. - + Automatically determine the MTU for your connection, or manually override. Automaticky určete jednotku MTU pro připojení nebo ručně přepište. - + Select the DNS server while connected to Windscribe. Vyberte server DNS při připojení k aplikaci Windscribe. - + Allow access to local services and printers while connected to Windscribe. Povolte přístup k místním službám a tiskárnám při připojení k aplikaci Windscribe. - + Spoof your device's physical address (MAC address). Falšování fyzické adresy (MAC adresy) zařízení. - + Close all active TCP sockets when the VPN tunnel is established. Zavřete všechny aktivní sokety TCP při vytvoření tunelu VPN. - + Configure your TV, gaming console, or other devices that support proxy servers. Nakonfigurujte televizor, herní konzoli nebo jiná zařízení, která podporují proxy servery. - - + + Connect to the VPN even in hostile environment. + + + + + Settings Conflict Konflikt nastavení - + Disabling Allow LAN Traffic will cause your proxy gateway to stop working. Do you want to disable the proxy? Zakázání možnosti Povolit provoz LAN způsobí, že brána proxy přestane fungovat. Chcete zakázat proxy server? - + LAN traffic is currently blocked by the Windscribe firewall. Do you want to allow LAN traffic to bypass the firewall in order for this feature to work? Provoz v síti LAN je v současné době blokován bránou firewall Windscribe. Chcete, aby přenosy v síti LAN obcházely bránu firewall, aby tato funkce fungovala? @@ -2141,9 +2153,13 @@ Nejprve se připojte k síti Zabezpečený hotspot není síťovým adaptérem podporován. - Secure hotspot is not supported for IKEv2/WireGuard protocol and automatic connection mode. - Zabezpečený hotspot není podporován protokolem IKEv2/WireGuard a režimem automatického připojení. + Zabezpečený hotspot není podporován protokolem IKEv2/WireGuard a režimem automatického připojení. + + + + Secure hotspot is not supported for IKEv2 protocol. + diff --git a/client/gui/translations/ws_desktop_de.ts b/client/gui/translations/ws_desktop_de.ts index 2ad6ce2de..7eddc70fb 100644 --- a/client/gui/translations/ws_desktop_de.ts +++ b/client/gui/translations/ws_desktop_de.ts @@ -37,52 +37,52 @@ ConnectWindow::ConnectWindowItem - + No Network Info Keine Netzwerkinformationen - + Unsecured Ungesichert - + Secured Gesichert - + Connection to Windscribe has been terminated. Die Verbindung zu Windscribe wurde beendet. - + transferred in übertragen in - + Connected for Verbunden für - + transferred überführt - + Firewall Firewall - + Blocks all connectivity in the event of a sudden disconnect Blockiert die gesamte Konnektivität im Falle einer plötzlichen Trennung - + Connect to rate Verbinden Sie sich mit dem Tarif @@ -832,14 +832,14 @@ Bitte wenden Sie sich an den Support - + Lost connection to the backend process. Recovering... Die Verbindung zum Backend-Prozess wurde unterbrochen. Genesend... - + Select an application Wählen Sie eine Anwendung aus @@ -989,18 +989,18 @@ Wenn das Problem nach einem Neustart weiterhin besteht, senden Sie bitte ein Deb Preferences - - + + Invalid DNS Settings Ungültige DNS-Einstellungen - + 'Connected DNS' was not configured with a valid Upstream 1 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). 'Verbundenes DNS' wurde nicht mit einem gültigen Upstream 1 (IP/DNS-over-HTTPS/TLS) konfiguriert. DNS wurde auf ROBERT zurückgesetzt (Standard). - + 'Connected DNS' was not configured with a valid Upstream 2 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). 'Verbundenes DNS' wurde nicht mit einem gültigen Upstream 2 (IP/DNS-over-HTTPS/TLS) konfiguriert. DNS wurde auf ROBERT zurückgesetzt (Standard). @@ -1306,119 +1306,131 @@ Wenn das Problem nach einem Neustart weiterhin besteht, senden Sie bitte ein Deb PreferencesWindow::ConnectionWindowItem - - + + Allow LAN Traffic LAN-Datenverkehr zulassen - + + Terminate Sockets Sockets beenden - + + + Circumvent Censorship + + + + Connection Verbindung - + Exclusive Ausschließlich - + Inclusive Inklusive - + Off Aus - + Network Options Netzwerk-Optionen - + Split Tunneling Geteiltes Tunneln - + Proxy Settings Proxy-Einstellungen - + Connects to last used location when the app launches or joins a network. Stellt eine Verbindung mit dem zuletzt verwendeten Standort her, wenn die App gestartet wird oder einem Netzwerk beitritt. - + Auto-Connect Automatische Verbindung - + Control the mode of behavior of the Windscribe firewall. Kontrollieren Sie den Modus des Verhaltens der Windscribe-Firewall. - + Connection Mode Verbindungsmodus - + Automatically choose the VPN protocol, or select one manually. Wählen Sie das VPN-Protokoll automatisch oder manuell aus. - + Automatically determine the MTU for your connection, or manually override. Ermitteln Sie automatisch die MTU für Ihre Verbindung oder setzen Sie sie manuell außer Kraft. - + Select the DNS server while connected to Windscribe. Wählen Sie den DNS-Server aus, während Sie mit Windscribe verbunden sind. - + Allow access to local services and printers while connected to Windscribe. Erlauben Sie den Zugriff auf lokale Dienste und Drucker, während Sie mit Windscribe verbunden sind. - + Spoof your device's physical address (MAC address). Fälschen Sie die physische Adresse Ihres Geräts (MAC-Adresse). - + Close all active TCP sockets when the VPN tunnel is established. Schließen Sie alle aktiven TCP-Sockets, wenn der VPN-Tunnel eingerichtet ist. - + Configure your TV, gaming console, or other devices that support proxy servers. Konfigurieren Sie Ihren Fernseher, Ihre Spielekonsole oder andere Geräte, die Proxyserver unterstützen. - - + + Connect to the VPN even in hostile environment. + + + + + Settings Conflict Einstellungskonflikt - + Disabling Allow LAN Traffic will cause your proxy gateway to stop working. Do you want to disable the proxy? Das Deaktivieren von LAN-Datenverkehr zulassen führt dazu, dass Ihr Proxy-Gateway nicht mehr funktioniert. Möchten Sie den Proxy deaktivieren? - + LAN traffic is currently blocked by the Windscribe firewall. Do you want to allow LAN traffic to bypass the firewall in order for this feature to work? Der LAN-Datenverkehr wird derzeit von der Windscribe-Firewall blockiert. Möchten Sie zulassen, dass LAN-Datenverkehr die Firewall umgeht, damit diese Funktion funktioniert? @@ -2141,9 +2153,13 @@ Zuerst eine Verbindung mit einem Netzwerk herstellen Der sichere Hotspot wird von Ihrem Netzwerkadapter nicht unterstützt. - Secure hotspot is not supported for IKEv2/WireGuard protocol and automatic connection mode. - Der sichere Hotspot wird für das IKEv2/WireGuard-Protokoll und den automatischen Verbindungsmodus nicht unterstützt. + Der sichere Hotspot wird für das IKEv2/WireGuard-Protokoll und den automatischen Verbindungsmodus nicht unterstützt. + + + + Secure hotspot is not supported for IKEv2 protocol. + diff --git a/client/gui/translations/ws_desktop_es.ts b/client/gui/translations/ws_desktop_es.ts index 773ef644d..20c056522 100644 --- a/client/gui/translations/ws_desktop_es.ts +++ b/client/gui/translations/ws_desktop_es.ts @@ -37,52 +37,52 @@ ConnectWindow::ConnectWindowItem - + No Network Info Sin información de red - + Unsecured Mal fijado - + Secured Asegurado - + Connection to Windscribe has been terminated. La conexión a Windscribe ha finalizado. - + transferred in transferido en - + Connected for Conectado para - + transferred Transferido - + Firewall Cortafuegos - + Blocks all connectivity in the event of a sudden disconnect Bloquea toda la conectividad en caso de una desconexión repentina - + Connect to rate Conéctese a la tarifa @@ -832,14 +832,14 @@ Póngase en contacto con el servicio de asistencia - + Lost connection to the backend process. Recovering... Se perdió la conexión con el proceso de backend. Recuperación... - + Select an application Seleccione una aplicación @@ -989,18 +989,18 @@ Si el problema persiste después de un reinicio, envíe un registro de depuraci Preferences - - + + Invalid DNS Settings Configuración de DNS no válida - + 'Connected DNS' was not configured with a valid Upstream 1 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). 'DNS conectado' no se configuró con un Upstream 1 válido (IP/DNS-over-HTTPS/TLS). DNS se revirtió a ROBERT (predeterminado). - + 'Connected DNS' was not configured with a valid Upstream 2 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). 'DNS conectado' no se configuró con un Upstream 2 válido (IP/DNS-over-HTTPS/TLS). DNS se revirtió a ROBERT (predeterminado). @@ -1306,119 +1306,131 @@ Si el problema persiste después de un reinicio, envíe un registro de depuraci PreferencesWindow::ConnectionWindowItem - - + + Allow LAN Traffic Permitir tráfico LAN - + + Terminate Sockets Terminar sockets - + + + Circumvent Censorship + + + + Connection Conexión - + Exclusive Exclusivo - + Inclusive Inclusivo - + Off Apagado - + Network Options Opciones de red - + Split Tunneling Túnel dividido - + Proxy Settings Configuración de proxy - + Connects to last used location when the app launches or joins a network. Se conecta a la última ubicación utilizada cuando la aplicación se inicia o se une a una red. - + Auto-Connect Conexión automática - + Control the mode of behavior of the Windscribe firewall. Controle el modo de comportamiento del firewall de Windscribe. - + Connection Mode Modo de conexión - + Automatically choose the VPN protocol, or select one manually. Elija automáticamente el protocolo VPN o seleccione uno manualmente. - + Automatically determine the MTU for your connection, or manually override. Determine automáticamente la MTU para su conexión o anule manualmente. - + Select the DNS server while connected to Windscribe. Seleccione el servidor DNS mientras está conectado a Windscribe. - + Allow access to local services and printers while connected to Windscribe. Permita el acceso a servicios e impresoras locales mientras está conectado a Windscribe. - + Spoof your device's physical address (MAC address). Suplantar la dirección física de su dispositivo (dirección MAC). - + Close all active TCP sockets when the VPN tunnel is established. Cierre todos los sockets TCP activos cuando se establezca el túnel VPN. - + Configure your TV, gaming console, or other devices that support proxy servers. Configure su televisor, consola de juegos u otros dispositivos que admitan servidores proxy. - - + + Connect to the VPN even in hostile environment. + + + + + Settings Conflict Conflicto de configuración - + Disabling Allow LAN Traffic will cause your proxy gateway to stop working. Do you want to disable the proxy? Si deshabilita Permitir tráfico LAN, la puerta de enlace proxy dejará de funcionar. ¿Desea desactivar el proxy? - + LAN traffic is currently blocked by the Windscribe firewall. Do you want to allow LAN traffic to bypass the firewall in order for this feature to work? El tráfico LAN está actualmente bloqueado por el firewall de Windscribe. ¿Desea permitir que el tráfico LAN evite el firewall para que esta función funcione? @@ -2141,9 +2153,13 @@ Conéctese primero a una red El adaptador de red no admite Secure Hotspot. - Secure hotspot is not supported for IKEv2/WireGuard protocol and automatic connection mode. - El punto de acceso seguro no es compatible con el protocolo IKEv2 / WireGuard y el modo de conexión automática. + El punto de acceso seguro no es compatible con el protocolo IKEv2 / WireGuard y el modo de conexión automática. + + + + Secure hotspot is not supported for IKEv2 protocol. + diff --git a/client/gui/translations/ws_desktop_fr.ts b/client/gui/translations/ws_desktop_fr.ts index 70ef6e151..222d8020b 100644 --- a/client/gui/translations/ws_desktop_fr.ts +++ b/client/gui/translations/ws_desktop_fr.ts @@ -37,52 +37,52 @@ ConnectWindow::ConnectWindowItem - + No Network Info Aucune information réseau - + Unsecured Non sécurisé - + Secured Sécurisé - + Connection to Windscribe has been terminated. La connexion à Windscribe a été interrompue. - + transferred in transféré en - + Connected for Connecté pour - + transferred Transféré - + Firewall Pare-feu - + Blocks all connectivity in the event of a sudden disconnect Bloque toute connectivité en cas de déconnexion soudaine - + Connect to rate Se connecter pour évaluer @@ -832,14 +832,14 @@ Veuillez contacter le support - + Lost connection to the backend process. Recovering... Perte de connexion au processus principal. Récupération... - + Select an application Sélectionner une application @@ -989,18 +989,18 @@ Si le problème persiste après un redémarrage, envoyez un journal de débogage Preferences - - + + Invalid DNS Settings Paramètres DNS non valides - + 'Connected DNS' was not configured with a valid Upstream 1 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). 'Connected DNS' n’a pas été configuré avec un Upstream 1 valide (IP/DNS-over-HTTPS/TLS). DNS est revenu à ROBERT (par défaut). - + 'Connected DNS' was not configured with a valid Upstream 2 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). 'Connected DNS' n’a pas été configuré avec un Upstream 2 valide (IP/DNS-over-HTTPS/TLS). DNS est revenu à ROBERT (par défaut). @@ -1306,119 +1306,131 @@ Si le problème persiste après un redémarrage, envoyez un journal de débogage PreferencesWindow::ConnectionWindowItem - - + + Allow LAN Traffic Autoriser le trafic LAN - + + Terminate Sockets Terminaison des sockets - + + + Circumvent Censorship + + + + Connection Connexion - + Exclusive Exclusif - + Inclusive Inclusif - + Off De - + Network Options Options réseau - + Split Tunneling Split Tunneling - + Proxy Settings Paramètres de proxy - + Connects to last used location when the app launches or joins a network. Se connecte au dernier emplacement utilisé lorsque l’application se lance ou rejoint un réseau. - + Auto-Connect Connexion automatique - + Control the mode of behavior of the Windscribe firewall. Contrôlez le mode de comportement du pare-feu Windscribe. - + Connection Mode Mode de connexion - + Automatically choose the VPN protocol, or select one manually. Choisissez automatiquement le protocole VPN ou sélectionnez-en un manuellement. - + Automatically determine the MTU for your connection, or manually override. Déterminez automatiquement la MTU de votre connexion ou remplacez-la manuellement. - + Select the DNS server while connected to Windscribe. Sélectionnez le serveur DNS lorsque vous êtes connecté à Windscribe. - + Allow access to local services and printers while connected to Windscribe. Autorisez l’accès aux services locaux et aux imprimantes lorsque vous êtes connecté à Windscribe. - + Spoof your device's physical address (MAC address). Usurper l’adresse physique de votre appareil (adresse MAC). - + Close all active TCP sockets when the VPN tunnel is established. Fermez tous les sockets TCP actifs lorsque le tunnel VPN est établi. - + Configure your TV, gaming console, or other devices that support proxy servers. Configurez votre téléviseur, votre console de jeu ou d’autres appareils prenant en charge les serveurs proxy. - - + + Connect to the VPN even in hostile environment. + + + + + Settings Conflict Conflit de paramètres - + Disabling Allow LAN Traffic will cause your proxy gateway to stop working. Do you want to disable the proxy? La désactivation de l’option Autoriser le trafic LAN entraînera l’arrêt du fonctionnement de votre passerelle proxy. Voulez-vous désactiver le proxy ? - + LAN traffic is currently blocked by the Windscribe firewall. Do you want to allow LAN traffic to bypass the firewall in order for this feature to work? Le trafic LAN est actuellement bloqué par le pare-feu Windscribe. Voulez-vous autoriser le trafic LAN à contourner le pare-feu pour que cette fonctionnalité fonctionne ? @@ -2141,9 +2153,13 @@ Se connecter d’abord à un réseau Le point d’accès sécurisé n’est pas pris en charge par votre carte réseau. - Secure hotspot is not supported for IKEv2/WireGuard protocol and automatic connection mode. - Le point d’accès sécurisé n’est pas pris en charge pour le protocole IKEv2/WireGuard et le mode de connexion automatique. + Le point d’accès sécurisé n’est pas pris en charge pour le protocole IKEv2/WireGuard et le mode de connexion automatique. + + + + Secure hotspot is not supported for IKEv2 protocol. + diff --git a/client/gui/translations/ws_desktop_hi.ts b/client/gui/translations/ws_desktop_hi.ts index fb5688b05..ff4c8bd44 100644 --- a/client/gui/translations/ws_desktop_hi.ts +++ b/client/gui/translations/ws_desktop_hi.ts @@ -37,52 +37,52 @@ ConnectWindow::ConnectWindowItem - + No Network Info कोई नेटवर्क जानकारी नहीं - + Unsecured असुरक्षित - + Secured सुरक्षित - + Connection to Windscribe has been terminated. विंडस्क्राइब से कनेक्शन समाप्त कर दिया गया है. - + transferred in में स्थानांतरित - + Connected for के लिए कनेक्ट डे - + transferred स्थानांतरित - + Firewall फ़ायरवॉल - + Blocks all connectivity in the event of a sudden disconnect अचानक डिस्कनेक्ट होने की स्थिति में सभी कनेक्टिविटी ब्लॉक - + Connect to rate दर से कनेक्ट करें @@ -832,14 +832,14 @@ कृपया समर्थन से संपर्क करें - + Lost connection to the backend process. Recovering... बैकएंड प्रक्रिया से कनेक्शन खो गया. ठीक।।। - + Select an application किसी अनुप्रयोग का चयन करें @@ -989,18 +989,18 @@ If the problem persists after a restart, please send a debug log and open a supp Preferences - - + + Invalid DNS Settings अमान्य DNS सेटिंग्स - + 'Connected DNS' was not configured with a valid Upstream 1 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). 'कनेक्टेड DNS' को मान्य अपस्ट्रीम 1 (IP/DNS-over-HTTPS/TLS) के साथ कॉन्फ़िगर नहीं किया गया था. DNS को ROBERT (डिफ़ॉल्ट) में वापस कर दिया गया था। - + 'Connected DNS' was not configured with a valid Upstream 2 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). 'कनेक्टेड DNS' को मान्य अपस्ट्रीम 2 (IP/DNS-over-HTTPS/TLS) के साथ कॉन्फ़िगर नहीं किया गया था. DNS को ROBERT (डिफ़ॉल्ट) में वापस कर दिया गया था। @@ -1306,119 +1306,131 @@ If the problem persists after a restart, please send a debug log and open a supp PreferencesWindow::ConnectionWindowItem - - + + Allow LAN Traffic LAN ट्रैफ़िक की अनुमति दें - + + Terminate Sockets सॉकेट समाप्त करें - + + + Circumvent Censorship + + + + Connection नाता - + Exclusive निवारक - + Inclusive सम्मिलित - + Off बंद - + Network Options नेटवर्क विकल्प - + Split Tunneling स्प्लिट टनलिंग - + Proxy Settings प्रॉक्सी सेटिंग्स - + Connects to last used location when the app launches or joins a network. ऐप लॉन्च होने या नेटवर्क में शामिल होने पर अंतिम उपयोग किए गए स्थान से कनेक्ट होता है। - + Auto-Connect ऑटो-कनेक्ट - + Control the mode of behavior of the Windscribe firewall. विंडस्क्राइब फ़ायरवॉल के व्यवहार के तरीके को नियंत्रित करें। - + Connection Mode कनेक्शन मोड - + Automatically choose the VPN protocol, or select one manually. स्वचालित रूप से वीपीएन प्रोटोकॉल चुनें, या मैन्युअल रूप से एक का चयन करें। - + Automatically determine the MTU for your connection, or manually override. स्वचालित रूप से अपने कनेक्शन के लिए MTU निर्धारित करें, या मैन्युअल रूप से ओवरराइड करें। - + Select the DNS server while connected to Windscribe. विंडस्क्राइब से कनेक्ट करते समय DNS सर्वर का चयन करें। - + Allow access to local services and printers while connected to Windscribe. विंडस्क्राइब से कनेक्ट होने के दौरान स्थानीय सेवाओं और प्रिंटर तक पहुंच की अनुमति दें। - + Spoof your device's physical address (MAC address). अपने डिवाइस के भौतिक पते (MAC पता) को स्पूफ करें। - + Close all active TCP sockets when the VPN tunnel is established. वीपीएन सुरंग स्थापित होने पर सभी सक्रिय टीसीपी सॉकेट बंद करें। - + Configure your TV, gaming console, or other devices that support proxy servers. अपने टीवी, गेमिंग कंसोल, या प्रॉक्सी सर्वर का समर्थन करने वाले अन्य डिवाइस कॉन्फ़िगर करें। - - + + Connect to the VPN even in hostile environment. + + + + + Settings Conflict सेटिंग्स विरोध - + Disabling Allow LAN Traffic will cause your proxy gateway to stop working. Do you want to disable the proxy? LAN ट्रैफ़िक की अनुमति अक्षम करने से आपका प्रॉक्सी गेटवे काम करना बंद कर देगा। क्या आप प्रॉक्सी को अक्षम करना चाहते हैं? - + LAN traffic is currently blocked by the Windscribe firewall. Do you want to allow LAN traffic to bypass the firewall in order for this feature to work? लैन यातायात वर्तमान में विंडस्क्राइब फ़ायरवॉल द्वारा अवरुद्ध है। क्या आप इस सुविधा के काम करने के लिए LAN ट्रैफ़िक को फ़ायरवॉल को बायपास करने की अनुमति देना चाहते हैं? @@ -2141,9 +2153,13 @@ Connect to a network first सुरक्षित हॉटस्पॉट आपके नेटवर्क एडाप्टर द्वारा समर्थित नहीं है। - Secure hotspot is not supported for IKEv2/WireGuard protocol and automatic connection mode. - सुरक्षित हॉटस्पॉट IKEv2/WireGuard प्रोटोकॉल और स्वचालित कनेक्शन मोड के लिए समर्थित नहीं है। + सुरक्षित हॉटस्पॉट IKEv2/WireGuard प्रोटोकॉल और स्वचालित कनेक्शन मोड के लिए समर्थित नहीं है। + + + + Secure hotspot is not supported for IKEv2 protocol. + diff --git a/client/gui/translations/ws_desktop_ru.ts b/client/gui/translations/ws_desktop_ru.ts index 205cb8a3c..a3e51c2f4 100644 --- a/client/gui/translations/ws_desktop_ru.ts +++ b/client/gui/translations/ws_desktop_ru.ts @@ -31,58 +31,58 @@ ESC - Закрыть + Закр. ConnectWindow::ConnectWindowItem - + No Network Info Нет информации о сети - + Unsecured Не защищена - + Secured Защищена - + Connection to Windscribe has been terminated. Соединение с Windscribe было прервано. - + transferred in переведено в - + Connected for Подключено - + transferred передано - + Firewall Брандмауэр - + Blocks all connectivity in the event of a sudden disconnect Заблокирует все соединения в случае внезапного отключения VPN - + Connect to rate Подключитесь, чтобы оценить сервер @@ -1307,108 +1307,109 @@ If the problem persists after a restart, please send a debug log and open a supp PreferencesWindow::ConnectionWindowItem - + Allow LAN Traffic - Разрешить трафик локальной сети + Разрешить трафик LAN + Terminate Sockets Закрытие сокетов - - + + Circumvent Censorship Обход блокировок - + Connection Связь - + Exclusive Исключающий - + Inclusive Включающий - + Off Выкл. - + Network Options - Параметры сети + Параметры сетей - + Split Tunneling Раздельное туннелирование - + Proxy Settings Настройки прокси-сервера - + Connects to last used location when the app launches or joins a network. Подключаться к последней используемой локации при запуске приложения или присоединении к сети. - + Auto-Connect Автоматическое подключение - + Control the mode of behavior of the Windscribe firewall. Управление режимом поведения брандмауэра Windscribe. - + Connection Mode Режим подключения - + Automatically choose the VPN protocol, or select one manually. Выбор VPN-протокола автоматически или вручную - + Automatically determine the MTU for your connection, or manually override. Автоматическое определение MTU для подключения или переопределение вручную. - + Select the DNS server while connected to Windscribe. Выберите DNS-сервер при подключении к Windscribe. - + Allow access to local services and printers while connected to Windscribe. Разрешить доступ к локальным службам и принтерам при подключении к Windscribe. - + Spoof your device's physical address (MAC address). Подделка физичесого адреса (MAC-адреса) устройства. - + Close all active TCP sockets when the VPN tunnel is established. Закрытие всех активных TCP-соединений при установке VPN-туннеля. - + Configure your TV, gaming console, or other devices that support proxy servers. Настройка телевизора, игровой консоли и других устройств, поддерживающих прокси-серверы. @@ -1538,7 +1539,7 @@ If the problem persists after a restart, please send a debug log and open a supp Launch on Startup - Запуск при включении ОС + Запуск при вкл. ОС @@ -1578,7 +1579,7 @@ If the problem persists after a restart, please send a debug log and open a supp Docked - Закреплённый + Закреплённый вид @@ -1598,7 +1599,7 @@ If the problem persists after a restart, please send a debug log and open a supp Show Location Load - Отображать нагрузку локаций + Нагрузка локаций @@ -1618,7 +1619,7 @@ If the problem persists after a restart, please send a debug log and open a supp Latency Display - Отображение задержки + Вид задержки @@ -1648,7 +1649,7 @@ If the problem persists after a restart, please send a debug log and open a supp Choose to receive stable, beta, or experimental builds. - Выбор получения стабильных, бета- или экспериментальных сборок. + Выбор получения стабильных, бета или экспериментальных сборок. @@ -1840,7 +1841,7 @@ If the problem persists after a restart, please send a debug log and open a supp Auto-Secure Networks - Автоматически безопасные сети + Автозащита сетей @@ -2338,7 +2339,7 @@ If the reinstall does not help, please contact Windscribe support for assistance Include or exclude apps and hostnames from the VPN tunnel. - Включение или исключение приложений и имен узлов из VPN-туннеля. + Включение или исключение приложений и адресов/доменов из VPN-туннеля. @@ -2461,17 +2462,17 @@ If the reinstall does not help, please contact Windscribe support for assistance Geography - География + Географически Alphabet - Алфавит + В алфавитном порядке Latency - Задержка + По задержке (пингу) diff --git a/client/gui/translations/ws_desktop_zh.ts b/client/gui/translations/ws_desktop_zh.ts index 748f64223..1f14bc4a6 100644 --- a/client/gui/translations/ws_desktop_zh.ts +++ b/client/gui/translations/ws_desktop_zh.ts @@ -37,52 +37,52 @@ ConnectWindow::ConnectWindowItem - + No Network Info 暂无网络信息 - + Unsecured 担保 - + Secured 担保 - + Connection to Windscribe has been terminated. 与Windscribe的连接已终止。 - + transferred in 转入 - + Connected for 已连接 - + transferred 转移 - + Firewall 防火墙 - + Blocks all connectivity in the event of a sudden disconnect 在突然断开连接时阻止所有连接 - + Connect to rate 连接费率 @@ -802,14 +802,14 @@ 无法运行更新程序(错误 %1)。 请联系支持人员 - + Lost connection to the backend process. Recovering... 与后端进程的连接丢失。 恢复。。。 - + Select an application 选择一个应用程序 @@ -989,18 +989,18 @@ If the problem persists after a restart, please send a debug log and open a supp Preferences - - + + Invalid DNS Settings 无效的 DNS 设置 - + 'Connected DNS' was not configured with a valid Upstream 1 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). “连接的 DNS”未配置有效的上游 1(IP/DNS-over-HTTPS/TLS)。DNS 已恢复为 ROBERT(默认)。 - + 'Connected DNS' was not configured with a valid Upstream 2 (IP/DNS-over-HTTPS/TLS). DNS was reverted to ROBERT (default). “连接的 DNS”未配置有效的上游 2(IP/DNS-over-HTTPS/TLS)。DNS 已恢复为 ROBERT(默认)。 @@ -1306,119 +1306,131 @@ If the problem persists after a restart, please send a debug log and open a supp PreferencesWindow::ConnectionWindowItem - - + + Allow LAN Traffic 允许局域网流量 - + + Terminate Sockets 终止套接字 - + + + Circumvent Censorship + + + + Connection 连接 - + Exclusive 独家 - + Inclusive 包容 - + Off 关闭 - + Network Options 网络选项 - + Split Tunneling 拆分隧道 - + Proxy Settings 代理设置 - + Connects to last used location when the app launches or joins a network. 在应用启动或加入网络时连接到上次使用的位置。 - + Auto-Connect 自动连接 - + Control the mode of behavior of the Windscribe firewall. 控制 Windscribe 防火墙的行为模式。 - + Connection Mode 连接模式 - + Automatically choose the VPN protocol, or select one manually. 自动选择 VPN 协议,或手动选择一个。 - + Automatically determine the MTU for your connection, or manually override. 自动确定连接的 MTU,或手动覆盖。 - + Select the DNS server while connected to Windscribe. 在连接到Windscribe时选择DNS服务器。 - + Allow access to local services and printers while connected to Windscribe. 允许在连接到 Windscribe 时访问本地服务和打印机。 - + Spoof your device's physical address (MAC address). 欺骗设备的物理地址(MAC 地址)。 - + Close all active TCP sockets when the VPN tunnel is established. 建立 VPN 隧道后关闭所有活动的 TCP 套接字。 - + Configure your TV, gaming console, or other devices that support proxy servers. 配置电视、游戏机或其他支持代理服务器的设备。 - - + + Connect to the VPN even in hostile environment. + + + + + Settings Conflict 设置冲突 - + Disabling Allow LAN Traffic will cause your proxy gateway to stop working. Do you want to disable the proxy? 禁用允许 LAN 流量将导致代理网关停止工作。 是否要禁用代理? - + LAN traffic is currently blocked by the Windscribe firewall. Do you want to allow LAN traffic to bypass the firewall in order for this feature to work? LAN 流量目前被 Windscribe 防火墙阻止。 是否要允许 LAN 流量绕过防火墙以使此功能正常工作? @@ -2141,9 +2153,13 @@ Connect to a network first 您的网络适配器不支持安全热点。 - Secure hotspot is not supported for IKEv2/WireGuard protocol and automatic connection mode. - IKEv2/WireGuard 协议和自动连接模式不支持安全热点。 + IKEv2/WireGuard 协议和自动连接模式不支持安全热点。 + + + + Secure hotspot is not supported for IKEv2 protocol. + diff --git a/installer/linux/additional_files/arm64/wstunnel/readme.txt b/installer/linux/additional_files/arm64/wstunnel/readme.txt deleted file mode 100644 index a9c8e0cf3..000000000 --- a/installer/linux/additional_files/arm64/wstunnel/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Precompiled binary of wstunnel v4.1 aarch64 for Linux. Copies to engine bundle when building engine project. - -https://github.com/erebe/wstunnel/releases diff --git a/installer/linux/additional_files/arm64/wstunnel/windscribewstunnel b/installer/linux/additional_files/arm64/wstunnel/windscribewstunnel deleted file mode 100755 index 08f9c11e9..000000000 Binary files a/installer/linux/additional_files/arm64/wstunnel/windscribewstunnel and /dev/null differ diff --git a/installer/linux/additional_files/x86_64/wstunnel/readme.txt b/installer/linux/additional_files/x86_64/wstunnel/readme.txt deleted file mode 100644 index dbc4e7a59..000000000 --- a/installer/linux/additional_files/x86_64/wstunnel/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Precompiled binary of wstunnel v4 x64 for Linux. Copies to engine bundle when building engine project. - -https://github.com/erebe/wstunnel/releases diff --git a/installer/linux/additional_files/x86_64/wstunnel/windscribewstunnel b/installer/linux/additional_files/x86_64/wstunnel/windscribewstunnel deleted file mode 100755 index 5e8bd50e9..000000000 Binary files a/installer/linux/additional_files/x86_64/wstunnel/windscribewstunnel and /dev/null differ diff --git a/installer/windows/additional_files/wstunnel/wstunnel.exe b/installer/windows/additional_files/wstunnel/wstunnel.exe deleted file mode 100644 index 51b1e9e8c..000000000 Binary files a/installer/windows/additional_files/wstunnel/wstunnel.exe and /dev/null differ diff --git a/tools/build_all.py b/tools/build_all.py index c04da7abe..1b03f3df3 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -612,14 +612,6 @@ def build_installer_linux(configdata, qt_root): dstfile = os.path.join(BUILD_INSTALLER_FILES, k) fix_rpath_linux(dstfile) - # Copy wstunnel into InstallerFiles - msg.Info("Copying wstunnel...") - if platform.processor() == "aarch64": - wstunnel_dir = os.path.join(pathhelper.ROOT_DIR, "installer", "linux", "additional_files", "arm64", "wstunnel") - else: - wstunnel_dir = os.path.join(pathhelper.ROOT_DIR, "installer", "linux", "additional_files", "x86_64", "wstunnel") - copy_file("windscribewstunnel", wstunnel_dir, BUILD_INSTALLER_FILES) - # sign supplementary binaries and move the signatures into InstallerFiles/signatures if arghelper.sign_app() and "linux" in configdata["codesign_files"]: for binary_name in configdata["codesign_files"]["linux"]: diff --git a/tools/build_all.yml b/tools/build_all.yml index 87cfb7805..cb5d22506 100644 --- a/tools/build_all.yml +++ b/tools/build_all.yml @@ -138,7 +138,6 @@ client_deploy_files: - vcruntime140.dll - vcruntime140_1.dll additional_files: - - wstunnel/wstunnel.exe -> wstunnel.exe - subinacl.exe libs: qt: @@ -160,8 +159,6 @@ client_deploy_files: - lib/cares.dll -> cares.dll curl: - bin/libcurl.dll -> libcurl.dll - stunnel: - - tstunnel.exe -> tstunnel.exe zlib: - lib/zlib1.dll -> zlib1.dll openvpn: @@ -171,6 +168,8 @@ client_deploy_files: - wireguard.dll -> wireguard.dll ctrld: - ctrld.exe -> windscribectrld.exe + wstunnel: + - windscribewstunnel.exe -> windscribewstunnel.exe # The dga library should be in the build-libs directory. If it is not there, then it will not be included in the installer. dga: - dga.dll -> dga.dll @@ -221,7 +220,7 @@ client_deploy_files: openssl_ech_draft: - lib/libssl.3.dylib -> libssl.3.dylib - lib/libcrypto.3.dylib -> libcrypto.3.dylib - Contents/Helpers/windscribestunnel: + Contents/Helpers/windscribewstunnel: openssl_ech_draft: - lib/libssl.3.dylib -> libssl.3.dylib - lib/libcrypto.3.dylib -> libcrypto.3.dylib @@ -235,7 +234,6 @@ client_deploy_files: # Remove unused Qt frameworks. - Contents/Frameworks/QtQml.framework - Contents/Frameworks/QtQuick.framework - - stunnel linux_x86_64: libs: @@ -293,12 +291,13 @@ client_deploy_files: - libdga.so -> lib/libdga.so openvpn: - openvpn -> windscribeopenvpn - stunnel: - - stunnel -> windscribestunnel ctrld: - ctrld -> windscribectrld wireguard: - windscribewireguard -> windscribewireguard + wstunnel: + - windscribewstunnel -> windscribewstunnel + fix_rpath: - lib/libQt6Network.so.6 -> $ORIGIN - lib/libQt6XcbQpa.so.6 -> $ORIGIN @@ -306,7 +305,6 @@ client_deploy_files: - lib/libcurl.so.4 -> $ORIGIN - lib/libssl.so.3 -> $ORIGIN - lib/libcrypto.so.3 -> $ORIGIN - - windscribestunnel -> $ORIGIN/lib - windscribeopenvpn -> $ORIGIN/lib - windscribe-authhelper -> $ORIGIN/lib - Windscribe -> $ORIGIN/lib @@ -330,7 +328,6 @@ codesign_files: - libcrypto-3-arm64.dll - libssl-3-arm64.dll linux: - - windscribestunnel - windscribewstunnel - windscribeopenvpn - windscribectrld @@ -353,5 +350,3 @@ rpath_fix_files_mac: - lib/libcurl.4.dylib openvpn: - openvpn - stunnel: - - stunnel diff --git a/tools/deps/custom_wstunnel/rsrc_windows_amd64.syso b/tools/deps/custom_wstunnel/rsrc_windows_amd64.syso new file mode 100644 index 000000000..6368382d4 Binary files /dev/null and b/tools/deps/custom_wstunnel/rsrc_windows_amd64.syso differ diff --git a/tools/deps/custom_wstunnel/rsrc_windows_arm64.syso b/tools/deps/custom_wstunnel/rsrc_windows_arm64.syso new file mode 100644 index 000000000..5f98a513b Binary files /dev/null and b/tools/deps/custom_wstunnel/rsrc_windows_arm64.syso differ diff --git a/tools/deps/custom_wstunnel/wstunnel.rc b/tools/deps/custom_wstunnel/wstunnel.rc new file mode 100644 index 000000000..7e8d5a39d --- /dev/null +++ b/tools/deps/custom_wstunnel/wstunnel.rc @@ -0,0 +1,36 @@ +#include +#include "../../../client/common/version/windscribe_version.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1, 0, 1, 0 + PRODUCTVERSION 1, 0, 1, 0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Windscribe Limited\0" + VALUE "FileDescription", "Windscribe wstunnel\0" + VALUE "FileVersion", "1.0.1\0" + VALUE "LegalCopyright", WINDSCRIBE_COPYRIGHT_STR + VALUE "OriginalFilename", "windscribewstunnel.exe\0" + VALUE "ProductName", "Windscribe wstunnel\0" + VALUE "ProductVersion", "1.0.1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1200 + END + END +/* End of Version info */ + diff --git a/tools/deps/install_stunnel b/tools/deps/install_wstunnel similarity index 79% rename from tools/deps/install_stunnel rename to tools/deps/install_wstunnel index ea8a2f433..b607dcca4 100755 --- a/tools/deps/install_stunnel +++ b/tools/deps/install_wstunnel @@ -5,4 +5,4 @@ #------------------------------------------------------------------------------- tools_dir=$(dirname "$0") -PYTHONDONTWRITEBYTECODE=1 exec python3 "$tools_dir/install_stunnel.py" "$@" +PYTHONDONTWRITEBYTECODE=1 exec python3 "$tools_dir/install_wstunnel.py" "$@" diff --git a/tools/deps/install_stunnel.bat b/tools/deps/install_wstunnel.bat similarity index 91% rename from tools/deps/install_stunnel.bat rename to tools/deps/install_wstunnel.bat index 660fe1467..ffa1842fa 100644 --- a/tools/deps/install_stunnel.bat +++ b/tools/deps/install_wstunnel.bat @@ -15,6 +15,6 @@ set PYTHONDONTWRITEBYTECODE=1 set python_dir=%PYTHONHOME% if not "%python_dir%" == "" set python_dir=%python_dir%\ -%python_dir%python3 "%tools_dir%\install_stunnel.py" %* +%python_dir%python3 "%tools_dir%\install_wstunnel.py" %* if _%pause_on_exit%_==_1_ pause exit /B %ERRORLEVEL% diff --git a/tools/deps/install_stunnel.py b/tools/deps/install_wstunnel.py similarity index 53% rename from tools/deps/install_stunnel.py rename to tools/deps/install_wstunnel.py index 5796954f6..83e32bf5f 100644 --- a/tools/deps/install_stunnel.py +++ b/tools/deps/install_wstunnel.py @@ -1,17 +1,17 @@ #!/usr/bin/env python # ------------------------------------------------------------------------------ -# Windscribe Build System +# ESET VPN Build System # Copyright (c) 2020-2023, Windscribe Limited. All rights reserved. # ------------------------------------------------------------------------------ -# Purpose: installs stunnel executable. +# Purpose: installs Wstunnel executables. import os +import shutil import sys import time - TOOLS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, TOOLS_DIR) -CONFIG_NAME = os.path.join("vars", "stunnel.yml") +CONFIG_NAME = os.path.join("vars", "wstunnel.yml") # To ensure modules in the 'base' folder can import other modules in base. import base.pathhelper as pathhelper @@ -22,43 +22,31 @@ import installutils as iutl # Dependency-specific settings. -DEP_TITLE = "stunnel" -DEP_URL = "https://www.stunnel.org/archive/5.x/" +DEP_TITLE = "wstunnel" +DEP_URL = "https://github.com/Windscribe/wstunnel.git" DEP_OS_LIST = ["win32", "macos", "linux"] -DEP_FILE_MASK = ["tstunnel.exe", "stunnel"] +DEP_FILE_MASK = ["windscribewstunnel.exe", "windscribewstunnel"] -def BuildDependencyMSVC(openssl_root, outpath): - # Create an environment with VS vars. +def BuildDependencyMSVC(): buildenv = os.environ.copy() - buildenv.update({"MAKEFLAGS": "S"}) - buildenv.update(iutl.GetVisualStudioEnvironment(is_arm64_build)) - buildenv.update({"CL": "/D_WINSOCK_DEPRECATED_NO_WARNINGS /FS"}) # /FS needed for JOM. - target_arch = "arm64" if is_arm64_build else "win64" - buildenv.update({"NEWTGTCPU": "W32", "OPENSSL_HOME": openssl_root, "TARGET_ARCH": target_arch}) - currend_wd = os.getcwd() - os.chdir("src") - # Build and install. - build_cmd = iutl.GetMakeBuildCommand() - build_cmd.extend(["/F", "vc.mak"]) - iutl.RunCommand(build_cmd, env=buildenv, shell=True) - utl.CopyFile("{}/bin/{}/tstunnel.exe".format(currend_wd, target_arch), "{}/tstunnel.exe".format(outpath)) + buildenv.update({"GOARCH": "arm64" if is_arm64_build else "amd64", "GOOS": "windows"}) + iutl.RunCommand(["go", "build", "-o", os.path.join("build", "windscribewstunnel.exe"), "-a", "-gcflags=all=-l -B", "-ldflags=-w -s"], env=buildenv) -def BuildDependencyGNU(openssl_root, outpath): - # Create an environment with CC flags. +def BuildDependencyMacOS(): buildenv = os.environ.copy() - # Configure. - configure_cmd = ["./configure"] - if utl.GetCurrentOS() == "macos": - configure_cmd.append("CFLAGS=-arch x86_64 -arch arm64 -mmacosx-version-min=10.14") - configure_cmd.append("--prefix={}".format(outpath)) - configure_cmd.append("--with-ssl={}".format(openssl_root)) - iutl.RunCommand(configure_cmd, env=buildenv) - # Build and install. - iutl.RunCommand(iutl.GetMakeBuildCommand(), env=buildenv) - iutl.RunCommand(["make", "install-exec", "-s"], env=buildenv) - utl.CopyFile("{}/bin/stunnel".format(outpath), "{}/stunnel".format(outpath)) + buildenv.update({"GOARCH": "arm64", "GOOS": "darwin"}) + iutl.RunCommand(["go", "build", "-o", os.path.join("build", "windscribewstunnel-arm64"), "-a", "-gcflags=all=-l -B", "-ldflags=-w -s"], env=buildenv) + buildenv = os.environ.copy() + buildenv.update({"GOARCH": "amd64", "GOOS": "darwin"}) + iutl.RunCommand(["go", "build", "-o", os.path.join("build", "windscribewstunnel-amd64"), "-a", "-gcflags=all=-l -B", "-ldflags=-w -s"], env=buildenv) + + +def BuildDependencyLinux(): + buildenv = os.environ.copy() + buildenv.update({"GOARCH": "arm64" if is_arm64_build else "amd64", "GOOS": "linux"}) + iutl.RunCommand(["go", "build", "-o", os.path.join("build", "windscribewstunnel"), "-a", "-gcflags=all=-l -B", "-ldflags=-w -s"], env=buildenv) def InstallDependency(): @@ -73,32 +61,37 @@ def InstallDependency(): dep_version_str = os.environ.get(dep_version_var, None) if not dep_version_str: raise iutl.InstallError("{} not defined.".format(dep_version_var)) - openssl_root = iutl.GetDependencyBuildRoot("openssl_ech_draft") - if not openssl_root: - raise iutl.InstallError("OpenSSL is not installed.") # Prepare output. temp_dir = iutl.PrepareTempDirectory(dep_name) - # Download and unpack the archive. - archivetitle = "{}-{}".format(dep_name, dep_version_str) - archivename = archivetitle + ".tar.gz" - localfilename = os.path.join(temp_dir, archivename) - msg.HeadPrint("Downloading: \"{}\"".format(archivename)) - iutl.DownloadFile("{}{}".format(DEP_URL, archivename), localfilename) - msg.HeadPrint("Extracting: \"{}\"".format(archivename)) - iutl.ExtractFile(localfilename) - # Copy modified files. - iutl.CopyCustomFiles(dep_name, os.path.join(temp_dir, archivetitle)) + with utl.PushDir(os.path.join(temp_dir)): + iutl.RunCommand(["git", "clone", DEP_URL, "."]) + iutl.RunCommand(["git", "checkout", "tags/{}".format(dep_version_str)]) dep_buildroot_str = os.path.join("build-libs-arm64" if is_arm64_build else "build-libs", dep_name) outpath = os.path.normpath(os.path.join(os.path.dirname(TOOLS_DIR), dep_buildroot_str)) # Clean the output folder to ensure no conflicts when we're updating to a newer stunnel version. utl.RemoveDirectory(outpath) # Build the dependency. - with utl.PushDir(os.path.join(temp_dir, archivetitle)): - msg.HeadPrint("Building: \"{}\"".format(archivetitle)) - if utl.GetCurrentOS() == "win32": - BuildDependencyMSVC(openssl_root, temp_dir) - else: - BuildDependencyGNU(openssl_root, temp_dir) + msg.Info("Building: {}".format(DEP_TITLE)) + if utl.GetCurrentOS() == "macos": + with utl.PushDir(os.path.join(temp_dir)): + BuildDependencyMacOS() + utl.CreateDirectory(outpath) + with utl.PushDir(temp_dir): + iutl.RunCommand([ + "lipo", + "-create", + os.path.join("build", "windscribewstunnel-amd64"), + os.path.join("build", "windscribewstunnel-arm64"), + "-output", + os.path.join("build", "windscribewstunnel")]) + elif utl.GetCurrentOS() == "win32": + shutil.copyfile(os.path.join(TOOLS_DIR, "deps", "custom_wstunnel", "rsrc_windows_arm64.syso" if is_arm64_build else "rsrc_windows_amd64.syso"), os.path.join(temp_dir, "rsrc.syso")) + with utl.PushDir(temp_dir): + BuildDependencyMSVC() + else: + with utl.PushDir(temp_dir): + BuildDependencyLinux() + # Copy the dependency to output directory and to a zip file, if needed. installzipname = None if "-zip" in sys.argv: @@ -106,9 +99,7 @@ def InstallDependency(): dep_artifact_str = os.environ.get(dep_artifact_var, "{}.zip".format(dep_name)) installzipname = os.path.join(os.path.dirname(outpath), dep_artifact_str) msg.Print("Installing artifacts...") - aflist = iutl.InstallArtifacts(temp_dir, DEP_FILE_MASK, outpath, installzipname) - for af in aflist: - msg.HeadPrint("Ready: \"{}\"".format(af)) + iutl.InstallArtifacts(os.path.join(temp_dir, "build"), DEP_FILE_MASK, outpath, installzipname) # Cleanup. msg.Print("Cleaning temporary directory...") utl.RemoveDirectory(temp_dir) diff --git a/tools/vars/stunnel.yml b/tools/vars/wstunnel.yml similarity index 80% rename from tools/vars/stunnel.yml rename to tools/vars/wstunnel.yml index 2268911eb..1afa4089e 100644 --- a/tools/vars/stunnel.yml +++ b/tools/vars/wstunnel.yml @@ -3,5 +3,5 @@ # Copyright (c) 2020-2021, Windscribe Limited. All rights reserved. # ------------------------------------------------------------------------------ variables: - VERSION_STUNNEL: '5.66' - ARTIFACT_STUNNEL: 'stunnel.zip' + VERSION_WSTUNNEL: '1.0.1' + ARTIFACT_WSTUNNEL: 'wstunnel.zip'