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
-
+
لا توجد معلومات الشبكة
-
+
غير المضمونين
-
+
المضمون
-
+
تم إنهاء الاتصال ب Windscribe.
-
+
نقل في
-
+
متصل ل
-
+
نقل
-
+
جدار حمايه
-
+
يحظر كل الاتصال في حالة انقطاع الاتصال المفاجئ
-
+
الاتصال بالسعر
@@ -832,14 +832,14 @@
يرجى الاتصال بالدعم
-
+
فقد الاتصال بعملية الواجهة الخلفية.
يتعافي...
-
+
حدد تطبيقا
@@ -989,18 +989,18 @@ If the problem persists after a restart, please send a debug log and open a supp
Preferences
-
-
+
+
إعدادات DNS غير صالحة
-
+
لم يتم تكوين "DNS المتصل" باستخدام Upstream 1 صالح (IP / DNS عبر HTTPS / TLS). تمت إعادة DNS إلى ROBERT (افتراضي).
-
+
لم يتم تكوين "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
-
-
+
+
السماح بحركة مرور LAN
-
+
+
إنهاء المقابس
-
+
+
+
+
+
+
+
اتصال
-
+
خاص
-
+
شامله
-
+
قباله
-
+
خيارات الشبكة
-
+
الانقسام النفقي
-
+
إعدادات الوكيل
-
+
يتصل بآخر موقع مستخدم عند تشغيل التطبيق أو الانضمام إلى شبكة.
-
+
الاتصال التلقائي
-
+
تحكم في وضع سلوك جدار الحماية Windscribe.
-
+
وضع الاتصال
-
+
اختر بروتوكول VPN تلقائيا ، أو حدد واحدا يدويا.
-
+
تحديد وحدة الإرسال الكبرى تلقائيا لاتصالك، أو تجاوزها يدويا.
-
+
حدد خادم DNS أثناء الاتصال ب Windscribe.
-
+
السماح بالوصول إلى الخدمات المحلية والطابعات أثناء الاتصال ب Windscribe.
-
+
انتحال العنوان الفعلي لجهازك (عنوان MAC).
-
+
أغلق كافة مآخذ توصيل TCP النشطة عند إنشاء نفق VPN.
-
+
قم بتكوين التلفزيون أو وحدة التحكم في الألعاب أو الأجهزة الأخرى التي تدعم الخوادم الوكيلة.
-
-
+
+
+
+
+
+
+
تعارض الإعدادات
-
+
سيؤدي تعطيل السماح بحركة مرور LAN إلى توقف بوابة الوكيل عن العمل. هل تريد تعطيل الوكيل؟
-
+
يتم حظر حركة مرور LAN حاليا بواسطة جدار حماية Windscribe. هل تريد السماح لحركة مرور LAN بتجاوز جدار الحماية حتى تعمل هذه الميزة؟
@@ -2141,9 +2153,13 @@ Connect to a network first
نقطة الاتصال الآمنة غير مدعومة بواسطة محول الشبكة.
-
- نقطة الاتصال الآمنة غير مدعومة لبروتوكول IKEv2/WireGuard ووضع الاتصال التلقائي.
+ نقطة الاتصال الآمنة غير مدعومة لبروتوكول IKEv2/WireGuard ووضع الاتصال التلقائي.
+
+
+
+
+
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
-
+
Žádné informace o síti
-
+
Nezabezpečený
-
+
Zabezpečený
-
+
Připojení k Windscribe bylo ukončeno.
-
+
převedeno do
-
+
Připojeno pro
-
+
převedený
-
+
Firewall
-
+
Blokuje veškerou konektivitu v případě náhlého odpojení
-
+
Připojit k sazbě
@@ -802,14 +802,14 @@
Nelze spustit updater (Chyba %1). Kontaktujte prosím podporu
-
+
Došlo ke ztrátě připojení k back-endovému procesu.
Uzdravování...
-
+
Vyberte aplikaci
@@ -989,18 +989,18 @@ Pokud problém přetrvává i po restartování, odešlete protokol ladění, ot
Preferences
-
-
+
+
Neplatná nastavení DNS
-
+
"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í).
-
+
"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
-
-
+
+
Povolit provoz v síti LAN
-
+
+
Ukončení zásuvek
-
+
+
+
+
+
+
+
Připojení
-
+
Výhradní
-
+
Zahrnující
-
+
Pryč
-
+
Možnosti sítě
-
+
Dělené tunelové propojení
-
+
Nastavení proxy serveru
-
+
Připojí se k naposledy použitému umístění, když se aplikace spustí nebo připojí k síti.
-
+
Automatické připojení
-
+
Ovládejte režim chování brány firewall Windscribe.
-
+
Režim připojení
-
+
Automaticky vyberte protokol VPN nebo jej vyberte ručně.
-
+
Automaticky určete jednotku MTU pro připojení nebo ručně přepište.
-
+
Vyberte server DNS při připojení k aplikaci Windscribe.
-
+
Povolte přístup k místním službám a tiskárnám při připojení k aplikaci Windscribe.
-
+
Falšování fyzické adresy (MAC adresy) zařízení.
-
+
Zavřete všechny aktivní sokety TCP při vytvoření tunelu VPN.
-
+
Nakonfigurujte televizor, herní konzoli nebo jiná zařízení, která podporují proxy servery.
-
-
+
+
+
+
+
+
+
Konflikt nastavení
-
+
Zakázání možnosti Povolit provoz LAN způsobí, že brána proxy přestane fungovat. Chcete zakázat proxy server?
-
+
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.
-
- 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í.
+
+
+
+
+
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
-
+
Keine Netzwerkinformationen
-
+
Ungesichert
-
+
Gesichert
-
+
Die Verbindung zu Windscribe wurde beendet.
-
+
übertragen in
-
+
Verbunden für
-
+
überführt
-
+
Firewall
-
+
Blockiert die gesamte Konnektivität im Falle einer plötzlichen Trennung
-
+
Verbinden Sie sich mit dem Tarif
@@ -832,14 +832,14 @@
Bitte wenden Sie sich an den Support
-
+
Die Verbindung zum Backend-Prozess wurde unterbrochen.
Genesend...
-
+
Wählen Sie eine Anwendung aus
@@ -989,18 +989,18 @@ Wenn das Problem nach einem Neustart weiterhin besteht, senden Sie bitte ein Deb
Preferences
-
-
+
+
Ungültige DNS-Einstellungen
-
+
'Verbundenes DNS' wurde nicht mit einem gültigen Upstream 1 (IP/DNS-over-HTTPS/TLS) konfiguriert. DNS wurde auf ROBERT zurückgesetzt (Standard).
-
+
'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
-
-
+
+
LAN-Datenverkehr zulassen
-
+
+
Sockets beenden
-
+
+
+
+
+
+
+
Verbindung
-
+
Ausschließlich
-
+
Inklusive
-
+
Aus
-
+
Netzwerk-Optionen
-
+
Geteiltes Tunneln
-
+
Proxy-Einstellungen
-
+
Stellt eine Verbindung mit dem zuletzt verwendeten Standort her, wenn die App gestartet wird oder einem Netzwerk beitritt.
-
+
Automatische Verbindung
-
+
Kontrollieren Sie den Modus des Verhaltens der Windscribe-Firewall.
-
+
Verbindungsmodus
-
+
Wählen Sie das VPN-Protokoll automatisch oder manuell aus.
-
+
Ermitteln Sie automatisch die MTU für Ihre Verbindung oder setzen Sie sie manuell außer Kraft.
-
+
Wählen Sie den DNS-Server aus, während Sie mit Windscribe verbunden sind.
-
+
Erlauben Sie den Zugriff auf lokale Dienste und Drucker, während Sie mit Windscribe verbunden sind.
-
+
Fälschen Sie die physische Adresse Ihres Geräts (MAC-Adresse).
-
+
Schließen Sie alle aktiven TCP-Sockets, wenn der VPN-Tunnel eingerichtet ist.
-
+
Konfigurieren Sie Ihren Fernseher, Ihre Spielekonsole oder andere Geräte, die Proxyserver unterstützen.
-
-
+
+
+
+
+
+
+
Einstellungskonflikt
-
+
Das Deaktivieren von LAN-Datenverkehr zulassen führt dazu, dass Ihr Proxy-Gateway nicht mehr funktioniert. Möchten Sie den Proxy deaktivieren?
-
+
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.
-
- 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.
+
+
+
+
+
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
-
+
Sin información de red
-
+
Mal fijado
-
+
Asegurado
-
+
La conexión a Windscribe ha finalizado.
-
+
transferido en
-
+
Conectado para
-
+
Transferido
-
+
Cortafuegos
-
+
Bloquea toda la conectividad en caso de una desconexión repentina
-
+
Conéctese a la tarifa
@@ -832,14 +832,14 @@
Póngase en contacto con el servicio de asistencia
-
+
Se perdió la conexión con el proceso de backend.
Recuperación...
-
+
Seleccione una aplicación
@@ -989,18 +989,18 @@ Si el problema persiste después de un reinicio, envíe un registro de depuraci
Preferences
-
-
+
+
Configuración de DNS no válida
-
+
'DNS conectado' no se configuró con un Upstream 1 válido (IP/DNS-over-HTTPS/TLS). DNS se revirtió a ROBERT (predeterminado).
-
+
'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
-
-
+
+
Permitir tráfico LAN
-
+
+
Terminar sockets
-
+
+
+
+
+
+
+
Conexión
-
+
Exclusivo
-
+
Inclusivo
-
+
Apagado
-
+
Opciones de red
-
+
Túnel dividido
-
+
Configuración de proxy
-
+
Se conecta a la última ubicación utilizada cuando la aplicación se inicia o se une a una red.
-
+
Conexión automática
-
+
Controle el modo de comportamiento del firewall de Windscribe.
-
+
Modo de conexión
-
+
Elija automáticamente el protocolo VPN o seleccione uno manualmente.
-
+
Determine automáticamente la MTU para su conexión o anule manualmente.
-
+
Seleccione el servidor DNS mientras está conectado a Windscribe.
-
+
Permita el acceso a servicios e impresoras locales mientras está conectado a Windscribe.
-
+
Suplantar la dirección física de su dispositivo (dirección MAC).
-
+
Cierre todos los sockets TCP activos cuando se establezca el túnel VPN.
-
+
Configure su televisor, consola de juegos u otros dispositivos que admitan servidores proxy.
-
-
+
+
+
+
+
+
+
Conflicto de configuración
-
+
Si deshabilita Permitir tráfico LAN, la puerta de enlace proxy dejará de funcionar. ¿Desea desactivar el proxy?
-
+
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.
-
- 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.
+
+
+
+
+
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
-
+
Aucune information réseau
-
+
Non sécurisé
-
+
Sécurisé
-
+
La connexion à Windscribe a été interrompue.
-
+
transféré en
-
+
Connecté pour
-
+
Transféré
-
+
Pare-feu
-
+
Bloque toute connectivité en cas de déconnexion soudaine
-
+
Se connecter pour évaluer
@@ -832,14 +832,14 @@
Veuillez contacter le support
-
+
Perte de connexion au processus principal.
Récupération...
-
+
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
-
-
+
+
Paramètres DNS non valides
-
+
'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' 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
-
-
+
+
Autoriser le trafic LAN
-
+
+
Terminaison des sockets
-
+
+
+
+
+
+
+
Connexion
-
+
Exclusif
-
+
Inclusif
-
+
De
-
+
Options réseau
-
+
Split Tunneling
-
+
Paramètres de proxy
-
+
Se connecte au dernier emplacement utilisé lorsque l’application se lance ou rejoint un réseau.
-
+
Connexion automatique
-
+
Contrôlez le mode de comportement du pare-feu Windscribe.
-
+
Mode de connexion
-
+
Choisissez automatiquement le protocole VPN ou sélectionnez-en un manuellement.
-
+
Déterminez automatiquement la MTU de votre connexion ou remplacez-la manuellement.
-
+
Sélectionnez le serveur DNS lorsque vous êtes connecté à Windscribe.
-
+
Autorisez l’accès aux services locaux et aux imprimantes lorsque vous êtes connecté à Windscribe.
-
+
Usurper l’adresse physique de votre appareil (adresse MAC).
-
+
Fermez tous les sockets TCP actifs lorsque le tunnel VPN est établi.
-
+
Configurez votre téléviseur, votre console de jeu ou d’autres appareils prenant en charge les serveurs proxy.
-
-
+
+
+
+
+
+
+
Conflit de paramètres
-
+
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 ?
-
+
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.
-
- 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.
+
+
+
+
+
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
-
+
कोई नेटवर्क जानकारी नहीं
-
+
असुरक्षित
-
+
सुरक्षित
-
+
विंडस्क्राइब से कनेक्शन समाप्त कर दिया गया है.
-
+
में स्थानांतरित
-
+
के लिए कनेक्ट डे
-
+
स्थानांतरित
-
+
फ़ायरवॉल
-
+
अचानक डिस्कनेक्ट होने की स्थिति में सभी कनेक्टिविटी ब्लॉक
-
+
दर से कनेक्ट करें
@@ -832,14 +832,14 @@
कृपया समर्थन से संपर्क करें
-
+
बैकएंड प्रक्रिया से कनेक्शन खो गया.
ठीक।।।
-
+
किसी अनुप्रयोग का चयन करें
@@ -989,18 +989,18 @@ If the problem persists after a restart, please send a debug log and open a supp
Preferences
-
-
+
+
अमान्य DNS सेटिंग्स
-
+
'कनेक्टेड DNS' को मान्य अपस्ट्रीम 1 (IP/DNS-over-HTTPS/TLS) के साथ कॉन्फ़िगर नहीं किया गया था. DNS को ROBERT (डिफ़ॉल्ट) में वापस कर दिया गया था।
-
+
'कनेक्टेड 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
-
-
+
+
LAN ट्रैफ़िक की अनुमति दें
-
+
+
सॉकेट समाप्त करें
-
+
+
+
+
+
+
+
नाता
-
+
निवारक
-
+
सम्मिलित
-
+
बंद
-
+
नेटवर्क विकल्प
-
+
स्प्लिट टनलिंग
-
+
प्रॉक्सी सेटिंग्स
-
+
ऐप लॉन्च होने या नेटवर्क में शामिल होने पर अंतिम उपयोग किए गए स्थान से कनेक्ट होता है।
-
+
ऑटो-कनेक्ट
-
+
विंडस्क्राइब फ़ायरवॉल के व्यवहार के तरीके को नियंत्रित करें।
-
+
कनेक्शन मोड
-
+
स्वचालित रूप से वीपीएन प्रोटोकॉल चुनें, या मैन्युअल रूप से एक का चयन करें।
-
+
स्वचालित रूप से अपने कनेक्शन के लिए MTU निर्धारित करें, या मैन्युअल रूप से ओवरराइड करें।
-
+
विंडस्क्राइब से कनेक्ट करते समय DNS सर्वर का चयन करें।
-
+
विंडस्क्राइब से कनेक्ट होने के दौरान स्थानीय सेवाओं और प्रिंटर तक पहुंच की अनुमति दें।
-
+
अपने डिवाइस के भौतिक पते (MAC पता) को स्पूफ करें।
-
+
वीपीएन सुरंग स्थापित होने पर सभी सक्रिय टीसीपी सॉकेट बंद करें।
-
+
अपने टीवी, गेमिंग कंसोल, या प्रॉक्सी सर्वर का समर्थन करने वाले अन्य डिवाइस कॉन्फ़िगर करें।
-
-
+
+
+
+
+
+
+
सेटिंग्स विरोध
-
+
LAN ट्रैफ़िक की अनुमति अक्षम करने से आपका प्रॉक्सी गेटवे काम करना बंद कर देगा। क्या आप प्रॉक्सी को अक्षम करना चाहते हैं?
-
+
लैन यातायात वर्तमान में विंडस्क्राइब फ़ायरवॉल द्वारा अवरुद्ध है। क्या आप इस सुविधा के काम करने के लिए LAN ट्रैफ़िक को फ़ायरवॉल को बायपास करने की अनुमति देना चाहते हैं?
@@ -2141,9 +2153,13 @@ Connect to a network first
सुरक्षित हॉटस्पॉट आपके नेटवर्क एडाप्टर द्वारा समर्थित नहीं है।
-
- सुरक्षित हॉटस्पॉट IKEv2/WireGuard प्रोटोकॉल और स्वचालित कनेक्शन मोड के लिए समर्थित नहीं है।
+ सुरक्षित हॉटस्पॉट IKEv2/WireGuard प्रोटोकॉल और स्वचालित कनेक्शन मोड के लिए समर्थित नहीं है।
+
+
+
+
+
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 @@
- Закрыть
+ Закр.
ConnectWindow::ConnectWindowItem
-
+
Нет информации о сети
-
+
Не защищена
-
+
Защищена
-
+
Соединение с Windscribe было прервано.
-
+
переведено в
-
+
Подключено
-
+
передано
-
+
Брандмауэр
-
+
Заблокирует все соединения в случае внезапного отключения VPN
-
+
Подключитесь, чтобы оценить сервер
@@ -1307,108 +1307,109 @@ If the problem persists after a restart, please send a debug log and open a supp
PreferencesWindow::ConnectionWindowItem
-
+
- Разрешить трафик локальной сети
+ Разрешить трафик LAN
+
Закрытие сокетов
-
-
+
+
Обход блокировок
-
+
Связь
-
+
Исключающий
-
+
Включающий
-
+
Выкл.
-
+
- Параметры сети
+ Параметры сетей
-
+
Раздельное туннелирование
-
+
Настройки прокси-сервера
-
+
Подключаться к последней используемой локации при запуске приложения или присоединении к сети.
-
+
Автоматическое подключение
-
+
Управление режимом поведения брандмауэра Windscribe.
-
+
Режим подключения
-
+
Выбор VPN-протокола автоматически или вручную
-
+
Автоматическое определение MTU для подключения или переопределение вручную.
-
+
Выберите DNS-сервер при подключении к Windscribe.
-
+
Разрешить доступ к локальным службам и принтерам при подключении к Windscribe.
-
+
Подделка физичесого адреса (MAC-адреса) устройства.
-
+
Закрытие всех активных TCP-соединений при установке VPN-туннеля.
-
+
Настройка телевизора, игровой консоли и других устройств, поддерживающих прокси-серверы.
@@ -1538,7 +1539,7 @@ If the problem persists after a restart, please send a debug log and open a supp
- Запуск при включении ОС
+ Запуск при вкл. ОС
@@ -1578,7 +1579,7 @@ If the problem persists after a restart, please send a debug log and open a supp
- Закреплённый
+ Закреплённый вид
@@ -1598,7 +1599,7 @@ If the problem persists after a restart, please send a debug log and open a supp
- Отображать нагрузку локаций
+ Нагрузка локаций
@@ -1618,7 +1619,7 @@ If the problem persists after a restart, please send a debug log and open a supp
- Отображение задержки
+ Вид задержки
@@ -1648,7 +1649,7 @@ If the problem persists after a restart, please send a debug log and open a supp
- Выбор получения стабильных, бета- или экспериментальных сборок.
+ Выбор получения стабильных, бета или экспериментальных сборок.
@@ -1840,7 +1841,7 @@ If the problem persists after a restart, please send a debug log and open a supp
- Автоматически безопасные сети
+ Автозащита сетей
@@ -2338,7 +2339,7 @@ If the reinstall does not help, please contact Windscribe support for assistance
- Включение или исключение приложений и имен узлов из VPN-туннеля.
+ Включение или исключение приложений и адресов/доменов из VPN-туннеля.
@@ -2461,17 +2462,17 @@ If the reinstall does not help, please contact Windscribe support for assistance
- География
+ Географически
- Алфавит
+ В алфавитном порядке
- Задержка
+ По задержке (пингу)
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
-
+
暂无网络信息
-
+
担保
-
+
担保
-
+
与Windscribe的连接已终止。
-
+
转入
-
+
已连接
-
+
转移
-
+
防火墙
-
+
在突然断开连接时阻止所有连接
-
+
连接费率
@@ -802,14 +802,14 @@
无法运行更新程序(错误 %1)。 请联系支持人员
-
+
与后端进程的连接丢失。
恢复。。。
-
+
选择一个应用程序
@@ -989,18 +989,18 @@ If the problem persists after a restart, please send a debug log and open a supp
Preferences
-
-
+
+
无效的 DNS 设置
-
+
“连接的 DNS”未配置有效的上游 1(IP/DNS-over-HTTPS/TLS)。DNS 已恢复为 ROBERT(默认)。
-
+
“连接的 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
-
-
+
+
允许局域网流量
-
+
+
终止套接字
-
+
+
+
+
+
+
+
连接
-
+
独家
-
+
包容
-
+
关闭
-
+
网络选项
-
+
拆分隧道
-
+
代理设置
-
+
在应用启动或加入网络时连接到上次使用的位置。
-
+
自动连接
-
+
控制 Windscribe 防火墙的行为模式。
-
+
连接模式
-
+
自动选择 VPN 协议,或手动选择一个。
-
+
自动确定连接的 MTU,或手动覆盖。
-
+
在连接到Windscribe时选择DNS服务器。
-
+
允许在连接到 Windscribe 时访问本地服务和打印机。
-
+
欺骗设备的物理地址(MAC 地址)。
-
+
建立 VPN 隧道后关闭所有活动的 TCP 套接字。
-
+
配置电视、游戏机或其他支持代理服务器的设备。
-
-
+
+
+
+
+
+
+
设置冲突
-
+
禁用允许 LAN 流量将导致代理网关停止工作。 是否要禁用代理?
-
+
LAN 流量目前被 Windscribe 防火墙阻止。 是否要允许 LAN 流量绕过防火墙以使此功能正常工作?
@@ -2141,9 +2153,13 @@ Connect to a network first
您的网络适配器不支持安全热点。
-
- IKEv2/WireGuard 协议和自动连接模式不支持安全热点。
+ IKEv2/WireGuard 协议和自动连接模式不支持安全热点。
+
+
+
+
+
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'