NetTunnelWindows/NetTunnelSDK/tunnel/tunnel.cpp

353 lines
13 KiB
C++
Raw Normal View History

2023-06-15 01:35:37 +00:00
#include "pch.h"
#include "tunnel.h"
#include <shlobj_core.h>
#include <strsafe.h>
#include <spdlog/sinks/wincolor_sink.h>
#include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/sinks/dup_filter_sink.h>
#include <spdlog/sinks/daily_file_sink.h>
#include <dbghelp.h>
2023-06-15 01:35:37 +00:00
#include "usrerr.h"
#include "globalcfg.h"
#include "misc.h"
#include "user.h"
#include <shlwapi.h>
#include <winsock2.h>
#pragma comment(lib, "Dbghelp.lib")
#define CONFIG_FILE_NAME TEXT("tunnelsdk.ini")
2023-06-15 01:35:37 +00:00
static SDK_CONFIG g_globalConfig;
PSDK_CONFIG GetGlobalCfgInfo() {
return &g_globalConfig;
}
static spdlog::level::level_enum logLevelToSpdlogLevel(LOG_LEVEL level) {
switch (level) {
case LOG_TRACE:
return spdlog::level::level_enum::trace;
case LOG_DEBUG:
return spdlog::level::level_enum::debug;
case LOG_INFO:
return spdlog::level::level_enum::info;
case LOG_WARN:
return spdlog::level::level_enum::warn;
case LOG_ERROR:
return spdlog::level::level_enum::err;
case LOG_CRITICAL:
return spdlog::level::level_enum::critical;
case LOG_OFF:
return spdlog::level::level_enum::off;
}
return spdlog::level::level_enum::info;
}
static void InitTunnelSDKLog(const TCHAR *pLogFile, LOG_LEVEL level) {
TCHAR buf[MAX_PATH] = {0};
TCHAR tmpPath[MAX_PATH];
2023-06-15 01:35:37 +00:00
if (pLogFile && strlen(pLogFile) > 0) {
if (PathIsRelative(pLogFile)) {
StringCbPrintf(buf, MAX_PATH, TEXT("%s\\%s"), g_globalConfig.workDirectory, pLogFile);
} else {
StringCbCopy(buf, MAX_PATH, pLogFile);
}
} else {
StringCbPrintf(buf, MAX_PATH, TEXT("%s\\tunnelsdklog.log"), g_globalConfig.workDirectory);
2023-06-15 01:35:37 +00:00
}
StringCbCopy(tmpPath, MAX_PATH, buf);
PathRemoveFileSpec(tmpPath);
MakeSureDirectoryPathExists(tmpPath);
g_globalConfig.enableLog = TRUE;
g_globalConfig.logLevel = logLevelToSpdlogLevel(level);
const auto dupFileFilter = std::make_shared<spdlog::sinks::dup_filter_sink_st>(std::chrono::seconds(5));
const auto dupStdFilter = std::make_shared<spdlog::sinks::dup_filter_sink_st>(std::chrono::seconds(5));
//std::make_shared<spdlog::sinks::rotating_file_sink_mt>(buf, 1024 * 1024 * 5, 10)->
dupFileFilter->add_sink(std::make_shared<spdlog::sinks::daily_file_sink_mt>(buf, 2, 30));
//dupFileFilter->add_sink(std::make_shared<spdlog::sinks::rotating_file_sink_mt>(buf, 1024 * 1024 * 5, 10));
dupStdFilter->add_sink(std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>());
std::vector<spdlog::sink_ptr> sinks {dupStdFilter, dupFileFilter};
auto logger = std::make_shared<spdlog::logger>(TEXT("tunnelSDK"), sinks.begin(), sinks.end());
spdlog::set_default_logger(logger);
spdlog::set_level(g_globalConfig.logLevel);
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l][%s:%#] %v");
spdlog::flush_every(std::chrono::seconds(1));
2023-06-15 01:35:37 +00:00
#if 0
std::cout << "TRACE: " << logger->should_log(spdlog::level::trace) << std::endl;
std::cout << "DEBUG: " << logger->should_log(spdlog::level::debug) << std::endl;
std::cout << "INFO: " << logger->should_log(spdlog::level::info) << std::endl;
std::cout << "WARN: " << logger->should_log(spdlog::level::warn) << std::endl;
std::cout << "ERROR: " << logger->should_log(spdlog::level::err) << std::endl;
std::cout << "CRITICAL: " << logger->should_log(spdlog::level::critical) << std::endl;
#endif
2023-06-15 06:16:52 +00:00
SPDLOG_INFO(TEXT("Log({1}): {0}"), buf, static_cast<int>(level));
2023-06-15 01:35:37 +00:00
}
int TunnelSDKInitEnv(const TCHAR *pWorkDir,
const TCHAR *pSvrUrl,
const TCHAR *pLogFile,
LOG_LEVEL level,
bool isWorkServer) {
int ret;
size_t length;
WSADATA WsaData;
CoInitialize(nullptr);
CoInitializeSecurity(nullptr,
-1,
nullptr,
nullptr,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
nullptr,
EOAC_NONE,
nullptr);
WSAStartup(MAKEWORD(2, 2), &WsaData);
memset(&g_globalConfig, 0, sizeof(SDK_CONFIG));
g_globalConfig.isWorkServer = isWorkServer;
g_globalConfig.scgProxy.scgGwPort = 0;
if (pWorkDir == nullptr) {
// 获取当前文件默认路径
GetModuleFileName(nullptr, g_globalConfig.workDirectory, MAX_PATH);
PathRemoveFileSpec(g_globalConfig.workDirectory);
} else {
if (StringCbLength(pWorkDir, MAX_PATH, &length) == S_OK && length == 0 || PathIsRelative(pWorkDir)) {
// 获取当前文件默认路径
GetModuleFileName(nullptr, g_globalConfig.workDirectory, MAX_PATH);
PathRemoveFileSpec(g_globalConfig.workDirectory);
} else {
MakeSureDirectoryPathExists(pWorkDir);
StringCbCopy(g_globalConfig.workDirectory, MAX_PATH, pWorkDir);
}
}
// 初始化日志
InitTunnelSDKLog(pLogFile, level);
// 创建配置文件存储目录
if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_NO_ALIAS, NULL, 0, g_globalConfig.configDirectory))) {
SPDLOG_ERROR(TEXT("Get Windows system directory error."));
return -ERR_SYS_CALL;
}
StringCbCat(g_globalConfig.configDirectory, MAX_PATH, "\\NetTunnel");
SPDLOG_DEBUG(TEXT("Configure directory: {0}."), g_globalConfig.configDirectory);
SPDLOG_DEBUG(TEXT("Platform Server: {}, Work Module: {}"), pSvrUrl, isWorkServer ? TEXT("SERVER") : TEXT("Client"));
// 如果配置目录不存在则自动创建
if (!PathFileExists(g_globalConfig.configDirectory)) {
if (!CreateDirectory(g_globalConfig.configDirectory, nullptr)) {
SPDLOG_ERROR(TEXT("Create configure directory '{0}' error."), g_globalConfig.configDirectory);
return -ERR_CREATE_FILE;
}
}
StringCbCopy(g_globalConfig.platformServerUrl, MAX_IP_LEN, pSvrUrl);
if (FAILED(SHGetFolderPath(NULL, CSIDL_WINDOWS | CSIDL_FLAG_NO_ALIAS, NULL, 0, g_globalConfig.systemDirectory))) {
SPDLOG_ERROR(TEXT("Get Windows system directory error."));
return -ERR_SYS_CALL;
}
StringCbPrintf(g_globalConfig.cfgPath, MAX_PATH, TEXT("%s\\%s"), g_globalConfig.workDirectory, CONFIG_FILE_NAME);
if ((ret = InitializeWireGuardLibrary()) == ERR_SUCCESS) {
return ret;
}
#if 0
if (FindWireguardExe(nullptr, 0) != ERR_SUCCESS) {
SPDLOG_ERROR(TEXT("WireGuard not found, Please install WireGuard first or set the WireGuard Path."));
return -ERR_ITEM_UNEXISTS;
}
#endif
return ERR_SUCCESS;
}
void TunnelSDKUnInit() {
RemoteWireGuardControl(false);
LocalWireGuardControl(false, false);
UnInitializeWireGuardLibrary();
CoFreeUnusedLibraries();
WSACleanup();
}
void DisableVerifySignature() {
memset(g_globalConfig.clientId, 0, MAX_PATH);
memset(g_globalConfig.clientSecret, 0, MAX_PATH);
}
int EnableVerifySignature(const TCHAR *pClientId, const TCHAR *pClientSecret) {
if (pClientId == nullptr || lstrlen(pClientId) == 0 || lstrlen(pClientId) >= MAX_PATH) {
SPDLOG_ERROR(TEXT("Input pClientId params error: {0}"), pClientId);
return -ERR_INPUT_PARAMS;
}
if (pClientSecret == nullptr || lstrlen(pClientSecret) == 0 || lstrlen(pClientSecret) >= MAX_PATH) {
SPDLOG_ERROR(TEXT("Input pClientSecret params error: {0}"), pClientSecret);
return -ERR_INPUT_PARAMS;
}
DisableVerifySignature();
StringCbCopy(g_globalConfig.clientId, MAX_PATH, pClientId);
StringCbCopy(g_globalConfig.clientSecret, MAX_PATH, pClientSecret);
return ERR_SUCCESS;
}
int EnableSCGProxy(bool isEnable, const TCHAR *pSCGIpAddr, int scgPort) {
SPDLOG_DEBUG(TEXT("SCG Proxy: {0}:{1} {2}"), pSCGIpAddr, scgPort, isEnable ? TEXT("TRUE") :TEXT("FALSE"));
if (pSCGIpAddr == nullptr || lstrlen(pSCGIpAddr) == 0 || lstrlen(pSCGIpAddr) >= MAX_IP_LEN) {
SPDLOG_ERROR(TEXT("Input pInterfaceName params error: {0}"), pSCGIpAddr);
return -ERR_INPUT_PARAMS;
}
memset(g_globalConfig.scgProxy.scgIpAddr, 0, MAX_IP_LEN);
if (isEnable) {
IP_INFO ipInfo;
int ret;
if ((ret = GetIpV4InfoFromHostname(AF_INET, pSCGIpAddr, &ipInfo)) != ERR_SUCCESS) {
return ret;
}
g_globalConfig.userCfg.cliConfig.scgCtrlAppId = WG_CTRL_SCG_ID;
g_globalConfig.userCfg.cliConfig.scgTunnelAppId = WG_TUNNEL_SCG_ID;
StringCbCopy(g_globalConfig.scgProxy.scgIpAddr, MAX_IP_LEN, ipInfo.hostip);
g_globalConfig.scgProxy.scgGwPort = static_cast<UINT16>(scgPort);
CreateUDPProxyServer();
} else {
StopUDPProxyServer();
g_globalConfig.scgProxy.scgGwPort = 0;
}
return ERR_SUCCESS;
}
bool UsedSCGProxy() {
return (g_globalConfig.scgProxy.scgGwPort > 0);
}
void TunnelLogEnable(bool enLog) {
if (enLog) {
spdlog::set_level(g_globalConfig.logLevel);
} else {
spdlog::set_level(spdlog::level::level_enum::off);
2023-06-15 06:16:52 +00:00
}
}
2023-06-15 01:35:37 +00:00
int SetProtocolEncryptType(const PROTO_CRYPTO_TYPE type, const TCHAR *pProKey) {
if (type > CRYPTO_BASE64 && type < CRYPTO_MAX) {
if (pProKey == nullptr || strlen(pProKey) < MIN_IP_LEN) {
2023-06-15 01:35:37 +00:00
return -ERR_INPUT_PARAMS;
}
}
g_globalConfig.proCryptoType = type;
StringCbCopy(g_globalConfig.proKeyBuf, 256, pProKey);
2023-06-15 01:35:37 +00:00
SPDLOG_DEBUG(TEXT("Protocol crypto type: {0} with key [{1}]"),
static_cast<int>(type),
pProKey ? pProKey : TEXT(""));
2023-06-15 01:35:37 +00:00
return ERR_SUCCESS;
}
//int CheckSystemMinDepend(CHECK_FUNCTION chkItem, TCHAR* pErrMsg, errMsg[MAX_PATH], );
int CheckSystemMinRequired(CHK_RESULT chkResult[CHK_MAX]) {
for (int i = 0; i < CHK_MAX; i++) {
const PCHK_RESULT pChk = &chkResult[i];
pChk->chk = static_cast<CHECK_FUNCTION>(i);
pChk->result = true;
memset(pChk->errMsg, 0, MAX_PATH);
switch (pChk->chk) {
case CHK_SYSTEM_INIT:
if (lstrlen(g_globalConfig.configDirectory) == 0) {
pChk->result = false;
StringCbCopy(pChk->errMsg,
MAX_PATH,
TEXT("错误: SDK 未初始化,请先调用 TunnelSDKInitEnv 接口执行初始化操作。"));
SPDLOG_ERROR(pChk->errMsg);
}
break;
case CHK_WIREGUARD_CONFIG: {
TCHAR cfgVal[MAX_PATH];
GetPrivateProfileString(CFG_WIREGUARD_SECTION,
CFG_WGCFG_PATH,
TEXT(""),
cfgVal,
MAX_PATH,
GetGlobalCfgInfo()->cfgPath);
if (!PathFileExists(cfgVal)) {
pChk->result = false;
StringCbCopy(pChk->errMsg,
MAX_PATH,
TEXT("错误: 未找到 WireGuard 配置文件,请先调用 WireGuardInstallServerService 或者 "
"WireGuardCreateClientConfig 接口创建合法的 WireGuard 配置文件。"));
SPDLOG_ERROR(pChk->errMsg);
}
} break;
case CHK_WIREGUARD_SERVICE: {
int ret;
bool bInstall;
ret = IsWireGuardServerInstalled(&bInstall);
if (ret != ERR_SUCCESS) {
pChk->result = false;
StringCbPrintf(pChk->errMsg,
MAX_PATH,
TEXT("错误: 获取系统 WireGuard 服务安装状态异常, 错误码:{0}。"),
ret);
SPDLOG_ERROR(pChk->errMsg);
}
if (!bInstall) {
pChk->result = false;
StringCbCopy(pChk->errMsg,
MAX_PATH,
TEXT("错误:系统 WireGuard 服务未安装,请调用 WireGuardInstallServerService 接口安装 "
"WireGuard 服务。"));
SPDLOG_ERROR(pChk->errMsg);
}
} break;
case CHK_WG_INTERFACE_PRIVATE:
if (!chkResult[CHK_WIREGUARD_SERVICE].chk) {
pChk->result = false;
StringCbCopy(pChk->errMsg,
MAX_PATH,
TEXT("错误:系统 WireGuard 服务未安装,请调用 WireGuardInstallServerService 接口安装 "
"WireGuard 服务。"));
SPDLOG_ERROR(pChk->errMsg);
}
break;
case CHK_MAX:
break;
}
}
2023-06-15 01:35:37 +00:00
return ERR_SUCCESS;
}