#include "pch.h" #include "tunnel.h" #include #include #include "globalcfg.h" #include "httplib.h" #include "misc.h" #include "network.h" #include "protocol.h" #include "usrerr.h" #include "user.h" #include static HANDLE g_ControlSvrThread = nullptr; static httplib::Server g_httpServer; static USER_SERVER_CONFIG g_UserSvrCfg; /** * @brief 连接到服务端控制服务 * @param pUserSvrUrl 服务端控制服务 URL 地址 */ void ConnectServerControlService(const TCHAR *pUserSvrUrl) { InitControlServer(pUserSvrUrl); } static void HttpResponseError(httplib::Response &pRes, int errCode, const TCHAR *pErrMessage) { ProtocolResponse rsp; std::string json; if (errCode != ERR_SUCCESS) { rsp.msgContent.errCode = errCode; } if (pErrMessage && lstrlen(pErrMessage) > 0) { rsp.msgContent.errMessage = pErrMessage; } else { if (errCode == ERR_SUCCESS) { rsp.msgContent.errMessage = TEXT("OK"); } } if (aigc::JsonHelper::ObjectToJson(rsp, json)) { pRes.set_content(json, TEXT("application/json")); } else { SPDLOG_ERROR(TEXT("ProtocolResponse to json error")); } } int CreateControlService(PUSER_SERVER_CONFIG pSvr) { static TCHAR g_CliNetwork[MAX_IP_LEN] = {}; static WGSERVER_CONFIG g_curCliConfig = {}; static std::mutex g_InterfaceMutex; DWORD dwStatus = 0; // HTTP 服务已经运行 if (g_httpServer.is_running()) { return ERR_SUCCESS; } // 线程已经运行 if (g_ControlSvrThread && GetExitCodeThread(g_ControlSvrThread, &dwStatus) && dwStatus == STILL_ACTIVE) { return -ERR_ITEM_EXISTS; } if (pSvr == nullptr) { SPDLOG_ERROR(TEXT("Input pSvr params error")); return -ERR_INPUT_PARAMS; } if (pSvr->svrListenPort <= 0 || pSvr->svrListenPort >= 65535) { SPDLOG_ERROR(TEXT("Input svrListenPort params error {0}"), pSvr->svrListenPort); return -ERR_INPUT_PARAMS; } if (lstrlen(pSvr->svrPrivateKey) != lstrlen(TEXT("4PPcnW3wYewNpoXjNoY3hQuCnzTNq/E9hhfU9/U6QmY="))) { SPDLOG_ERROR(TEXT("Input svrPrivateKey params length error {0}"), pSvr->svrPrivateKey); return -ERR_INPUT_PARAMS; } if (lstrlen(pSvr->svrAddress) == 0) { SPDLOG_ERROR(TEXT("Input svrAddress params error {0}"), pSvr->svrAddress); return -ERR_INPUT_PARAMS; } // 保存参数 memcpy(&g_UserSvrCfg, pSvr, sizeof(USER_SERVER_CONFIG)); g_httpServer.set_exception_handler([](const auto &req, auto &res, std::exception_ptr ep) { const auto fmt = TEXT("

Error 500

%s

"); char buf[BUFSIZ]; try { std::rethrow_exception(ep); } catch (std::exception &e) { StringCbPrintf(buf, BUFSIZ, fmt, e.what()); } catch (...) { // See the following NOTE StringCbPrintf(buf, BUFSIZ, fmt, TEXT("Unknown Exception")); } res.set_content(buf, TEXT("text/html")); res.status = 500; }); g_httpServer.set_error_handler([](const auto &req, auto &res) { const auto fmt = TEXT("

Error Status: %d

"); char buf[BUFSIZ]; StringCbPrintf(buf, BUFSIZ, fmt, res.status); res.set_content(buf, TEXT("text/html")); }); g_httpServer.Post(SET_CLIENTHEART_PATH, [](const httplib::Request &req, httplib::Response &res) { ProtocolResponse rsp; std::string json; rsp.msgContent.errCode = ERR_SUCCESS; rsp.msgContent.errMessage = TEXT("OK"); if (aigc::JsonHelper::ObjectToJson(rsp, json)) { res.set_content(json, TEXT("application/json")); } else { SPDLOG_ERROR(TEXT("ProtocolResponse to json error")); } }); g_httpServer.Post(SET_CLIENTSTART_TUNNEL, [](const httplib::Request &req, httplib::Response &res) { ProtocolRequest reqData; if (aigc::JsonHelper::JsonToObject(reqData, req.body)) { int ret; bool isSvrStart = false; g_InterfaceMutex.lock(); // Because of COM return CO_E_FIRST CoInitialize(nullptr); // 判断先前是否启动过服务 if ((ret = IsWireGuardServerRunning(GetGlobalCfgInfo()->userCfg.userName, &isSvrStart)) != ERR_SUCCESS) { // 返回获取系统服务错误,是否未安装 HttpResponseError(res, ret, TEXT("Not found WireGuard application in system")); SPDLOG_ERROR(TEXT("IsWireGuardServerInstalled error: {0}"), ret); g_InterfaceMutex.unlock(); return; } // 当前服务状态和需要执行的操作不同 if (isSvrStart != reqData.msgContent.isStart) { if (reqData.msgContent.isStart) { IP_INFO cliInfo; IP_INFO tunnelInfo; int retry = 3; // 启动服务 ret = WireGuardInstallDefaultServerService(true); if (ret != ERR_SUCCESS) { // 返回启动服务失败 SPDLOG_ERROR(TEXT("WireGuardInstallDefaultServerService error: {0}"), ret); HttpResponseError(res, ret, TEXT("Start WireGuard Tunnel Service error.")); g_InterfaceMutex.unlock(); return; } // 添加路由 if ((ret = GetIpV4InfoFromCIDR(g_CliNetwork, &cliInfo)) != ERR_SUCCESS) { // 返回启动服务失败 SPDLOG_ERROR(TEXT("GetIpV4InfoFromCIDR ({1}) error: {0}"), ret, g_CliNetwork); HttpResponseError(res, ret, TEXT("Parse IpAddress error.")); g_InterfaceMutex.unlock(); return; } if ((ret = GetIpV4InfoFromCIDR(g_UserSvrCfg.svrAddress, &tunnelInfo)) != ERR_SUCCESS) { // 返回启动服务失败 SPDLOG_ERROR(TEXT("GetIpV4InfoFromCIDR ({1}) error: {0}"), ret, g_UserSvrCfg.svrAddress); HttpResponseError(res, ret, TEXT("Parse tunnel ip address error.")); g_InterfaceMutex.unlock(); return; } do { ret = AddRouteTable(cliInfo.ip, cliInfo.netmask, tunnelInfo.ip); Sleep(1000); } while (ret != ERR_SUCCESS && retry--); if (ret != ERR_SUCCESS) { // 返回启动服务失败 SPDLOG_ERROR(TEXT("Add Route {1}/{2} gateway {3} error: {0}"), ret, cliInfo.ip, cliInfo.netmask, tunnelInfo.ip); HttpResponseError(res, ret, TEXT("Parse tunnel ip address error.")); g_InterfaceMutex.unlock(); return; } } else { if ((ret = WireGuardUnInstallServerService(GetGlobalCfgInfo()->userCfg.userName)) != ERR_SUCCESS) { // 返回停止服务失败 HttpResponseError(res, ret, TEXT("Stop pre running WireGuard service error")); SPDLOG_ERROR(TEXT("WireGuardUnInstallServerService error: {0}"), ret); g_InterfaceMutex.unlock(); return; } } } if (reqData.msgContent.isStart) { SPDLOG_INFO(TEXT("Tunnel Service Start Now ......: {0}"), GetGlobalCfgInfo()->userCfg.userName); } else { SPDLOG_INFO(TEXT("Tunnel Service Stoped: {0}"), GetGlobalCfgInfo()->userCfg.userName); } HttpResponseError(res, ERR_SUCCESS, nullptr); g_InterfaceMutex.unlock(); } }); g_httpServer.Post(SET_CLIENTCFG_PATH, [](const httplib::Request &req, httplib::Response &res) { ProtocolRequest reqData; if (aigc::JsonHelper::JsonToObject(reqData, req.body)) { int ret; bool isSvrStart = false; ProtocolResponse rsp; std::string json; g_InterfaceMutex.lock(); // Because of COM return CO_E_FIRST CoInitialize(nullptr); // 判断先前是否启动过服务 if ((ret = IsWireGuardServerRunning(GetGlobalCfgInfo()->userCfg.userName, &isSvrStart)) != ERR_SUCCESS) { // 返回获取系统服务错误,是否未安装 HttpResponseError(res, ret, TEXT("Not found WireGuard application in system")); SPDLOG_ERROR(TEXT("IsWireGuardServerInstalled error: {0}"), ret); g_InterfaceMutex.unlock(); return; } if (isSvrStart) { SPDLOG_DEBUG(TEXT("WireGuardUnInstallServerService: {0}"), GetGlobalCfgInfo()->userCfg.userName); if ((ret = WireGuardUnInstallServerService(GetGlobalCfgInfo()->userCfg.userName)) != ERR_SUCCESS) { // 返回停止服务失败 HttpResponseError(res, ret, TEXT("Stop pre running WireGuard service error")); SPDLOG_ERROR(TEXT("WireGuardUnInstallServerService error: {0}"), ret); g_InterfaceMutex.unlock(); return; } } memset(&g_curCliConfig, 0, sizeof(WGSERVER_CONFIG)); g_curCliConfig.ListenPort = g_UserSvrCfg.svrListenPort - 1; StringCbCopy(g_curCliConfig.Name, 64, GetGlobalCfgInfo()->userCfg.userName); StringCbCopy(g_curCliConfig.Address, 32, g_UserSvrCfg.svrAddress); StringCbCopy(g_curCliConfig.PrivateKey, 64, g_UserSvrCfg.svrPrivateKey); StringCbCopy(g_curCliConfig.CliPubKey, 64, reqData.msgContent.cliPublicKey.c_str()); StringCbCopy(g_CliNetwork, MAX_IP_LEN, reqData.msgContent.cliNetwork.c_str()); StringCbPrintf(g_curCliConfig.AllowNet, 256, TEXT("%s,%s"), reqData.msgContent.cliNetwork.c_str(), reqData.msgContent.cliTunnelAddr.c_str()); // 创建 WireGuard 配置文件 ret = WireGuardCreateServerConfig(&g_curCliConfig); if (ret != ERR_SUCCESS) { // 返回写入 WireGuard 配置文件错误 HttpResponseError(res, ret, TEXT("Create WireGuard service configure file error")); SPDLOG_ERROR(TEXT("WireGuardCreateServerConfig error: {0}"), ret); g_InterfaceMutex.unlock(); return; } // 返回当前隧道信息 rsp.msgContent.errCode = ERR_SUCCESS; rsp.msgContent.errMessage = TEXT("OK"); rsp.msgContent.svrNetwork = g_UserSvrCfg.svrAddress; if (aigc::JsonHelper::ObjectToJson(rsp, json)) { res.set_content(json, TEXT("application/json")); } else { SPDLOG_ERROR(TEXT("ProtocolResponse to json error")); HttpResponseError(res, ERR_JSON_CREATE, TEXT("ProtocolResponse to json error")); } g_InterfaceMutex.unlock(); } }); SPDLOG_DEBUG(TEXT("Start HTTP Service at {0}"), pSvr->svrListenPort); if (!g_httpServer.bind_to_port(TEXT("0.0.0.0"), pSvr->svrListenPort)) { SPDLOG_ERROR(TEXT("Start HTTP Service at {0} error"), pSvr->svrListenPort); return -ERR_SOCKET_BIND_PORT; } g_ControlSvrThread = CreateThread( nullptr, // Thread attributes 0, // Stack size (0 = use default) [](LPVOID lpParameter) { if (!g_httpServer.listen_after_bind()) { SPDLOG_ERROR(TEXT("Start HTTP Service at {0} error")); } SPDLOG_DEBUG(TEXT("Http service exit.....")); return static_cast(0); }, // Thread start address nullptr, // Parameter to pass to the thread 0, // Creation flags nullptr); // Thread id if (g_ControlSvrThread == nullptr) { // Thread creation failed. // More details can be retrieved by calling GetLastError() return -ERR_CREATE_THREAD; } g_httpServer.wait_until_ready(); return ERR_SUCCESS; } int StopControlService() { if (g_httpServer.is_running()) { g_httpServer.stop(); } if (g_ControlSvrThread) { // Wait for thread to finish execution if (WaitForSingleObject(g_ControlSvrThread, 10 * 1000) == WAIT_TIMEOUT) { SPDLOG_ERROR(TEXT("Waitting HTTP Service clost timeout")); return -ERROR_TIMEOUT; } CloseHandle(g_ControlSvrThread); g_ControlSvrThread = nullptr; } return ERR_SUCCESS; }