From 1a4c76d333aff61f5f578dfa08b16132144e5c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=98=95?= Date: Mon, 31 Jul 2023 14:07:11 +0800 Subject: [PATCH] =?UTF-8?q?OCT=201.=20=E7=A7=BB=E9=99=A4=20Wireguard=20Win?= =?UTF-8?q?dows=20=E7=A8=8B=E5=BA=8F=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- InstallTunnelSDK/InstallTunnelSDK.vdproj | 154 +++- NetTunnelApp/MainForm.cs | 13 +- NetTunnelApp/NetTunnelLib.cs | 8 +- NetTunnelSDK/ControlService.cpp | 6 + NetTunnelSDK/NetTunnelSDK.vcxproj | 3 + NetTunnelSDK/NetTunnelSDK.vcxproj.filters | 6 + NetTunnelSDK/ProxyService.cpp | 261 +------ NetTunnelSDK/UserManager.cpp | 9 +- NetTunnelSDK/WireguardService.cpp | 251 ++++++ NetTunnelSDK/common.h | 75 ++ NetTunnelSDK/dllmain.cpp | 14 +- NetTunnelSDK/globalcfg.h | 6 +- NetTunnelSDK/misc.h | 2 +- NetTunnelSDK/network.cpp | 46 ++ NetTunnelSDK/network.h | 14 +- NetTunnelSDK/tunnel.cpp | 38 +- NetTunnelSDK/tunnel.h | 168 ++-- NetTunnelSDK/usrerr.h | 9 +- NetTunnelSDK/wireguard.cpp | 68 +- NetTunnelSDKTestApp/NetNat.cpp | 145 ++++ NetTunnelSDKTestApp/NetTunnelSDKTestApp.cpp | 48 +- .../NetTunnelSDKTestApp.vcxproj | 2 + .../NetTunnelSDKTestApp.vcxproj.filters | 3 + NetTunnelSDKTestApp/WireGurad.cpp | 718 ++++++++++++++++++ NetTunnelSDKTestApp/common.h | 5 +- NetTunnelSDKTestApp/wireguard.h | 308 ++++++++ NetTunnelSvr/NetTunnelSvr.cpp | 120 +++ NetTunnelSvr/NetTunnelSvr.vcxproj | 138 ++++ NetTunnelSvr/NetTunnelSvr.vcxproj.filters | 22 + NetTunnelSvr/NetTunnelSvr.vcxproj.user | 4 + TestNetTunnelSDK/TestNetTunnelSDK.cpp | 16 +- tunnel_windows.sln | 27 + 32 files changed, 2240 insertions(+), 467 deletions(-) create mode 100644 NetTunnelSDK/WireguardService.cpp create mode 100644 NetTunnelSDK/common.h create mode 100644 NetTunnelSDKTestApp/NetNat.cpp create mode 100644 NetTunnelSDKTestApp/WireGurad.cpp create mode 100644 NetTunnelSDKTestApp/wireguard.h create mode 100644 NetTunnelSvr/NetTunnelSvr.cpp create mode 100644 NetTunnelSvr/NetTunnelSvr.vcxproj create mode 100644 NetTunnelSvr/NetTunnelSvr.vcxproj.filters create mode 100644 NetTunnelSvr/NetTunnelSvr.vcxproj.user diff --git a/InstallTunnelSDK/InstallTunnelSDK.vdproj b/InstallTunnelSDK/InstallTunnelSDK.vdproj index 947da65..91c4523 100644 --- a/InstallTunnelSDK/InstallTunnelSDK.vdproj +++ b/InstallTunnelSDK/InstallTunnelSDK.vdproj @@ -58,12 +58,6 @@ "Entry" { "MsmKey" = "8:_3853091F559CDFEDEBC0DE9767664FD8" - "OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_3853091F559CDFEDEBC0DE9767664FD8" "OwnerKey" = "8:_A2B46765ECF148F6B3BD76DC027D3B06" "MsmSig" = "8:_UNDEFINED" } @@ -82,12 +76,6 @@ "Entry" { "MsmKey" = "8:_4709F8F14ABE7B5983245A0461485A18" - "OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_4709F8F14ABE7B5983245A0461485A18" "OwnerKey" = "8:_A2B46765ECF148F6B3BD76DC027D3B06" "MsmSig" = "8:_UNDEFINED" } @@ -106,19 +94,13 @@ "Entry" { "MsmKey" = "8:_6A8B2CA20D527217332BB0170E559DB9" - "OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_6A8B2CA20D527217332BB0170E559DB9" "OwnerKey" = "8:_A2B46765ECF148F6B3BD76DC027D3B06" "MsmSig" = "8:_UNDEFINED" } "Entry" { - "MsmKey" = "8:_8A5EF688505390205390D3ABE7EC7364" - "OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5" + "MsmKey" = "8:_84BB8455EE8B1AB05AA45633B9D70FD7" + "OwnerKey" = "8:_A2B46765ECF148F6B3BD76DC027D3B06" "MsmSig" = "8:_UNDEFINED" } "Entry" @@ -171,6 +153,12 @@ } "Entry" { + "MsmKey" = "8:_CEE2F747DF77425F8F8416259F5A60C6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_CF70965F768635AE40F5A4648E193482" "OwnerKey" = "8:_451417C63FD78D938C6E04BB65EAA006" "MsmSig" = "8:_UNDEFINED" @@ -183,12 +171,30 @@ } "Entry" { + "MsmKey" = "8:_DC143071B1794733B7955D905E8F722D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_E128C35F6AE09A19D4BFECA45A1271B7" "OwnerKey" = "8:_10E071CF096B417C925C5E27E36CE39A" "MsmSig" = "8:_UNDEFINED" } "Entry" { + "MsmKey" = "8:_E68F9AF277DA30F367774B24D4F4A4B0" + "OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FAA1AF88F72C4C469E6B4CE67FCCB8CB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_UNDEFINED" "OwnerKey" = "8:_10E071CF096B417C925C5E27E36CE39A" "MsmSig" = "8:_UNDEFINED" @@ -286,6 +292,14 @@ "PrerequisitesLocation" = "2:1" "Url" = "8:" "ComponentsUrl" = "8:" + "Items" + { + "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2" + { + "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)" + "ProductCode" = "8:.NETFramework,Version=v4.7.2" + } + } } } } @@ -529,6 +543,26 @@ "IsDependency" = "11:TRUE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_84BB8455EE8B1AB05AA45633B9D70FD7" + { + "SourcePath" = "8:CRYPT32.dll" + "TargetName" = "8:CRYPT32.dll" + "Tag" = "8:" + "Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8A5EF688505390205390D3ABE7EC7364" { "SourcePath" = "8:MSVCP140D.dll" @@ -620,6 +654,26 @@ "IsDependency" = "11:TRUE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CEE2F747DF77425F8F8416259F5A60C6" + { + "SourcePath" = "8:..\\x64\\Debug\\NetTunnelSvr.exe" + "TargetName" = "8:NetTunnelSvr.exe" + "Tag" = "8:" + "Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_CF70965F768635AE40F5A4648E193482" { "AssemblyRegister" = "3:1" @@ -651,6 +705,26 @@ "IsDependency" = "11:TRUE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DC143071B1794733B7955D905E8F722D" + { + "SourcePath" = "8:..\\x64\\Debug\\wireguard.dll" + "TargetName" = "8:wireguard.dll" + "Tag" = "8:" + "Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_E128C35F6AE09A19D4BFECA45A1271B7" { "AssemblyRegister" = "3:1" @@ -682,6 +756,46 @@ "IsDependency" = "11:TRUE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E68F9AF277DA30F367774B24D4F4A4B0" + { + "SourcePath" = "8:WinDivert.dll" + "TargetName" = "8:WinDivert.dll" + "Tag" = "8:" + "Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FAA1AF88F72C4C469E6B4CE67FCCB8CB" + { + "SourcePath" = "8:..\\x64\\Debug\\tunnel.dll" + "TargetName" = "8:tunnel.dll" + "Tag" = "8:" + "Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } } "FileType" { diff --git a/NetTunnelApp/MainForm.cs b/NetTunnelApp/MainForm.cs index dd57ef0..b4a9a53 100644 --- a/NetTunnelApp/MainForm.cs +++ b/NetTunnelApp/MainForm.cs @@ -216,13 +216,14 @@ public partial class MainForm : Form private void menuSetVPNPath_Click(object sender, EventArgs e) { - DialogResult result = ofDlgWireGuard.ShowDialog(); + //DialogResult result = ofDlgWireGuard.ShowDialog(); - if (result == DialogResult.OK) - { - _wireguardPath = ofDlgWireGuard.FileName; - NetTunnelLib.SetWireguardPath(_wireguardPath); - } + //if (result == DialogResult.OK) + //{ + // _wireguardPath = ofDlgWireGuard.FileName; + // NetTunnelLib.SetWireguardPath(_wireguardPath); + //} + MessageBox.Show("Not Support"); } private void menuSetModeClient_Click(object sender, EventArgs e) diff --git a/NetTunnelApp/NetTunnelLib.cs b/NetTunnelApp/NetTunnelLib.cs index b38e355..1154d5b 100644 --- a/NetTunnelApp/NetTunnelLib.cs +++ b/NetTunnelApp/NetTunnelLib.cs @@ -181,13 +181,7 @@ public class NetTunnelLib [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int SetProtocolEncryptType(ProtoCryptoType type, String pProKey); - - [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int FindWireguardExe(StringBuilder lpString, int maxSize); - - [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int SetWireguardPath(String path); - + [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int GenerateWireguardKeyPairs(StringBuilder wgPubKey, int maxPubKey, StringBuilder wgPrivKey, int MaxPrivKey); diff --git a/NetTunnelSDK/ControlService.cpp b/NetTunnelSDK/ControlService.cpp index 12a8fc3..b97da6b 100644 --- a/NetTunnelSDK/ControlService.cpp +++ b/NetTunnelSDK/ControlService.cpp @@ -204,6 +204,12 @@ int CreateControlService(PUSER_SERVER_CONFIG pSvr) { } } + if (isSvrStart) { + 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(); } diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj b/NetTunnelSDK/NetTunnelSDK.vcxproj index 0461a18..c14b519 100644 --- a/NetTunnelSDK/NetTunnelSDK.vcxproj +++ b/NetTunnelSDK/NetTunnelSDK.vcxproj @@ -114,6 +114,7 @@ Use pch.h stdcpp17 + MultiThreadedDebug Windows @@ -149,6 +150,7 @@ + @@ -187,6 +189,7 @@ Use + diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters index 3487057..fa2a99a 100644 --- a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters +++ b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters @@ -81,6 +81,9 @@ 头文件 + + 头文件 + @@ -125,6 +128,9 @@ 源文件\network + + 源文件\wireguard + diff --git a/NetTunnelSDK/ProxyService.cpp b/NetTunnelSDK/ProxyService.cpp index 825c01d..0a0fab8 100644 --- a/NetTunnelSDK/ProxyService.cpp +++ b/NetTunnelSDK/ProxyService.cpp @@ -6,15 +6,8 @@ #include "globalcfg.h" #include "usrerr.h" -#include - #pragma comment(lib, "WinDivert.lib") -typedef enum { - PROXY_TCP = 1 << 0, - PROXY_UDP = 1 << 1, -} PROXY_PORTO_TYPE; - typedef struct { bool isRunning; HANDLE proxyThread; @@ -23,223 +16,21 @@ typedef struct { } UDP_PROXY_CTX, *PUDP_PROXY_CTX; typedef struct { - SOCKET proxySock; - SOCKET reservePortSock; - SOCKET altSock; - bool isRunning; - UINT16 proxyPort; - UINT16 altPort; - HANDLE proxyThread; - HANDLE proxyHandle; - bool isExitSvr; -} TCP_PROXY_CTX, *PTCP_PORXY_CTX; - -typedef struct { - int proType; TCHAR streamFilter[1024]; TCHAR targetIp[MAX_IP_LEN]; UINT16 targetPort; int vmId; int svrId; - TCP_PROXY_CTX tcpCtx; UDP_PROXY_CTX udpCtx; } PROXY_INFO, *PPROXY_INFO; -typedef struct { - SOCKET s; - PPROXY_INFO pCtx; - bool inbound; - in_addr dest; -} PROXY_CONNECTION_CONFIG, *PPROXY_CONNECTION_CONFIG; static std::unordered_map g_ProxyColleagues; -static int NewAvaliableSocket(SOCKET *pSock, UINT16 *pPort) { - const int reusedAddr = 1; - sockaddr_in proxySvrAddr {}; - sockaddr_in bindAddr {}; - int ret; - int addrSize = sizeof(sockaddr_in); - const SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) { - SPDLOG_ERROR(TEXT("Cretate TCP Socket error: {0}"), WSAGetLastError()); - return -ERR_SOCKET_BIND_PORT; - } - - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&reusedAddr), sizeof(int)) == - SOCKET_ERROR) { - SPDLOG_ERROR(TEXT("Failed to set socket optino SO_REUSEADDR ({0}})"), WSAGetLastError()); - closesocket(sock); - return -ERR_SOCKET_SET_OPT; - } - - proxySvrAddr.sin_family = AF_INET; - proxySvrAddr.sin_addr.s_addr = htonl(INADDR_ANY); - proxySvrAddr.sin_port = htons(0); - - if (bind(sock, reinterpret_cast(&proxySvrAddr), sizeof(proxySvrAddr)) == SOCKET_ERROR) { - SPDLOG_ERROR(TEXT("Failed to bind socket ({0})"), WSAGetLastError()); - closesocket(sock); - return -ERR_SOCKET_BIND; - } - - if (getsockname(sock, reinterpret_cast(&bindAddr), &addrSize) != 0) { - SPDLOG_ERROR(TEXT("Failed to get socket bind port ({0})"), WSAGetLastError()); - closesocket(sock); - return -ERR_SOCKET_GET_OPT; - } - - *pSock = sock; - *pPort = ntohs(bindAddr.sin_port); - - return ERR_SUCCESS; -} - -static DWORD proxyForwardCb(LPVOID lpParameter) { - return 0; -} - -static DWORD proxyConnCb(LPVOID lpParameter) { - const auto p = static_cast(lpParameter); - sockaddr_in altAddr {}; - SOCKET altSock; - HANDLE thread; - SOCKET connSock = p->s; - in_addr dest = p->dest; - PPROXY_INFO pInfo = p->pCtx; - PPROXY_CONNECTION_CONFIG pCfgProxySvr, pCfgAltSvr; - - HeapFree(GetProcessHeap(), 0, p); - - altSock = socket(AF_INET, SOCK_STREAM, 0); - - if (altSock == INVALID_SOCKET) { - SPDLOG_ERROR(TEXT("Cretate TCP Socket error: {0}"), WSAGetLastError()); - closesocket(connSock); - return 0; - } - - memset(&altAddr, 0, sizeof(altAddr)); - altAddr.sin_family = AF_INET; - altAddr.sin_port = htons(pInfo->tcpCtx.altPort); - altAddr.sin_addr = dest; - - if (connect(altSock, reinterpret_cast(&altAddr), sizeof(altAddr)) == SOCKET_ERROR) { - SPDLOG_ERROR(TEXT("Failed to connect socket ({0})"), WSAGetLastError()); - closesocket(connSock); - closesocket(altSock); - return 0; - } - - pInfo->tcpCtx.altSock = altSock; - - pCfgProxySvr = static_cast( - HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG))); - - if (pCfgProxySvr == nullptr) { - SPDLOG_ERROR(TEXT("Malloc {0} bytes error."), sizeof(PROXY_CONNECTION_CONFIG)); - closesocket(connSock); - closesocket(altSock); - return 0; - } - - pCfgAltSvr = static_cast(HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG))); - - if (pCfgAltSvr == nullptr) { - SPDLOG_ERROR(TEXT("Malloc {0} bytes error."), sizeof(PROXY_CONNECTION_CONFIG)); - closesocket(connSock); - closesocket(altSock); - free(pCfgProxySvr); - return 0; - } - - thread = CreateThread(nullptr, // Thread attributes - 0, // Stack size (0 = use default) - proxyForwardCb, // Thread start address - pCfgProxySvr, // Parameter to pass to the thread - 0, // Creation flags - nullptr); // Thread id - - if (thread == nullptr) { - SPDLOG_ERROR(TEXT("Failed to create thread ({0})"), GetLastError()); - closesocket(connSock); - closesocket(altSock); - free(pCfgProxySvr); - free(pCfgAltSvr); - return 0; - } - - return 0; -} - -static int StartTcpProxyService(PPROXY_INFO pInfo) { - pInfo->tcpCtx.isExitSvr = false; - - if (listen(pInfo->tcpCtx.proxySock, SOMAXCONN) == SOCKET_ERROR) { - SPDLOG_ERROR(TEXT("Failed to listen socket ({0})"), WSAGetLastError()); - closesocket(pInfo->tcpCtx.proxySock); - return -ERR_SOCKET_LISTEN; - } - - pInfo->tcpCtx.proxyThread = CreateThread( - nullptr, // Thread attributes - 0, // Stack size (0 = use default) - [](LPVOID lpParameter) { - const auto p = static_cast(lpParameter); - - while (!p->tcpCtx.isExitSvr) { - PPROXY_CONNECTION_CONFIG pCfg; - sockaddr_in connAddr {}; - int size = sizeof(connAddr); - - SOCKET s = accept(p->tcpCtx.proxySock, reinterpret_cast(&connAddr), &size); - - if (s == INVALID_SOCKET) { - continue; - } - - pCfg = static_cast( - HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG))); - - if (pCfg) { - HANDLE thread; - pCfg->s = s; - pCfg->dest = connAddr.sin_addr; - pCfg->pCtx = p; - - thread = CreateThread(nullptr, - 0, - proxyConnCb, // Thread start address - pCfg, // Parameter to pass to the thread - 0, - nullptr); - - if (thread == nullptr) { - closesocket(s); - HeapFree(GetProcessHeap(), 0, pCfg); - continue; - } - - CloseHandle(thread); - } - } - - return static_cast(0); - }, // Thread start address - pInfo, // Parameter to pass to the thread - 0, // Creation flags - nullptr); // Thread id - - if (pInfo->tcpCtx.proxyThread == nullptr) { - SPDLOG_ERROR(TEXT("Create TCP Listen Thread Error ({0})"), GetLastError()); - return -ERR_CREATE_THREAD; - } -} - -int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int vmId, int svrId) { +int CreatePorxyService(const TCHAR *pTargetIp, int targetPort, int vmId, int svrId) { //int CreatePorxyService() { - int ret; + //int ret; static HANDLE hDriver; PPROXY_INFO pInfo; std::string key; @@ -251,12 +42,11 @@ int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int if ((iter = g_ProxyColleagues.find(key)) != g_ProxyColleagues.end()) { pInfo = iter->second; // 如果配置完全相同则直接返回 - if (pInfo->vmId == vmId && pInfo->svrId == svrId && pInfo->proType == proType) { + if (pInfo->vmId == vmId && pInfo->svrId == svrId) { return ERR_SUCCESS; } else { pInfo->vmId = vmId; pInfo->svrId = svrId; - pInfo->proType = proType; } } else { // 创建新的代理配置 @@ -272,48 +62,7 @@ int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int memset(pInfo->streamFilter, 0, 1024); - // 重构过滤器 - if (pInfo->proType & PROXY_UDP) { - StringCbPrintf(pInfo->streamFilter, 1024, TEXT("(udp.DstPort == %d)"), targetPort); - //StringCbPrintf(pFilter, 1024, TEXT("tcp && remotePort == 9276")); - } - - if (pInfo->proType & PROXY_TCP) { - TCHAR tmpFilter[1024]; - - // 预先分配代理和转发 Socket - if ((ret = NewAvaliableSocket(&pInfo->tcpCtx.proxySock, &pInfo->tcpCtx.proxyPort)) != ERR_SUCCESS) { - return ret; - } - - if ((ret = NewAvaliableSocket(&pInfo->tcpCtx.reservePortSock, &pInfo->tcpCtx.altPort)) != ERR_SUCCESS) { - return ret; - } - - // 构建过滤器 - StringCbPrintf(tmpFilter, - 1024, - TEXT("(tcp.DstPort == %d or tcp.DstPort == %d or tcp.DstPort == %d or tcp.SrcPort == %d or " - "tcp.SrcPort == %d or tcp.SrcPort == %d)"), - targetPort, - pInfo->tcpCtx.proxyPort, - pInfo->tcpCtx.altPort, - targetPort, - pInfo->tcpCtx.proxyPort, - pInfo->tcpCtx.altPort); - - if (lstrlen(pInfo->streamFilter) > 0) { - StringCbCat(pInfo->streamFilter, 1024, TEXT(" or ")); - StringCbCat(pInfo->streamFilter, 1024, tmpFilter); - } else { - StringCbCopy(pInfo->streamFilter, 1024, tmpFilter); - } - } - - // 启动代理服务 - if ((ret = StartTcpProxyService(pInfo)) != ERR_SUCCESS) { - return ret; - } + StringCbPrintf(pInfo->streamFilter, 1024, TEXT("(udp.DstPort == %d and )"), targetPort); hDriver = WinDivertOpen(pInfo->streamFilter, WINDIVERT_LAYER_NETWORK, 0, 0); @@ -328,7 +77,7 @@ int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int 0, // Stack size (0 = use default) [](LPVOID lpParameter) { const HANDLE h = lpParameter; - unsigned char packet[0xFFFF]; + unsigned char packet[2048]; UINT packet_len; WINDIVERT_ADDRESS addr; diff --git a/NetTunnelSDK/UserManager.cpp b/NetTunnelSDK/UserManager.cpp index 3b14729..c8dd57d 100644 --- a/NetTunnelSDK/UserManager.cpp +++ b/NetTunnelSDK/UserManager.cpp @@ -423,12 +423,14 @@ int GetUserServerConfigure(const TCHAR *pUserName, const TCHAR *pToken, PUSER_SE if (pUserName && lstrlen(pUserName) > 0) { memset(pUser->userName, 0, MAX_PATH); StringCbCopy(pUser->userName, MAX_PATH, pUserName); + } else { + StringCbCopy(pUser->userName, MAX_PATH, TEXT("tunnel_svr")); } StringCbCopy(pUser->userToken, MAX_PATH, pToken); req.msgContent.token = pToken; - req.msgContent.user = pUserName; + req.msgContent.user = pUser->userName; ret = ProtolPostMessage(GET_SERVERCFG_PATH, &req, &rsp); @@ -453,6 +455,11 @@ int GetUserClientConfigure(const TCHAR *pUserName, const TCHAR *pToken, PUSER_CL ProtocolRequest req; ProtocolResponse rsp; + if (pUserName == nullptr || lstrlen(pUserName) == 0) { + SPDLOG_ERROR(TEXT("Input pUserName params error: {0}"), pUserName); + return -ERR_INPUT_PARAMS; + } + if (pToken == nullptr || lstrlen(pToken) == 0) { SPDLOG_ERROR(TEXT("Input pToken params error: {0}"), pToken); return -ERR_INPUT_PARAMS; diff --git a/NetTunnelSDK/WireguardService.cpp b/NetTunnelSDK/WireguardService.cpp new file mode 100644 index 0000000..5b7e085 --- /dev/null +++ b/NetTunnelSDK/WireguardService.cpp @@ -0,0 +1,251 @@ +#include "pch.h" +#include "usrerr.h" +#include "globalcfg.h" +#include "tunnel.h" + +#include +#include +#include + +int GetWireGuardServiceStatus(const TCHAR *pTunnelName, bool *pIsRunning) { + SC_HANDLE schSCManager; + SC_HANDLE schService; + TCHAR svrName[MAX_PATH]; + + if (pTunnelName == nullptr || lstrlen(pTunnelName) == 0) { + SPDLOG_ERROR(TEXT("Input pTunnelName error: {0}"), pTunnelName); + return -ERR_INPUT_PARAMS; + } + + if (pIsRunning == nullptr) { + SPDLOG_ERROR(TEXT("Input pIsRunning params error")); + return -ERR_INPUT_PARAMS; + } + + *pIsRunning = false; + + StringCbPrintf(svrName, MAX_PATH, TEXT("WireGuardTunnel$%s"), pTunnelName); + // Get a handle to the SCM database. + schSCManager = OpenSCManager(nullptr, // local computer + nullptr, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access rights + + if (nullptr == schSCManager) { + SPDLOG_ERROR(TEXT("OpenSCManager failed ({0})"), GetLastError()); + return -ERR_OPEN_SCM; + } + + // Get a handle to the service. + schService = OpenService(schSCManager, // SCM database + svrName, // name of service + SERVICE_ALL_ACCESS); // full access + + CloseServiceHandle(schService); + + // 如果服务不存在则直接返回 + if (schService != nullptr) { + *pIsRunning = true; + } + + return ERR_SUCCESS; +} + +int RemoveGuardService(const TCHAR *pTunnelName, bool bIsWaitStop) { + SC_HANDLE schSCManager; + SC_HANDLE schService; + TCHAR svrName[MAX_PATH]; + SERVICE_STATUS svrStatus; + + if (pTunnelName == nullptr || lstrlen(pTunnelName) == 0) { + SPDLOG_ERROR(TEXT("Input pTunnelName error: {0}"), pTunnelName); + return -ERR_INPUT_PARAMS; + } + + StringCbPrintf(svrName, MAX_PATH, TEXT("WireGuardTunnel$%s"), pTunnelName); + // Get a handle to the SCM database. + schSCManager = OpenSCManager(nullptr, // local computer + nullptr, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access rights + + if (nullptr == schSCManager) { + SPDLOG_ERROR(TEXT("OpenSCManager failed ({0})"), GetLastError()); + return -ERR_OPEN_SCM; + } + + // Get a handle to the service. + schService = OpenService(schSCManager, // SCM database + svrName, // name of service + SERVICE_ALL_ACCESS); // full access + + // 如果服务不存在则直接返回 + if (schService == nullptr) { + CloseServiceHandle(schSCManager); + return ERR_SUCCESS; + } + + if (ControlService(schService, SERVICE_CONTROL_STOP, &svrStatus) == 0) { + DWORD errCode = GetLastError(); + + if (errCode != ERROR_SERVICE_CANNOT_ACCEPT_CTRL && errCode != ERROR_SERVICE_NOT_ACTIVE) { + SPDLOG_ERROR(TEXT("Stop Service {1} failed ({0})"), errCode, svrName); + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return -ERR_STOP_SERVICE; + } + } + + for (int i = 0; bIsWaitStop && i < 10; i++) { + SERVICE_STATUS_PROCESS ssStatus; + DWORD dwBytesNeeded = 0; + + if (QueryServiceStatusEx(schService, // handle to service + SC_STATUS_PROCESS_INFO, // information level + reinterpret_cast(&ssStatus), // address of structure + sizeof(SERVICE_STATUS_PROCESS), // size of structure + &dwBytesNeeded)) // size needed if buffer is too small + { + // 服务已经停止 + if (ssStatus.dwCurrentState == SERVICE_STOPPED) { + break; + } + } + + //SPDLOG_ERROR(TEXT("Stop Service {1} retry times ({0})"), i + 1, svrName); + Sleep(1000); + } + + if (!DeleteService(schService) && GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE) { + SPDLOG_ERROR(TEXT("Delete Service {1} failed ({0})"), GetLastError(), svrName); + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return -ERR_DELETE_SERVICE; + } + + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return ERR_SUCCESS; +} + +int CreateWireGuardService(const TCHAR *pInterfaceName, const TCHAR *pWGConfigFilePath) { + //Service Name: "WireGuardTunnel$SomeTunnelName" + //Display Name: "Some Service Name" + //Service Type: SERVICE_WIN32_OWN_PROCESS + //Start Type: StartAutomatic + //Error Control: ErrorNormal, + //Dependencies: [ "Nsi", "TcpIp" ] + //Sid Type: SERVICE_SID_TYPE_UNRESTRICTED + //Executable: "C:\path\to\example\vpnclient.exe /service configfile.conf" + SC_HANDLE schSCManager; + SC_HANDLE schService; + TCHAR svrName[MAX_PATH]; + TCHAR displayName[MAX_PATH]; + TCHAR svrPath[MAX_PATH]; + TCHAR execParams[MAX_PATH * 2]; + + if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) { + SPDLOG_ERROR(TEXT("Input pInterfaceName error: {0}"), pInterfaceName); + return -ERR_INPUT_PARAMS; + } + + if (pWGConfigFilePath == nullptr || lstrlen(pWGConfigFilePath) == 0) { + SPDLOG_ERROR(TEXT("Input pGUID error: {0}"), pWGConfigFilePath); + return -ERR_INPUT_PARAMS; + } + + if (!PathFileExists(pWGConfigFilePath)) { + SPDLOG_ERROR(TEXT("WireGuard Configure File Not Exist: {0}"), pWGConfigFilePath); + return -ERR_ITEM_UNEXISTS; + } + + StringCbPrintf(svrName, MAX_PATH, TEXT("WireGuardTunnel$%s"), pInterfaceName); + StringCbPrintf(displayName, MAX_PATH, TEXT("WireGuard Tunnel Service %s"), pInterfaceName); + StringCbPrintf(svrPath, MAX_PATH, TEXT("%s\\NetTunnelSvr.exe"), GetGlobalCfgInfo()->workDirectory); + StringCbPrintf(execParams, MAX_PATH * 2, TEXT("\"%s\" /service \"%s\""), svrPath, pWGConfigFilePath); + //SPDLOG_DEBUG(TEXT("Params: {0}"), execParams); + + if (!PathFileExists(svrPath)) { + SPDLOG_ERROR(TEXT("WireGuard Service Not Exist: {0}"), svrPath); + return -ERR_ITEM_UNEXISTS; + } + + // Get a handle to the SCM database. + schSCManager = OpenSCManager(nullptr, // local computer + nullptr, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access rights + + if (nullptr == schSCManager) { + SPDLOG_ERROR(TEXT("OpenSCManager failed ({0})"), GetLastError()); + return -ERR_OPEN_SCM; + } + + // Get a handle to the service. + schService = OpenService(schSCManager, // SCM database + svrName, // name of service + SERVICE_ALL_ACCESS); // full access + // 如果服务已经存在则关闭 + if (schService != nullptr) { + int ret; + CloseServiceHandle(schSCManager); + CloseServiceHandle(schService); + ret = RemoveGuardService(pInterfaceName, true); + + if (ret != ERR_SUCCESS) { + return ret; + } + } + + schService = CreateService(schSCManager, + svrName, + displayName, + SC_MANAGER_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + execParams, + nullptr, + nullptr, + TEXT("Nsi\0TcpIp"), + nullptr, + nullptr); + + if (schService == nullptr) { + SPDLOG_ERROR(TEXT("Create Service {1} failed ({0})"), GetLastError(), svrName); + CloseServiceHandle(schSCManager); + return -ERR_CREATE_SERVICE; + } else { + SERVICE_SID_INFO info; + SERVICE_DESCRIPTIONA desc; + info.dwServiceSidType = SERVICE_SID_TYPE_UNRESTRICTED; + + if (!ChangeServiceConfig2(schService, SERVICE_CONFIG_SERVICE_SID_INFO, &info)) { + SPDLOG_ERROR(TEXT("Change Service {1} SERVICE_CONFIG_SERVICE_SID_INFO Configure failed ({0})"), + GetLastError(), + svrName); + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return -ERR_CONFIG_SERVICE; + } + + desc.lpDescription = TEXT(const_cast("SCC Tunnel Service over WireGuard")); + + if (!ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &desc)) { + SPDLOG_ERROR(TEXT("Change Service {1} SERVICE_CONFIG_DESCRIPTION Configure failed ({0})"), + GetLastError(), + svrName); + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return -ERR_CONFIG_SERVICE; + } + + if (!StartService(schService, 0, nullptr)) { + SPDLOG_ERROR(TEXT("Start Service {1} failed ({0})"), GetLastError(), svrName); + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return -ERR_START_SERVICE; + } + } + + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return ERR_SUCCESS; +} \ No newline at end of file diff --git a/NetTunnelSDK/common.h b/NetTunnelSDK/common.h new file mode 100644 index 0000000..11e48ef --- /dev/null +++ b/NetTunnelSDK/common.h @@ -0,0 +1,75 @@ +#pragma once + +/** + * @brief WireGuard key 最大长度 + */ +constexpr auto WG_KEY_MAX = (64); + +/** + * @brief 操作系统最大网卡数 + */ +#define NET_CARD_MAX (32) + +/** + * @brief IP 字符串最大长度(支持IPv6) + */ +#define MAX_IP_LEN (48) + +/** + * @brief IP 字符串最小长度 + */ +#define MIN_IP_LEN (7) + +/** + * @brief 网卡名称字符串最大长度(支持IPv6) + */ +#define MAX_NETCARD_NAME (64) + +/** + * @brief 协议加密类型 + * + */ +typedef enum { + CRYPTO_NONE = 0, ///< 不加密 + CRYPTO_BASE64 = 1, ///< BASE64 字符串编码 + CRYPTO_AES128 = 2, ///< AES 128位秘钥 加密 + CRYPTO_3DES = 3, ///< 3DES 加密 + CRYPTO_AES256 = 4, ///< AES 256 位秘钥加密 + CRYPTO_MAX, +} PROTO_CRYPTO_TYPE; + +/** + * @brief 日志等级 + * + */ +enum LOG_LEVEL { + LOG_TRACE = 0, ///< TRACE 日志等级 + LOG_DEBUG, ///< DEBUG 日志等级 + LOG_INFO, ///< INFO 日志等级 + LOG_WARN, ///< WARN 日志等级 + LOG_ERROR, ///< ERROR 日志等级 + LOG_CRITICAL, ///< CRITICAL 日志等级 + LOG_OFF ///< 关闭日志 +}; + +/** + * @brief Hash 算法类型 + * + */ +typedef enum { + HASH_MD2 = 0, ///< MD2 HASH 算法 + HASH_MD4, ///< MD4 HASH 算法 + HASH_MD5, ///< MD5 HASH 算法 + HASH_SHA1, ///< SHA1 HASH 算法 + HASH_SHA256, ///< SHA256 HASH 算法 + HASH_SHA384, ///< SHA384 HASH 算法 + HASH_SHA512 ///< SHA512 HASH 算法 +} HASH_TYPE; + +typedef enum { + CHK_SYSTEM_INIT, + CHK_WIREGUARD_CONFIG, + CHK_WIREGUARD_SERVICE, + CHK_WG_INTERFACE_PRIVATE, + CHK_MAX +} CHECK_FUNCTION; \ No newline at end of file diff --git a/NetTunnelSDK/dllmain.cpp b/NetTunnelSDK/dllmain.cpp index cdc86ee..5725abb 100644 --- a/NetTunnelSDK/dllmain.cpp +++ b/NetTunnelSDK/dllmain.cpp @@ -6,21 +6,9 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: - CoInitialize(nullptr); - CoInitializeSecurity(nullptr, - -1, - nullptr, - nullptr, - RPC_C_AUTHN_LEVEL_PKT, - RPC_C_IMP_LEVEL_IMPERSONATE, - nullptr, - EOAC_NONE, - nullptr); - break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - CoFreeUnusedLibraries(); + case DLL_PROCESS_DETACH: break; default: break; diff --git a/NetTunnelSDK/globalcfg.h b/NetTunnelSDK/globalcfg.h index 7f4fe1b..21258b1 100644 --- a/NetTunnelSDK/globalcfg.h +++ b/NetTunnelSDK/globalcfg.h @@ -1,7 +1,8 @@ #pragma once #include -#include "tunnel.h" +#include "common.h" +#if 0 /** * @brief WireGuard 配置项 */ @@ -11,6 +12,7 @@ typedef struct { TCHAR wgPath[MAX_PATH]; ///< wg.exe 路径 BOOL wgExists; ///< wg.exe 是否存在 } WIREGUARD_CFG, *PWIREGUARD_CFG; +#endif /** * @brief WireGuard 网络接口配置项 @@ -80,7 +82,7 @@ typedef struct { BOOL enableLog; ///< 是否启用日志 spdlog::level::level_enum logLevel; ///< 日志等级 TCHAR cfgPath[MAX_PATH]; ///< 配置文件路径 - WIREGUARD_CFG wireguardCfg; ///< wireguard 配置项 @see WIREGUARD_CFG + //WIREGUARD_CFG wireguardCfg; ///< wireguard 配置项 @see WIREGUARD_CFG WGINTERFACE_CFG wgServerCfg; ///< wireguard 服务端网络接口配置 WGINTERFACE_CFG wgClientCfg; ///< wireguard 客户端网络接口配置 USER_CONFIG userCfg; ///< 用户配置项 diff --git a/NetTunnelSDK/misc.h b/NetTunnelSDK/misc.h index 7e47ed9..d6cbea7 100644 --- a/NetTunnelSDK/misc.h +++ b/NetTunnelSDK/misc.h @@ -1,6 +1,6 @@ #pragma once -#include "tunnel.h" +#include "common.h" #include diff --git a/NetTunnelSDK/network.cpp b/NetTunnelSDK/network.cpp index 95747ca..1fc7b15 100644 --- a/NetTunnelSDK/network.cpp +++ b/NetTunnelSDK/network.cpp @@ -1241,6 +1241,52 @@ int RemoveNATRule(const TCHAR *pInterfaceName) { return ERR_SUCCESS; } +int SetInterfaceIpAddress(const TCHAR *pInterfaceName, const TCHAR *pIpaddr, const TCHAR *pNetmask) { + int ret; + TCHAR cmdBuf[MAX_PATH]; + //int cidr; + DWORD retCode; + IP_INFO ipInfo {}; + + if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) { + SPDLOG_ERROR("Input pInterfaceName params error: {0}", pInterfaceName); + return -ERR_INPUT_PARAMS; + } + + if (pIpaddr == nullptr || lstrlen(pIpaddr) == 0) { + SPDLOG_ERROR("Input pIpaddr params error: {0}", pIpaddr); + return -ERR_INPUT_PARAMS; + } + + if (pNetmask == nullptr || lstrlen(pNetmask) == 0) { + SPDLOG_WARN("Input pNetmask params error: {0}", pNetmask); + return -ERR_INPUT_PARAMS; + } + + GetIpV4InfoFromNetmask(pIpaddr, pNetmask, &ipInfo); + //cidr = NetmaskToCIDR(pNetmask); + + if (FAILED(StringCbPrintf( + cmdBuf, + MAX_PATH, + "PowerShell -Command \"& {New-NetIPAddress -InterfaceAlias %s -AddressFamily IPv4 -IPAddress %s -PrefixLength %d}\"", + pInterfaceName, + pIpaddr, + ipInfo.prefix))) { + SPDLOG_ERROR("Format String Error"); + return -ERR_MEMORY_STR; + } + + if ((ret = RunCommand(cmdBuf, nullptr, 0, &retCode)) != ERR_SUCCESS) { + SPDLOG_ERROR("Run command [{0}] error: {1}", cmdBuf, ret); + return -ERR_CALL_SHELL; + } + + SPDLOG_DEBUG("Run Set IP Command({1}): {0}", cmdBuf, retCode); + + return ERR_SUCCESS; +} + #if 0 int GetWindowsHyperVStatus(int *pEnabled) { int ret; diff --git a/NetTunnelSDK/network.h b/NetTunnelSDK/network.h index 7fb5505..e500875 100644 --- a/NetTunnelSDK/network.h +++ b/NetTunnelSDK/network.h @@ -234,7 +234,19 @@ TUNNEL_API int __cdecl SetNATRule(const TCHAR *pInterfaceName, const TCHAR *pCid */ TUNNEL_API int __cdecl RemoveNATRule(const TCHAR *pInterfaceName); - +/** + * @brief 设置网络接口IP地址 + * @param[in] pInterfaceName 网卡名称 + * @param[in] pIpaddr IP 地址 + * @param[in] pNetmask 子网掩码 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_MALLOC_MEMORY 分配内存失败 + * - -ERR_MEMORY_STR 字符串处理 + * - -ERR_CALL_SHELL 调用系统命令行失败 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl SetInterfaceIpAddress(const TCHAR *pInterfaceName, const TCHAR *pIpaddr, const TCHAR *pNetmask); TUNNEL_API int __cdecl CreatePorxyService(); #if 0 /** diff --git a/NetTunnelSDK/tunnel.cpp b/NetTunnelSDK/tunnel.cpp index 4dda544..c828649 100644 --- a/NetTunnelSDK/tunnel.cpp +++ b/NetTunnelSDK/tunnel.cpp @@ -95,7 +95,18 @@ int TunnelSDKInitEnv(const TCHAR *pWorkDir, LOG_LEVEL level, bool isWorkServer) { size_t length; - + + CoInitialize(nullptr); + CoInitializeSecurity(nullptr, + -1, + nullptr, + nullptr, + RPC_C_AUTHN_LEVEL_PKT, + RPC_C_IMP_LEVEL_IMPERSONATE, + nullptr, + EOAC_NONE, + nullptr); + memset(&g_globalConfig, 0, sizeof(SDK_CONFIG)); g_globalConfig.isWorkServer = isWorkServer; @@ -145,10 +156,12 @@ int TunnelSDKInitEnv(const TCHAR *pWorkDir, StringCbPrintf(g_globalConfig.cfgPath, MAX_PATH, TEXT("%s\\%s"), g_globalConfig.workDirectory, CONFIG_FILE_NAME); +#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_EXISTS; + return -ERR_ITEM_UNEXISTS; } +#endif return ERR_SUCCESS; } @@ -156,6 +169,7 @@ int TunnelSDKInitEnv(const TCHAR *pWorkDir, void TunnelSDKUnInit() { RemoteWireGuardControl(false); LocalWireGuardControl(false, false); + CoFreeUnusedLibraries(); } void EnableSCGProxy(bool isEnable) { @@ -210,26 +224,6 @@ int CheckSystemMinRequired(CHK_RESULT chkResult[CHK_MAX]) { SPDLOG_ERROR(pChk->errMsg); } break; - case CHK_WIREGUARD_INSTALL: - if (!g_globalConfig.wireguardCfg.wireguardExists) { - pChk->result = false; - StringCbCopy( - pChk->errMsg, - MAX_PATH, - TEXT("错误: 系统未检测到 wireguard.exe 程序,请先下载并安装 WireGuard 最新版本,或者调用 " - "SetWireguardPath 接口设置 WireGuard 程序路径。")); - SPDLOG_ERROR(pChk->errMsg); - } - break; - case CHK_WG_INSTALL: - if (!g_globalConfig.wireguardCfg.wgExists) { - pChk->result = false; - StringCbCopy(pChk->errMsg, - MAX_PATH, - TEXT("错误: 系统未检测到 wg.exe 程序,请重新安装 WireGuard 或者修复 wg.exe 程序。")); - SPDLOG_ERROR(pChk->errMsg); - } - break; case CHK_WIREGUARD_CONFIG: { TCHAR cfgVal[MAX_PATH]; GetPrivateProfileString(CFG_WIREGUARD_SECTION, diff --git a/NetTunnelSDK/tunnel.h b/NetTunnelSDK/tunnel.h index 026927d..906c9bd 100644 --- a/NetTunnelSDK/tunnel.h +++ b/NetTunnelSDK/tunnel.h @@ -1,5 +1,6 @@ #pragma once +#include "common.h" #include #ifdef NETTUNNELSDK_EXPORTS @@ -8,82 +9,6 @@ #define TUNNEL_API __declspec(dllimport) #endif -/** - * @brief WireGuard key 最大长度 - */ -constexpr auto WG_KEY_MAX = (64); - -/** - * @brief 操作系统最大网卡数 - */ -#define NET_CARD_MAX (32) - -/** - * @brief IP 字符串最大长度(支持IPv6) - */ -#define MAX_IP_LEN (48) - -/** - * @brief IP 字符串最小长度 - */ -#define MIN_IP_LEN (7) - -/** - * @brief 网卡名称字符串最大长度(支持IPv6) - */ -#define MAX_NETCARD_NAME (64) - -/** - * @brief 协议加密类型 - * - */ -typedef enum { - CRYPTO_NONE = 0, ///< 不加密 - CRYPTO_BASE64 = 1, ///< BASE64 字符串编码 - CRYPTO_AES128 = 2, ///< AES 128位秘钥 加密 - CRYPTO_3DES = 3, ///< 3DES 加密 - CRYPTO_AES256 = 4, ///< AES 256 位秘钥加密 - CRYPTO_MAX, -} PROTO_CRYPTO_TYPE; - -/** - * @brief 日志等级 - * - */ -enum LOG_LEVEL { - LOG_TRACE = 0, ///< TRACE 日志等级 - LOG_DEBUG, ///< DEBUG 日志等级 - LOG_INFO, ///< INFO 日志等级 - LOG_WARN, ///< WARN 日志等级 - LOG_ERROR, ///< ERROR 日志等级 - LOG_CRITICAL, ///< CRITICAL 日志等级 - LOG_OFF ///< 关闭日志 -}; - -/** - * @brief Hash 算法类型 - * - */ -typedef enum { - HASH_MD2 = 0, ///< MD2 HASH 算法 - HASH_MD4, ///< MD4 HASH 算法 - HASH_MD5, ///< MD5 HASH 算法 - HASH_SHA1, ///< SHA1 HASH 算法 - HASH_SHA256, ///< SHA256 HASH 算法 - HASH_SHA384, ///< SHA384 HASH 算法 - HASH_SHA512 ///< SHA512 HASH 算法 -} HASH_TYPE; - -typedef enum { - CHK_SYSTEM_INIT, - CHK_WIREGUARD_INSTALL, - CHK_WG_INSTALL, - CHK_WIREGUARD_CONFIG, - CHK_WIREGUARD_SERVICE, - CHK_WG_INTERFACE_PRIVATE, - CHK_MAX -} CHECK_FUNCTION; - /** * @brief 网络共享模式 * @@ -156,7 +81,8 @@ TUNNEL_API void __cdecl SetCurrentNetShareMode(NET_SHARE_MODE shareMode); * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO * - -ERR_ITEM_EXISTS 未找到 WireGuard 程序 * - -ERR_SYS_CALL 获取配置本地配置文件存储目录失败 - * - -ERR_CREATE_FILE 创建用户配置文件目录失败 + * - -ERR_CREATE_FILE 创建用户配置文件目录失败 + * - -ERR_ITEM_UNEXISTS WireGuard 未安装 * - ERR_SUCCESS 成功 */ TUNNEL_API int __cdecl TunnelSDKInitEnv(const TCHAR *pWorkDir, @@ -183,28 +109,6 @@ TUNNEL_API int __cdecl SetProtocolEncryptType(const PROTO_CRYPTO_TYPE type, cons */ TUNNEL_API void __cdecl TunnelLogEnable(bool enLog); -/** - * @brief 查找 WireGuard 运行环境 - * @param[out] pFullPath wireguard.exe 程序路径 - * @param[in] maxSize pFullPath 缓冲区最大字节数 - * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO - * - -ERR_INPUT_PARAMS 输入参数错误 - * - -ERR_MALLOC_MEMORY 分配内存失败 - * - -ERR_FILE_NOT_EXISTS 文件不存在 - * - ERR_SUCCESS 成功 - */ -TUNNEL_API int __cdecl FindWireguardExe(TCHAR *pFullPath, int maxSize); - -/** - * @brief 设置 wireguard.exe 程序路径 - * @param[in] pPath wireguard.exe 程序路径 - * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO - * - -ERR_INPUT_PARAMS 输入参数错误 - * - -ERR_ITEM_UNEXISTS 文件不存在 - * - ERR_SUCCESS 成功 - */ -TUNNEL_API int __cdecl SetWireguardPath(const TCHAR *pPath); - /** * @brief 创建 WireGuard 密钥对 * @param[out] pPubKey 公钥缓冲区 @@ -242,6 +146,49 @@ TUNNEL_API int __cdecl WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgCon */ TUNNEL_API int __cdecl WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig); +/** + * @brief 通过 WireGuard 配置文件安装隧道服务 + * @param pInterfaceName 隧道服务名 + * @param pWGConfigFilePath 配置文件完整路径 + * @return 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_ITEM_UNEXISTS 找不掉对应的服务 + * - -ERR_OPEN_SCM 打开服务管理器设备失败 + * - -ERR_OPEN_SERVICE 打开服务失败 + * - -ERR_CREATE_SERVICE 创建服务失败 + * - -ERR_CONFIG_SERVICE 配置服务失败 + * - -ERR_START_SERVICE 停止服务失败 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl CreateWireGuardService(const TCHAR *pInterfaceName, const TCHAR *pWGConfigFilePath); + +/** + * @brief 获取当前 WireGuard 服务隧道是否正则运行 + * @param pTunnelName 隧道服务名 + * @param pIsRunning pIsRunning WireGuard 服务隧道运行状态 + * - TRUE 已经安装 + * - FALSE 未安装 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_OPEN_SCM 打开服务管理器设备失败 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl GetWireGuardServiceStatus(const TCHAR *pTunnelName, bool *pIsRunning); + +/** + * @brief 移除 WireGuard 隧道服务 + * @param pTunnelName 隧道服务名 + * @param bIsWaitStop 是否等待隧道服务结束 TRUE: 等待服务结束, FALSE: 不等待直接结束 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_OPEN_SCM 打开服务管理器设备失败 + * - -ERR_OPEN_SERVICE 打开服务失败 + * - -ERR_STOP_SERVICE 停止服务失败 + * - -ERR_DELETE_SERVICE 删除服务失败 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl RemoveGuardService(const TCHAR *pTunnelName, bool bIsWaitStop); + /** * @brief 安装/卸载 WireGuard 服务 * @param[in] bInstall TRUE 安装服务, FALSE 卸载服务 @@ -362,6 +309,29 @@ TUNNEL_API int __cdecl CalcFileHash(const HASH_TYPE type, const TCHAR *pPath, TC */ TUNNEL_API int __cdecl InstallWindowsNATCommand(); TUNNEL_API int __cdecl WireGuardNetConnectionSharingEnable(); + + +/** + * @brief 查找 WireGuard 运行环境 + * @param[out] pFullPath wireguard.exe 程序路径 + * @param[in] maxSize pFullPath 缓冲区最大字节数 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_MALLOC_MEMORY 分配内存失败 + * - -ERR_FILE_NOT_EXISTS 文件不存在 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl FindWireguardExe(TCHAR *pFullPath, int maxSize); + +/** + * @brief 设置 wireguard.exe 程序路径 + * @param[in] pPath wireguard.exe 程序路径 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_ITEM_UNEXISTS 文件不存在 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl SetWireguardPath(const TCHAR *pPath); #endif #ifdef __cplusplus } diff --git a/NetTunnelSDK/usrerr.h b/NetTunnelSDK/usrerr.h index 72afd3f..937ec33 100644 --- a/NetTunnelSDK/usrerr.h +++ b/NetTunnelSDK/usrerr.h @@ -23,8 +23,13 @@ enum USER_ERRNO { ERR_GET_FILE_SIZE, ///< 获取文件大小失败 ERR_FIND_FILE, ///< 查找文件失败 ERR_COPY_FILE, ///< 复制文件失败 - ERR_OPEN_SCM, ///< 打开服务管理器设备 + ERR_OPEN_SCM, ///< 打开服务管理器设备失败 ERR_OPEN_SERVICE, ///< 打开服务失败 + ERR_CREATE_SERVICE, ///< 创建服务失败 + ERR_START_SERVICE, ///< 启动服务失败 + ERR_STOP_SERVICE, ///< 停止服务失败 + ERR_DELETE_SERVICE, ///< 删除服务失败 + ERR_CONFIG_SERVICE, ///< 修改服务配置失败 ERR_GET_SERVICESSTATUS, ///< 获取服务状态失败 ERR_MALLOC_MEMORY, ///< 分配内存失败 ERR_MMAP_MEMORY, ///< 共享内存失败 @@ -46,7 +51,7 @@ enum USER_ERRNO { ERR_BCRYPT_CREATEHASH, ///< 创建 Hash 算法失败 ERR_BCRYPT_HASHDATA, ///< 计算 Hash 数据失败 ERR_BCRYPT_FINISHHASH, ///< 计算 Hash 结果失败 - ERR_NET_UNCONNECT = 200, ///< 网络未连接 + ERR_NET_UNCONNECT = 200, ///< 网络未连接 ERR_NET_CATEGORY_MODE, ///< 网络工作模式 ERR_NET_INTELNEL_ICS, ///< 共享 Intelnet 网络 ICS 共享失败 ERR_NET_WIREGUARD_ICS, ///< 共享 WireGuard 网络 ICS 共享失败 diff --git a/NetTunnelSDK/wireguard.cpp b/NetTunnelSDK/wireguard.cpp index 0ff4abe..cfbbd7f 100644 --- a/NetTunnelSDK/wireguard.cpp +++ b/NetTunnelSDK/wireguard.cpp @@ -9,15 +9,13 @@ #include "misc.h" #include "network.h" +#define USED_EMBEDDED_WG (1) + #pragma comment(lib, "Shlwapi.lib") #pragma comment(lib, "Winmm.lib") -#define WG_NIC_DISCRIPT TEXT("WireGuard Tunnel") - static NET_SHARE_MODE g_CurShareMode = ICS_SHARE_MODE; -constexpr auto WINENVBUF_SIZE = (4096); - NET_SHARE_MODE GetCurrentNetShareMode() { return g_CurShareMode; } @@ -39,8 +37,7 @@ int GetWireGuardWorkMode(bool *pIsWorkServer) { int WireGuardInstallDefaultServerService(bool bInstall) { TCHAR cfgVal[MAX_PATH]; - DWORD retCode; - + GetPrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WGCFG_PATH, TEXT(""), @@ -50,14 +47,20 @@ int WireGuardInstallDefaultServerService(bool bInstall) { if (lstrlen(cfgVal) > 0) { if (PathFileExists(cfgVal)) { - TCHAR cmdBuf[MAX_PATH]; - TCHAR svrName[MAX_PATH]; int ret; + TCHAR svrName[MAX_PATH]; StringCbCopy(svrName, MAX_PATH, cfgVal); PathStripPath(svrName); PathRemoveExtension(svrName); +#if USED_EMBEDDED_WG + if (bInstall) { + ret = WireGuardInstallServerService(cfgVal); //CreateWireGuardService(svrName, cfgVal); + } else { + ret = RemoveGuardService(svrName, true); + } +#else if (bInstall) { // 安装服务 StringCbPrintf(cmdBuf, @@ -81,8 +84,9 @@ int WireGuardInstallDefaultServerService(bool bInstall) { } SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf); +#endif - if (bInstall) { + if (bInstall && ret == ERR_SUCCESS) { int retry = 10; do { ret = WaitNetAdapterConnected(svrName, 1000); @@ -102,9 +106,12 @@ int WireGuardInstallDefaultServerService(bool bInstall) { int WireGuardInstallServerService(const TCHAR *pTunnelCfgPath) { // 卸载服务 - TCHAR cmdBuf[MAX_PATH]; + TCHAR svrName[MAX_PATH]; int ret; - DWORD retCode; + + StringCbCopy(svrName, MAX_PATH, pTunnelCfgPath); + PathStripPath(svrName); + PathRemoveExtension(svrName); if (pTunnelCfgPath == nullptr || lstrlen(pTunnelCfgPath) == 0) { SPDLOG_ERROR(TEXT("Input pTunnelCfgPath params error")); @@ -115,6 +122,13 @@ int WireGuardInstallServerService(const TCHAR *pTunnelCfgPath) { return -ERR_ITEM_UNEXISTS; } + if ((ret = CreateWireGuardService(svrName, pTunnelCfgPath)) != ERR_SUCCESS) { + SPDLOG_ERROR(TEXT("Create WireGuard Service Error({0}): {1}, {2} "), ret, svrName, pTunnelCfgPath); + return ret; + } + +#if 0 + // 安装服务 StringCbPrintf(cmdBuf, MAX_PATH, @@ -128,26 +142,31 @@ int WireGuardInstallServerService(const TCHAR *pTunnelCfgPath) { } SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf); - +#endif return ERR_SUCCESS; } int WireGuardUnInstallServerService(const TCHAR *pTunnelName) { - // 卸载服务 - TCHAR cmdBuf[MAX_PATH]; - TCHAR svrName[MAX_PATH]; + // 卸载服务 int ret; - DWORD retCode; if (pTunnelName == nullptr || lstrlen(pTunnelName) == 0) { SPDLOG_ERROR(TEXT("Input pTunnelName params error")); return -ERR_INPUT_PARAMS; } +#if 0 StringCbCopy(svrName, MAX_PATH, pTunnelName); PathStripPath(svrName); PathRemoveExtension(svrName); +#endif +#if USED_EMBEDDED_WG + if ((ret = RemoveGuardService(pTunnelName, true)) != ERR_SUCCESS) { + SPDLOG_ERROR(TEXT("Stop WireGuard Service Error: {0}"), ret); + return ret; + } +#else StringCbPrintf(cmdBuf, MAX_PATH, TEXT("\"%s\" /uninstalltunnelservice %s"), @@ -160,7 +179,7 @@ int WireGuardUnInstallServerService(const TCHAR *pTunnelName) { } SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf); - +#endif return ERR_SUCCESS; } @@ -194,9 +213,12 @@ int IsWireGuardServerInstalled(bool *pIsInstalled) { } int IsWireGuardServerRunning(const TCHAR *pIfName, bool *pIsRunning) { - int ret; +#if USED_EMBEDDED_WG + return GetWireGuardServiceStatus(pIfName, pIsRunning); +#else + int ret; PNIC_CONTENT pInfo = nullptr; - int size = 0; + int size = 0; if (pIfName == nullptr || lstrlen(pIfName) == 0) { SPDLOG_ERROR(TEXT("Input pIfName params error")); @@ -223,6 +245,7 @@ int IsWireGuardServerRunning(const TCHAR *pIfName, bool *pIsRunning) { } return ret; +#endif } int WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig) { @@ -500,7 +523,9 @@ int WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgConfig) { return ERR_SUCCESS; } +// TODO: Change implement int GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, TCHAR *pPrivKey, int privKeySize) { +#if 0 int ret; DWORD retCode; TCHAR cmdBuffer[MAX_PATH]; @@ -540,10 +565,11 @@ int GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, TCHAR *pPrivKey, i StringCbCopy(pPubKey, pubkeySize, cmdResult); SPDLOG_DEBUG(TEXT("Run command [{0}] resutl \'{1}\'"), cmdBuffer, cmdResult); - +#endif return ERR_SUCCESS; } +#if 0 int SetWireguardPath(const TCHAR *pPath) { if (pPath == nullptr) { return -ERR_INPUT_PARAMS; @@ -573,6 +599,7 @@ int SetWireguardPath(const TCHAR *pPath) { } } + int FindWireguardExe(TCHAR *pFullPath, int maxSize) { TCHAR path[MAX_PATH]; TCHAR wireguardPath[MAX_PATH]; @@ -708,7 +735,6 @@ int FindWireguardExe(TCHAR *pFullPath, int maxSize) { return -ERR_FILE_NOT_EXISTS; } -#if 0 int InstallWindowsNATCommand() { TCHAR psCmdPath[MAX_PATH]; diff --git a/NetTunnelSDKTestApp/NetNat.cpp b/NetTunnelSDKTestApp/NetNat.cpp new file mode 100644 index 0000000..940c929 --- /dev/null +++ b/NetTunnelSDKTestApp/NetNat.cpp @@ -0,0 +1,145 @@ +#include +#include +#include +#include + +#pragma comment(lib, "wbemuuid.lib") + +int net_nat() { + HRESULT hr; + + // Initialize COM + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (FAILED(hr)) { + std::cout << "Failed to initialize COM" << std::endl; + return 1; + } + + // Initialize security + hr = CoInitializeSecurity(NULL, + -1, + NULL, + NULL, + RPC_C_AUTHN_LEVEL_DEFAULT, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, + EOAC_NONE, + NULL); + if (FAILED(hr)) { + std::cout << "Failed to initialize security" << std::endl; + CoUninitialize(); + return 1; + } + + // Obtain the initial locator to WMI + IWbemLocator *pLocator = NULL; + hr = CoCreateInstance(CLSID_WbemLocator, + 0, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, + reinterpret_cast(&pLocator)); + if (FAILED(hr)) { + std::cout << "Failed to create IWbemLocator object" << std::endl; + CoUninitialize(); + return 1; + } + + // Connect to the root\StandardCimv2 namespace with the current user + IWbemServices *pServices = NULL; + hr = pLocator->ConnectServer(_bstr_t(L"ROOT\\StandardCimv2"), NULL, NULL, 0, NULL, 0, 0, &pServices); + if (FAILED(hr)) { + std::cout << "Failed to connect to WMI namespace" << std::endl; + pLocator->Release(); + CoUninitialize(); + return 1; + } + + // Set the authentication information to the current user + hr = CoSetProxyBlanket(pServices, + RPC_C_AUTHN_WINNT, + RPC_C_AUTHZ_NONE, + NULL, + RPC_C_AUTHN_LEVEL_CALL, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, + EOAC_NONE); + if (FAILED(hr)) { + std::cout << "Failed to set proxy blanket" << std::endl; + pServices->Release(); + pLocator->Release(); + CoUninitialize(); + return 1; + } + + // Get the NAT class object + IWbemClassObject *pClass = NULL; + hr = pServices->GetObject(_bstr_t("MSFT_NetNat"), 0, NULL, &pClass, NULL); + if (FAILED(hr)) { + std::cout << "Failed to get NAT class object" << std::endl; + pServices->Release(); + pLocator->Release(); + CoUninitialize(); + return 1; + } + + // Spawn an instance of the NAT class + IWbemClassObject *pInstance = NULL; + hr = pClass->SpawnInstance(0, &pInstance); + if (FAILED(hr)) { + std::cout << "Failed to spawn NAT instance" << std::endl; + pClass->Release(); + pServices->Release(); + pLocator->Release(); + CoUninitialize(); + return 1; + } + + // Set the properties of the NAT instance + VARIANT var; + VariantInit(&var); + + // Set the name of the NAT instance + var.vt = VT_BSTR; + var.bstrVal = SysAllocString(L"MyNATRule"); + hr = pInstance->Put(L"Name", 0, &var, 0); + if (FAILED(hr)) { + std::cout << "Failed to set NAT instance name" << std::endl; + VariantClear(&var); + pInstance->Release(); + pClass->Release(); + pServices->Release(); + pLocator->Release(); + CoUninitialize(); + return 1; + } + + // Set other properties as needed + // ... + + // Create the NAT instance + IWbemCallResult *pResult = NULL; + hr = pServices->PutInstance(pInstance, WBEM_FLAG_CREATE_ONLY, NULL, &pResult); + if (FAILED(hr)) { + std::cout << "Failed to create NAT instance" << std::endl; + VariantClear(&var); + pInstance->Release(); + pClass->Release(); + pServices->Release(); + pLocator->Release(); + CoUninitialize(); + return 1; + } + + // Cleanup + VariantClear(&var); + pResult->Release(); + pInstance->Release(); + pClass->Release(); + pServices->Release(); + pLocator->Release(); + CoUninitialize(); + + std::cout << "NAT rule created successfully" << std::endl; + + return 0; +} \ No newline at end of file diff --git a/NetTunnelSDKTestApp/NetTunnelSDKTestApp.cpp b/NetTunnelSDKTestApp/NetTunnelSDKTestApp.cpp index cb5c839..89e35d5 100644 --- a/NetTunnelSDKTestApp/NetTunnelSDKTestApp.cpp +++ b/NetTunnelSDKTestApp/NetTunnelSDKTestApp.cpp @@ -44,7 +44,7 @@ void test_socket() { #if 0 int service_test() { - TCHAR szSvcName[] = _T("WireGuard"); + TCHAR szSvcName[] = TEXT("WireGuard"); SC_HANDLE schSCManager = nullptr; SC_HANDLE schService = nullptr; @@ -55,7 +55,6 @@ int service_test() { DWORD dwBytesNeeded = 0; // Get a handle to the SCM database. - schSCManager = OpenSCManager(nullptr, // local computer nullptr, // ServicesActive database SC_MANAGER_ALL_ACCESS); // full access rights @@ -111,13 +110,47 @@ int service_test() { cin.get(); return 0; } + +bool test_code() { + char temp_path[MAX_PATH + 1] = { 0 }; + if (!::GetTempPathA(MAX_PATH, temp_path)) + { + //LOG_ERROR("GetTempPathA failed! we use the default logger!"); + strcpy_s(temp_path, MAX_PATH, "c:\\windows\\temp\\"); + } + + char log_file[MAX_PATH + 1] = { 0 }; + sprintf_s(log_file, MAX_PATH, "%s%s", temp_path, "tunnel.log"); + +#ifdef _DEBUG + LOG_LEVEL log_level = LOG_DEBUG; +#else + LOG_LEVEL log_level = TUNNEL_LOG_INFO; +#endif + + int ret = TunnelSDKInitEnv(NULL, g_PlatformURL, log_file, log_level, true); + if (ret != ERR_SUCCESS) + { + //LOG_ERROR("TunnelSDKInitEnv failed! err=%d!", ret); + return false; + } + + std::string local_ip = "127.0.0.1"; + PUSER_SERVER_CONFIG server_config = NULL; + ret = GetUserServerConfigure(NULL, local_ip.c_str(), &server_config); + if (ret != ERR_SUCCESS) + { + //LOG_ERROR("GetUserServerConfigure failed! err=%d!", ret); + return false; + } +} #endif int tunnel_service() { PUSER_SERVER_CONFIG pSvrCfg; //TCHAR logPath[MAX_PATH]; - TunnelSDKInitEnv(g_AppPath, g_PlatformURL, nullptr, LOG_DEBUG, true); + TunnelSDKInitEnv(nullptr, g_PlatformURL, nullptr, LOG_DEBUG, true); //StringCbPrintf(logPath, MAX_PATH, TEXT("%s\\TestApp.log"), g_AppPath); //InitTunnelSDKLog(nullptr, LOG_DEBUG); @@ -144,8 +177,13 @@ int main() { //SetRouteTable(); //CreatePorxyService(); - //tunnel_service(); - test_socket(); + //test_code(); + //test_socket(); + tunnel_service(); + //net_nat(); + + //main_wireguard(true); + //main_wireguard_getinfo(); while (true) { Sleep(100); diff --git a/NetTunnelSDKTestApp/NetTunnelSDKTestApp.vcxproj b/NetTunnelSDKTestApp/NetTunnelSDKTestApp.vcxproj index ca7d327..a9b41cb 100644 --- a/NetTunnelSDKTestApp/NetTunnelSDKTestApp.vcxproj +++ b/NetTunnelSDKTestApp/NetTunnelSDKTestApp.vcxproj @@ -105,6 +105,7 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true ../NetTunnelSDK;%(AdditionalIncludeDirectories) + Default Console @@ -132,6 +133,7 @@ + diff --git a/NetTunnelSDKTestApp/NetTunnelSDKTestApp.vcxproj.filters b/NetTunnelSDKTestApp/NetTunnelSDKTestApp.vcxproj.filters index 2333458..05a12c0 100644 --- a/NetTunnelSDKTestApp/NetTunnelSDKTestApp.vcxproj.filters +++ b/NetTunnelSDKTestApp/NetTunnelSDKTestApp.vcxproj.filters @@ -33,6 +33,9 @@ 源文件 + + 源文件 + diff --git a/NetTunnelSDKTestApp/WireGurad.cpp b/NetTunnelSDKTestApp/WireGurad.cpp new file mode 100644 index 0000000..956e9c9 --- /dev/null +++ b/NetTunnelSDKTestApp/WireGurad.cpp @@ -0,0 +1,718 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wireguard.h" +#include "common.h" +#include "tunnel.h" +#include "network.h" + +#include +#include + +#pragma comment(lib, "Crypt32.lib") + +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) + +static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter; +static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter; +static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter; +static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID; +static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion; +static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver; +static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger; +static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging; +static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState; +static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState; +static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration; +static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration; + +#if 0 +static int InitializeWMI() +{ + IWbemLocator* p_instance_ = nullptr; + IWbemServices* p_service_ = nullptr; + IEnumWbemClassObject* p_enum_ = nullptr; + IWbemClassObject *p_obj_ = nullptr; + IWbemClassObject *p_config = nullptr; + + // Step 1: Initialize COM. + HRESULT hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + if (FAILED(hres)) { + SPDLOG_ERROR("CoInitializeEx Error: {0}", GetLastError()); + return false; + } + + // Step 3: Obtain the initial locator to WMI + hres = CoCreateInstance( + CLSID_WbemLocator, + 0, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, + (LPVOID*)&p_instance_); + if (FAILED(hres)) { + SPDLOG_ERROR("CoCreateInstance Error: {0}", GetLastError()); + return false; + } + + // Step 4: Connect to the local root\cimv2 namespace and obtain pointer pSvc to make IWbemServices calls. + hres = p_instance_->ConnectServer( + _bstr_t(L"ROOT\\CIMV2"), + NULL, + NULL, + 0, + NULL, + 0, + 0, + &p_service_ + ); + //ASSERT_THROW(SUCCEEDED(hres), "ConnectServer failed"); + if (FAILED(hres)) { +#ifdef _DEBUG + cout << "ConnectServer failed: " << hres << endl; +#endif + return false; + } + + // Step 5: Set security levels for the proxy + hres = CoSetProxyBlanket( + p_service_, // Indicates the proxy to set + RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx + RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx + NULL, // Server principal name + RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx + RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx + NULL, // client identity + EOAC_NONE // proxy capabilities + ); + //ASSERT_THROW(SUCCEEDED(hres), "CoSetProxyBlanket failed"); + if (FAILED(hres)) { +#ifdef _DEBUG + cout << "CoSetProxyBlanket failed: " << hres << endl; +#endif + return false; + } + + // 通过适配器名称来找到指定的适配器对象. + CComBSTR TheQuery = L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \""; + std::wstring_convert, wchar_t> conversion; + TheQuery += conversion.from_bytes(key_).c_str(); + TheQuery += L"\""; + // const BSTR lang = L"WQL"; + hres = p_service_->ExecQuery( + SysAllocString(L"WQL"), + // L"WQL", + TheQuery, + WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, + NULL, + &p_enum_); + //ASSERT_THROW(SUCCEEDED(hres), "ExecQuery failed"); + if (FAILED(hres)) { +#ifdef _DEBUG + cout << "ExecQuery failed: " << hres << endl; +#endif + return false; + } + + // Get the adapter object. + ULONG num = 0; + hres = p_enum_->Next(WBEM_INFINITE, 1, &p_obj_, &num); + //ASSERT_THROW(SUCCEEDED(hres), "Next failed"); + if (FAILED(hres)) { +#ifdef _DEBUG + cout << "Next failed: " << hres << endl; +#endif + return false; + } + + //ASSERT_THROW(0 < num, "Next failed"); + if (num < 1) { +#ifdef _DEBUG + cout << "Next failed num < 1" << endl; +#endif + return false; + } + + VariantInit(&path_); + hres = p_obj_->Get(L"__PATH", 0, &path_, NULL, NULL); + //ASSERT_THROW(SUCCEEDED(hres), "Get path failed"); + if (FAILED(hres)) { +#ifdef _DEBUG + cout << "Get failed: " << hres << endl; +#endif + return false; + } + hres = p_service_->GetObject(_bstr_t(L"Win32_NetworkAdapterConfiguration"), 0, NULL, &p_config, NULL); + //ASSERT_THROW(SUCCEEDED(hres), "GetObject Win32_NetworkAdapterConfiguration failed"); + if (FAILED(hres)) { +#ifdef _DEBUG + cout << "GetObject failed: " << hres << endl; +#endif + return false; + } + is_init_ = true; + return true; +} +#endif + +static HMODULE InitializeWireGuardNT(void) { + HMODULE WireGuardDll = LoadLibraryExW(L"wireguard.dll", + nullptr, + LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); + if (!WireGuardDll) { + return nullptr; + } +#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == nullptr) + if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) || + X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) || + X(WireGuardSetLogger) || X(WireGuardSetAdapterLogging) || X(WireGuardGetAdapterState) || + X(WireGuardSetAdapterState) || X(WireGuardGetConfiguration) || X(WireGuardSetConfiguration)) +#undef X + { + DWORD LastError = GetLastError(); + FreeLibrary(WireGuardDll); + SetLastError(LastError); + return nullptr; + } + return WireGuardDll; +} + +// +//static void CALLBACK ConsoleLogger(_In_ WIREGUARD_LOGGER_LEVEL Level, +// _In_ DWORD64 Timestamp, +// _In_z_ const WCHAR *LogLine) { +// SYSTEMTIME SystemTime; +// GetSystemTime(&SystemTime); +// //FileTimeToSystemTime((FILETIME *)&Timestamp, &SystemTime); +// WCHAR LevelMarker; +// switch (Level) { +// case WIREGUARD_LOG_INFO: +// LevelMarker = L'+'; +// break; +// case WIREGUARD_LOG_WARN: +// LevelMarker = L'-'; +// break; +// case WIREGUARD_LOG_ERR: +// LevelMarker = L'!'; +// break; +// default: +// return; +// } +// fwprintf(stderr, +// L"%04u-%02u-%02u %02u:%02u:%02u.%04u [%c] %s\n", +// SystemTime.wYear, +// SystemTime.wMonth, +// SystemTime.wDay, +// SystemTime.wHour, +// SystemTime.wMinute, +// SystemTime.wSecond, +// SystemTime.wMilliseconds, +// LevelMarker, +// LogLine); +//} + +static DWORD64 Now() { + return 0; +} + +#if 0 +static DWORD LogError(_In_z_ const WCHAR *Prefix, _In_ DWORD Error) { + WCHAR tMsg[MAX_PATH]; + StringCbPrintfW(tMsg, MAX_PATH, L"Error: %d", Error); + ConsoleLogger(WIREGUARD_LOG_ERR, Now(), tMsg); + return Error; +} + +static DWORD LogLastError(_In_z_ const WCHAR *Prefix) { + DWORD LastError = GetLastError(); + LogError(Prefix, LastError); + SetLastError(LastError); + return LastError; +} + +static void Log(_In_ WIREGUARD_LOGGER_LEVEL Level, _In_z_ const WCHAR *Format, ...) { + WCHAR LogLine[0x200]; + va_list args; + va_start(args, Format); + _vsnwprintf_s(LogLine, _countof(LogLine), _TRUNCATE, Format, args); + va_end(args); + ConsoleLogger(Level, Now(), LogLine); +} +#endif + +_Must_inspect_result_ _Return_type_success_(return != FALSE) static BOOL + GenerateKeyPair(_Out_writes_bytes_all_(WIREGUARD_KEY_LENGTH) BYTE PublicKey[WIREGUARD_KEY_LENGTH], + _Out_writes_bytes_all_(WIREGUARD_KEY_LENGTH) BYTE PrivateKey[WIREGUARD_KEY_LENGTH]) { + BCRYPT_ALG_HANDLE Algorithm; + BCRYPT_KEY_HANDLE Key; + NTSTATUS Status; + + struct { + BCRYPT_ECCKEY_BLOB Header; + BYTE Public[32]; + BYTE Unused[32]; + BYTE Private[32]; + } ExportedKey; + + ULONG Bytes; + + Status = BCryptOpenAlgorithmProvider(&Algorithm, BCRYPT_ECDH_ALGORITHM, nullptr, 0); + if (!NT_SUCCESS(Status)) { + goto out; + } + + Status = BCryptSetProperty(Algorithm, + BCRYPT_ECC_CURVE_NAME, + (PUCHAR)BCRYPT_ECC_CURVE_25519, + sizeof(BCRYPT_ECC_CURVE_25519), + 0); + if (!NT_SUCCESS(Status)) { + goto cleanupProvider; + } + + Status = BCryptGenerateKeyPair(Algorithm, &Key, 255, 0); + if (!NT_SUCCESS(Status)) { + goto cleanupProvider; + } + + Status = BCryptFinalizeKeyPair(Key, 0); + if (!NT_SUCCESS(Status)) { + goto cleanupKey; + } + + Status = BCryptExportKey(Key, + nullptr, + BCRYPT_ECCPRIVATE_BLOB, + (PUCHAR)&ExportedKey, + sizeof(ExportedKey), + &Bytes, + 0); + if (!NT_SUCCESS(Status)) { + goto cleanupKey; + } + + memcpy(PublicKey, ExportedKey.Public, WIREGUARD_KEY_LENGTH); + memcpy(PrivateKey, ExportedKey.Private, WIREGUARD_KEY_LENGTH); + SecureZeroMemory(&ExportedKey, sizeof(ExportedKey)); + +cleanupKey: + BCryptDestroyKey(Key); +cleanupProvider: + BCryptCloseAlgorithmProvider(Algorithm, 0); +out: + SetLastError(RtlNtStatusToDosError(Status)); + return NT_SUCCESS(Status); +} + +static HANDLE QuitEvent; + +//static BOOL WINAPI CtrlHandler(_In_ DWORD CtrlType) { +// switch (CtrlType) { +// case CTRL_C_EVENT: +// case CTRL_BREAK_EVENT: +// case CTRL_CLOSE_EVENT: +// case CTRL_LOGOFF_EVENT: +// case CTRL_SHUTDOWN_EVENT: +// SPDLOG_INFO("Cleaning up and shutting down"); +// SetEvent(QuitEvent); +// return TRUE; +// } +// return FALSE; +//} + +static BOOL GetEndPoint(const TCHAR *Input, _Out_ SOCKADDR_INET *ResolvedDemoServer) { + SOCKET Socket = INVALID_SOCKET; + TCHAR name[MAX_PATH]; + ADDRINFOA Hints = {}; + ADDRINFOA *Resolution; + + StringCbCopy(name, MAX_PATH, Input); + TCHAR *Colon1 = strchr(name, ':'); + *Colon1 = '\0'; + + Hints.ai_family = AF_UNSPEC; + Hints.ai_socktype = SOCK_STREAM; + Hints.ai_protocol = IPPROTO_TCP; + + if (GetAddrInfo(name, Colon1 + 1, &Hints, &Resolution)) { + return FALSE; + } + + for (const ADDRINFOA *Candidate = Resolution; Candidate; Candidate = Candidate->ai_next) { + UINT16 port; + if (Candidate->ai_family != AF_INET && Candidate->ai_family != AF_INET6) { + continue; + } + memcpy(ResolvedDemoServer, Candidate->ai_addr, Candidate->ai_addrlen); + port = static_cast(strtoul(Colon1 + 1, nullptr, 10)); + + if (ResolvedDemoServer->si_family == AF_INET) { + ResolvedDemoServer->Ipv4.sin_port = htons(port); + } else if (ResolvedDemoServer->si_family == AF_INET6) { + ResolvedDemoServer->Ipv6.sin6_port = htons(port); + } + + closesocket(Socket); + FreeAddrInfo(Resolution); + return TRUE; + } + + closesocket(Socket); + FreeAddrInfo(Resolution); + return FALSE; +} + +_Return_type_success_(return != FALSE) static BOOL TalkToDemoServer(_In_reads_bytes_(InputLength) const CHAR *Input, + _In_ DWORD InputLength, + _Out_writes_bytes_(*OutputLength) CHAR *Output, + _Inout_ DWORD *OutputLength, + _Out_ SOCKADDR_INET *ResolvedDemoServer) { + SOCKET Socket = INVALID_SOCKET; + ADDRINFOW Hints = {}; + ADDRINFOW *Resolution; + BOOL Ret = FALSE; + + Hints.ai_family = AF_UNSPEC; + Hints.ai_socktype = SOCK_STREAM; + Hints.ai_protocol = IPPROTO_TCP; + + if (GetAddrInfoW(L"demo.wireguard.com", L"42912", &Hints, &Resolution)) { + return FALSE; + } + for (ADDRINFOW *Candidate = Resolution; Candidate; Candidate = Candidate->ai_next) { + if (Candidate->ai_family != AF_INET && Candidate->ai_family != AF_INET6) { + continue; + } + Socket = socket(Candidate->ai_family, Candidate->ai_socktype, Candidate->ai_protocol); + if (Socket == INVALID_SOCKET) { + goto cleanupResolution; + } + if (connect(Socket, Candidate->ai_addr, (int)Candidate->ai_addrlen) == SOCKET_ERROR) { + closesocket(Socket); + Socket = INVALID_SOCKET; + } + memcpy(ResolvedDemoServer, Candidate->ai_addr, Candidate->ai_addrlen); + break; + } + if (Socket == INVALID_SOCKET) { + goto cleanupResolution; + } + if (send(Socket, Input, InputLength, 0) == SOCKET_ERROR) { + goto cleanupSocket; + } + if ((*OutputLength = recv(Socket, Output, *OutputLength, 0)) == SOCKET_ERROR) { + goto cleanupSocket; + } + Ret = TRUE; +cleanupSocket: + closesocket(Socket); +cleanupResolution: + FreeAddrInfoW(Resolution); + return Ret; +} + +typedef struct { + WIREGUARD_INTERFACE Interface; + WIREGUARD_PEER RemoteServer; + WIREGUARD_ALLOWED_IP AllV4; + WIREGUARD_ALLOWED_IP AllV4_2; +} WG_CONFIG_INFO; + +int main_wireguard_getinfo() { + DWORD Bytes; + WG_CONFIG_INFO Config {}; + HMODULE WireGuard = InitializeWireGuardNT(); + if (!WireGuard) { + SPDLOG_ERROR("Failed to initialize WireGuardNT: {0}", GetLastError()); + return -1; + } + + /* CryptStringToBinary(TEXT("WGAlqvys3O83VmWug6Z8NzUrxGr/PNHSeOVFnKLSe2k="), + 0, + CRYPT_STRING_BASE64, + Config.Interface.PublicKey, + &Bytes, + nullptr, + nullptr);*/ + + WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(L"admin"); + + if (!Adapter) { + SPDLOG_ERROR("Failed to create adapter: {0}", GetLastError()); + return -1; + } + + Bytes = sizeof(Config); + if (!WireGuardGetConfiguration(Adapter, &Config.Interface, &Bytes)) { + SPDLOG_ERROR("Failed to get configuration: {0}", GetLastError()); + //WireGuardCloseAdapter(Adapter); + return -3; + } + + //WireGuardCloseAdapter(Adapter); + + return 0; +} + +int main_wireguard(bool isDelete) { + WG_CONFIG_INFO Config {}; + DWORD LastError; + WSADATA WsaData; + MIB_IPINTERFACE_ROW IpInterface = {}; + DWORD Bytes; + MIB_UNICASTIPADDRESS_ROW AddressRow; + GUID ExampleGuid = { + 0xdeadc001, + 0xbeef, + 0xbabe, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef} + }; + WIREGUARD_ADAPTER_HANDLE Adapter; + DWORD Version; + + if (WSAStartup(MAKEWORD(2, 2), &WsaData)) { + SPDLOG_ERROR("Failed to initialize Winsock: {0}", GetLastError()); + return -1; + } + HMODULE WireGuard = InitializeWireGuardNT(); + if (!WireGuard) { + SPDLOG_ERROR("Failed to initialize WireGuardNT: {0}", GetLastError()); + return -2; + } + + SPDLOG_INFO("WireGuardNT library loaded"); + + // 配置本地隧道接口 + Config.Interface.Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY; + Config.Interface.PeersCount = 1; + CryptStringToBinary(TEXT("WGAlqvys3O83VmWug6Z8NzUrxGr/PNHSeOVFnKLSe2k="), + 0, + CRYPT_STRING_BASE64, + Config.Interface.PrivateKey, + &Bytes, + nullptr, + nullptr); + + // 配置远程隧道接口 + Config.RemoteServer.Flags = static_cast( + WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE | WIREGUARD_PEER_HAS_ENDPOINT); + Config.RemoteServer.AllowedIPsCount = 2; + Config.RemoteServer.PersistentKeepalive = 30; + CryptStringToBinary(TEXT("q3ep8hN2v3VpHbcru+rTmvyBt13iH0DkEsVAyT2LpVo="), + 0, + CRYPT_STRING_BASE64, + Config.RemoteServer.PublicKey, + &Bytes, + nullptr, + nullptr); + + if (!GetEndPoint(TEXT("efc.xajhuang.com:10000"), &Config.RemoteServer.Endpoint)) { + SPDLOG_ERROR("Failed to talk to demo server: {0}", GetLastError()); + goto cleanupWireGuard; + } + + Config.AllV4.AddressFamily = AF_INET; + Config.AllV4.Cidr = 24; + InetPtonA(AF_INET, TEXT("10.10.10.0"), &Config.AllV4.Address.V4.S_un.S_addr); + + Config.AllV4_2.AddressFamily = AF_INET; + Config.AllV4_2.Cidr = 24; + InetPtonA(AF_INET, TEXT("192.168.100.0"), &Config.AllV4.Address.V4.S_un.S_addr); + + InitializeUnicastIpAddressEntry(&AddressRow); + AddressRow.Address.Ipv4.sin_family = AF_INET; + AddressRow.OnLinkPrefixLength = 24; /* This is a /24 network */ + AddressRow.DadState = IpDadStatePreferred; + InetPtonA(AF_INET, TEXT("10.10.10.1"), &AddressRow.Address.Ipv4.sin_addr); + +#if 0 + Log(WIREGUARD_LOG_INFO, L"Generating keypair"); + if (!GenerateKeyPair(PublicKey, Config.Interface.PrivateKey)) { + LastError = LogError(L"Failed to generate keypair", GetLastError()); + goto cleanupWireGuard; + } + + Bytes = sizeof(PublicKeyString); + CryptBinaryToStringA(PublicKey, + sizeof(PublicKey), + CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR, + PublicKeyString, + &Bytes); + + Log(WIREGUARD_LOG_INFO, L"Talking to demo server"); + Bytes = sizeof(ServerResponse) - 1; + if (!TalkToDemoServer(PublicKeyString, + (DWORD)strlen(PublicKeyString), + ServerResponse, + &Bytes, + &Config.RemoteServer.Endpoint)) { + LastError = LogError(L"Failed to talk to demo server", GetLastError()); + goto cleanupWireGuard; + } + + Colon1 = strchr(ServerResponse, ':'); + Colon2 = Colon1 ? strchr(Colon1 + 1, ':') : nullptr; + Colon3 = Colon2 ? strchr(Colon2 + 1, ':') : nullptr; + + if (!Colon1 || !Colon2 || !Colon3) { + LastError = LogError(L"Failed to parse demo server response", ERROR_UNDEFINED_CHARACTER); + goto cleanupWireGuard; + } + if (Bytes && ServerResponse[--Bytes] == '\n') { + ServerResponse[Bytes] = '\0'; + } + *Colon1 = *Colon2 = *Colon3 = '\0'; + + + Bytes = sizeof(Config.RemoteServer.PublicKey); + if (strcmp(ServerResponse, "OK") || != 1 || + !CryptStringToBinaryA(Colon1 + 1, + 0, + CRYPT_STRING_BASE64, + Config.RemoteServer.PublicKey, + &Bytes, + nullptr, + nullptr)) { + LastError = LogError(L"Failed to parse demo server response", ERROR_UNDEFINED_CHARACTER); + goto cleanupWireGuard; + } + if (Config.RemoteServer.Endpoint.si_family == AF_INET) { + Config.RemoteServer.Endpoint.Ipv4.sin_port = htons((u_short)atoi(Colon2 + 1)); + } else if (Config.RemoteServer.Endpoint.si_family == AF_INET6) { + Config.RemoteServer.Endpoint.Ipv6.sin6_port = htons((u_short)atoi(Colon2 + 1)); + } +#endif + + QuitEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr); + if (!QuitEvent) { + SPDLOG_ERROR("Failed to create event:{0}", GetLastError()); + goto cleanupWireGuard; + } + //if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) { + // SPDLOG_ERROR("Failed to set console handler: {0}", GetLastError()); + // goto cleanupQuit; + //} + + Adapter = WireGuardOpenAdapter(L"Demo"); + + if (isDelete) { + SPDLOG_INFO("Remove adapter: {0}", "Demo"); + WireGuardCloseAdapter(Adapter); + return 0; + } + + if (!Adapter) { + Adapter = WireGuardCreateAdapter(L"Demo", L"Example", &ExampleGuid); + if (!Adapter) { + SPDLOG_ERROR("Failed to create adapter: {0}", LastError); + goto cleanupQuit; + } + } + + if (!WireGuardSetAdapterLogging(Adapter, WIREGUARD_ADAPTER_LOG_ON)) { + SPDLOG_ERROR("Failed to enable adapter logging: {0}", GetLastError()); + } + + Version = WireGuardGetRunningDriverVersion(); + SPDLOG_INFO("WireGuardNT v{0}.{1} loaded", (Version >> 16) & 0xff, (Version >> 0) & 0xff); + + WireGuardGetAdapterLUID(Adapter, &AddressRow.InterfaceLuid); + + SetInterfaceIpAddress("Demo", "10.10.10.1", "255.255.255.0"); + +#if 0 + InitializeIpForwardEntry(&DefaultRoute); + DefaultRoute.InterfaceLuid = AddressRow.InterfaceLuid; + DefaultRoute.DestinationPrefix.Prefix.si_family = AF_INET; + DefaultRoute.NextHop.si_family = AF_INET; + DefaultRoute.Metric = 0; + LastError = CreateIpForwardEntry2(&DefaultRoute); + if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS) { + SPDLOG_ERROR("Failed to set default route: {0}", LastError); + goto cleanupAdapter; + } + LastError = CreateUnicastIpAddressEntry(&AddressRow); + if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS) { + SPDLOG_ERROR("Failed to set IP address: {0}", LastError); + goto cleanupAdapter; + } +#endif +#if 1 + InitializeIpInterfaceEntry(&IpInterface); + IpInterface.InterfaceLuid = AddressRow.InterfaceLuid; + IpInterface.Family = AF_INET; + LastError = GetIpInterfaceEntry(&IpInterface); + if (LastError != ERROR_SUCCESS) { + SPDLOG_ERROR("Failed to get IP interface: {0}", LastError); + goto cleanupAdapter; + } + + /*if ((LastError = AddIpAddress(IpInterface.InterfaceIndex)) != 0) { + SPDLOG_ERROR("Set interface IP Error: {0}", LastError); + goto cleanupAdapter; + }*/ + + IpInterface.UseAutomaticMetric = FALSE; + IpInterface.Metric = 0; + IpInterface.NlMtu = 1420; + IpInterface.SitePrefixLength = 0; + LastError = SetIpInterfaceEntry(&IpInterface); + if (LastError != ERROR_SUCCESS) { + SPDLOG_ERROR("Failed to set metric and MTU: {0}", LastError); + goto cleanupAdapter; + } +#endif + + SPDLOG_INFO("Setting configuration and adapter up"); + if (!WireGuardSetConfiguration(Adapter, &Config.Interface, sizeof(Config)) || + !WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE_UP)) { + SPDLOG_ERROR("Failed to set configuration and adapter up: {0}", GetLastError()); + goto cleanupAdapter; + } + + do { + Bytes = sizeof(Config); + if (!WireGuardGetConfiguration(Adapter, &Config.Interface, &Bytes) || !Config.Interface.PeersCount) { + SPDLOG_ERROR("Failed to get configuration: {0}", GetLastError()); + goto cleanupAdapter; + } + DWORD64 Timestamp = Now(); + SYSTEMTIME SystemTime; + FileTimeToSystemTime((FILETIME *)&Timestamp, &SystemTime); + fwprintf(stderr, + L"%04u-%02u-%02u %02u:%02u:%02u.%04u [#] RX: %llu, TX: %llu\r", + SystemTime.wYear, + SystemTime.wMonth, + SystemTime.wDay, + SystemTime.wHour, + SystemTime.wMinute, + SystemTime.wSecond, + SystemTime.wMilliseconds, + Config.RemoteServer.RxBytes, + Config.RemoteServer.TxBytes); + } while (WaitForSingleObject(QuitEvent, 1000) == WAIT_TIMEOUT); + +cleanupAdapter: + WireGuardCloseAdapter(Adapter); +cleanupQuit: + //SetConsoleCtrlHandler(CtrlHandler, FALSE); + CloseHandle(QuitEvent); +cleanupWireGuard: + FreeLibrary(WireGuard); +cleanupWinsock: + WSACleanup(); + return 0; +} \ No newline at end of file diff --git a/NetTunnelSDKTestApp/common.h b/NetTunnelSDKTestApp/common.h index 7fead9d..31b0ff9 100644 --- a/NetTunnelSDKTestApp/common.h +++ b/NetTunnelSDKTestApp/common.h @@ -3,4 +3,7 @@ int ShowRouteTable(); int NetShare(); int GetInterface(); void CryptoExample(); -int SetRouteTable(); \ No newline at end of file +int SetRouteTable(); +int main_wireguard(bool isDelete); +int main_wireguard_getinfo(); +int net_nat(); \ No newline at end of file diff --git a/NetTunnelSDKTestApp/wireguard.h b/NetTunnelSDKTestApp/wireguard.h new file mode 100644 index 0000000..ce562fa --- /dev/null +++ b/NetTunnelSDKTestApp/wireguard.h @@ -0,0 +1,308 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT + * + * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ALIGNED +# if defined(_MSC_VER) +# define ALIGNED(n) __declspec(align(n)) +# elif defined(__GNUC__) +# define ALIGNED(n) __attribute__((aligned(n))) +# else +# error "Unable to define ALIGNED" +# endif +#endif + +/* MinGW is missing this one, unfortunately. */ +#ifndef _Post_maybenull_ +# define _Post_maybenull_ +#endif + +#pragma warning(push) +#pragma warning(disable : 4324) /* structure was padded due to alignment specifier */ + +/** + * A handle representing WireGuard adapter + */ +typedef struct _WIREGUARD_ADAPTER *WIREGUARD_ADAPTER_HANDLE; + +/** + * Creates a new WireGuard adapter. + * + * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 + * characters. + * + * @param TunnelType Name of the adapter tunnel type. Zero-terminated string of up to MAX_ADAPTER_NAME-1 + * characters. + * + * @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation deterministically. + * If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is + * created for each new adapter. It is called "requested" GUID because the API it uses is + * completely undocumented, and so there could be minor interesting complications with its usage. + * + * @return If the function succeeds, the return value is the adapter handle. Must be released with + * WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call + * GetLastError. + */ +typedef _Must_inspect_result_ +_Return_type_success_(return != NULL) +_Post_maybenull_ +WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_CREATE_ADAPTER_FUNC) +(_In_z_ LPCWSTR Name, _In_z_ LPCWSTR TunnelType, _In_opt_ const GUID *RequestedGUID); + +/** + * Opens an existing WireGuard adapter. + * + * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 + * characters. + * + * @return If the function succeeds, the return value is the adapter handle. Must be released with + * WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call + * GetLastError. + */ +typedef _Must_inspect_result_ +_Return_type_success_(return != NULL) +_Post_maybenull_ +WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_OPEN_ADAPTER_FUNC)(_In_z_ LPCWSTR Name); + +/** + * Releases WireGuard adapter resources and, if adapter was created with WireGuardCreateAdapter, removes adapter. + * + * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter. + */ +typedef VOID(WINAPI WIREGUARD_CLOSE_ADAPTER_FUNC)(_In_opt_ WIREGUARD_ADAPTER_HANDLE Adapter); + +/** + * Deletes the WireGuard driver if there are no more adapters in use. + * + * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To + * get extended error information, call GetLastError. + */ +typedef _Return_type_success_(return != FALSE) +BOOL(WINAPI WIREGUARD_DELETE_DRIVER_FUNC)(VOID); + +/** + * Returns the LUID of the adapter. + * + * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter + * + * @param Luid Pointer to LUID to receive adapter LUID. + */ +typedef VOID(WINAPI WIREGUARD_GET_ADAPTER_LUID_FUNC)(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid); + +/** + * Determines the version of the WireGuard driver currently loaded. + * + * @return If the function succeeds, the return value is the version number. If the function fails, the return value is + * zero. To get extended error information, call GetLastError. Possible errors include the following: + * ERROR_FILE_NOT_FOUND WireGuard not loaded + */ +typedef _Return_type_success_(return != 0) +DWORD(WINAPI WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC)(VOID); + +/** + * Determines the level of logging, passed to WIREGUARD_LOGGER_CALLBACK. + */ +typedef enum +{ + WIREGUARD_LOG_INFO, /**< Informational */ + WIREGUARD_LOG_WARN, /**< Warning */ + WIREGUARD_LOG_ERR /**< Error */ +} WIREGUARD_LOGGER_LEVEL; + +/** + * Called by internal logger to report diagnostic messages + * + * @param Level Message level. + * + * @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC. + * + * @param Message Message text. + */ +typedef VOID(CALLBACK *WIREGUARD_LOGGER_CALLBACK)( + _In_ WIREGUARD_LOGGER_LEVEL Level, + _In_ DWORD64 Timestamp, + _In_z_ LPCWSTR Message); + +/** + * Sets logger callback function. + * + * @param NewLogger Pointer to callback function to use as a new global logger. NewLogger may be called from various + * threads concurrently. Should the logging require serialization, you must handle serialization in + * NewLogger. Set to NULL to disable. + */ +typedef VOID(WINAPI WIREGUARD_SET_LOGGER_FUNC)(_In_ WIREGUARD_LOGGER_CALLBACK NewLogger); + +/** + * Whether and how logs from the driver are collected for the callback function. + */ +typedef enum +{ + WIREGUARD_ADAPTER_LOG_OFF, /**< No logs are generated from the driver. */ + WIREGUARD_ADAPTER_LOG_ON, /**< Logs are generated from the driver. */ + WIREGUARD_ADAPTER_LOG_ON_WITH_PREFIX /**< Logs are generated from the driver, index-prefixed. */ +} WIREGUARD_ADAPTER_LOG_STATE; + +/** + * Sets whether and how the adapter logs to the logger previously set up with WireGuardSetLogger. + * + * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter + * + * @param LogState Adapter logging state. + * + * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To + * get extended error information, call GetLastError. + */ +typedef _Return_type_success_(return != FALSE) +BOOL(WINAPI WIREGUARD_SET_ADAPTER_LOGGING_FUNC) +(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_LOG_STATE LogState); + +/** + * Determines the state of the adapter. + */ +typedef enum +{ + WIREGUARD_ADAPTER_STATE_DOWN, /**< Down */ + WIREGUARD_ADAPTER_STATE_UP, /**< Up */ +} WIREGUARD_ADAPTER_STATE; + +/** + * Sets the adapter state of the WireGuard adapter. Note: sockets are owned by the process that sets the state to up. + * + * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter + * + * @param State Adapter state. + * + * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To + * get extended error information, call GetLastError. + */ +typedef _Return_type_success_(return != FALSE) +BOOL(WINAPI WIREGUARD_SET_ADAPTER_STATE_FUNC) +(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_STATE State); + +/** + * Gets the adapter state of the WireGuard adapter. + * + * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter + * + * @param State Pointer to adapter state. + * + * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To + * get extended error information, call GetLastError. + */ +typedef _Must_inspect_result_ +_Return_type_success_(return != FALSE) +BOOL(WINAPI WIREGUARD_GET_ADAPTER_STATE_FUNC) +(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ WIREGUARD_ADAPTER_STATE *State); + +#define WIREGUARD_KEY_LENGTH 32 + +typedef struct _WIREGUARD_ALLOWED_IP WIREGUARD_ALLOWED_IP; +struct ALIGNED(8) _WIREGUARD_ALLOWED_IP +{ + union + { + IN_ADDR V4; + IN6_ADDR V6; + } Address; /**< IP address */ + ADDRESS_FAMILY AddressFamily; /**< Address family, either AF_INET or AF_INET6 */ + BYTE Cidr; /**< CIDR of allowed IPs */ +}; + +typedef enum +{ + WIREGUARD_PEER_HAS_PUBLIC_KEY = 1 << 0, /**< The PublicKey field is set */ + WIREGUARD_PEER_HAS_PRESHARED_KEY = 1 << 1, /**< The PresharedKey field is set */ + WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, /**< The PersistentKeepAlive field is set */ + WIREGUARD_PEER_HAS_ENDPOINT = 1 << 3, /**< The Endpoint field is set */ + WIREGUARD_PEER_REPLACE_ALLOWED_IPS = 1 << 5, /**< Remove all allowed IPs before adding new ones */ + WIREGUARD_PEER_REMOVE = 1 << 6, /**< Remove specified peer */ + WIREGUARD_PEER_UPDATE = 1 << 7 /**< Do not add a new peer */ +} WIREGUARD_PEER_FLAG; + +typedef struct _WIREGUARD_PEER WIREGUARD_PEER; +struct ALIGNED(8) _WIREGUARD_PEER +{ + WIREGUARD_PEER_FLAG Flags; /**< Bitwise combination of flags */ + DWORD Reserved; /**< Reserved; must be zero */ + BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Public key, the peer's primary identifier */ + BYTE PresharedKey[WIREGUARD_KEY_LENGTH]; /**< Preshared key for additional layer of post-quantum resistance */ + WORD PersistentKeepalive; /**< Seconds interval, or 0 to disable */ + SOCKADDR_INET Endpoint; /**< Endpoint, with IP address and UDP port number*/ + DWORD64 TxBytes; /**< Number of bytes transmitted */ + DWORD64 RxBytes; /**< Number of bytes received */ + DWORD64 LastHandshake; /**< Time of the last handshake, in 100ns intervals since 1601-01-01 UTC */ + DWORD AllowedIPsCount; /**< Number of allowed IP structs following this struct */ +}; + +typedef enum +{ + WIREGUARD_INTERFACE_HAS_PUBLIC_KEY = (1 << 0), /**< The PublicKey field is set */ + WIREGUARD_INTERFACE_HAS_PRIVATE_KEY = (1 << 1), /**< The PrivateKey field is set */ + WIREGUARD_INTERFACE_HAS_LISTEN_PORT = (1 << 2), /**< The ListenPort field is set */ + WIREGUARD_INTERFACE_REPLACE_PEERS = (1 << 3) /**< Remove all peers before adding new ones */ +} WIREGUARD_INTERFACE_FLAG; + +typedef struct _WIREGUARD_INTERFACE WIREGUARD_INTERFACE; +struct ALIGNED(8) _WIREGUARD_INTERFACE +{ + WIREGUARD_INTERFACE_FLAG Flags; /**< Bitwise combination of flags */ + WORD ListenPort; /**< Port for UDP listen socket, or 0 to choose randomly */ + BYTE PrivateKey[WIREGUARD_KEY_LENGTH]; /**< Private key of interface */ + BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Corresponding public key of private key */ + DWORD PeersCount; /**< Number of peer structs following this struct */ +}; + +/** + * Sets the configuration of the WireGuard adapter. + * + * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter + * + * @param Config Configuration for the adapter. + * + * @param Bytes Number of bytes in Config allocation. + * + * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To + * get extended error information, call GetLastError. + */ +typedef _Return_type_success_(return != FALSE) +BOOL(WINAPI WIREGUARD_SET_CONFIGURATION_FUNC) +(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_reads_bytes_(Bytes) const WIREGUARD_INTERFACE *Config, _In_ DWORD Bytes); + +/** + * Gets the configuration of the WireGuard adapter. + * + * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter + * + * @param Config Configuration for the adapter. + * + * @param Bytes Pointer to number of bytes in Config allocation. + * + * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To + * get extended error information, call GetLastError, which if ERROR_MORE_DATA, Bytes is updated with the + * required size. + */ +typedef _Must_inspect_result_ +_Return_type_success_(return != FALSE) +BOOL(WINAPI WIREGUARD_GET_CONFIGURATION_FUNC) +(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, + _Out_writes_bytes_all_(*Bytes) WIREGUARD_INTERFACE *Config, + _Inout_ DWORD *Bytes); + +#pragma warning(pop) + +#ifdef __cplusplus +} +#endif diff --git a/NetTunnelSvr/NetTunnelSvr.cpp b/NetTunnelSvr/NetTunnelSvr.cpp new file mode 100644 index 0000000..0e1a7af --- /dev/null +++ b/NetTunnelSvr/NetTunnelSvr.cpp @@ -0,0 +1,120 @@ +// NetTunnelSvr.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// +#include +#include +#include + +#define WG_TUNNEL_SVR_NAME TEXT("WireGuard_DLL_SVR") + +typedef BOOL(WINAPI WIREGUARD_TUNNEL_SERVICE_FUNC)(_In_z_ LPCWSTR Name); +static WIREGUARD_TUNNEL_SERVICE_FUNC *WireGuardTunnelService; + +static void LogToSystemEventLog(int wErrorType, int wCustumerCode, const TCHAR *szMsg) { + HANDLE hEventSource; + DWORD dwEventIdentifer; + + switch (wErrorType) { + case EVENTLOG_SUCCESS: + case EVENTLOG_AUDIT_SUCCESS: + dwEventIdentifer = 0x00; + break; + case EVENTLOG_INFORMATION_TYPE: + dwEventIdentifer = 0x01; + break; + case EVENTLOG_WARNING_TYPE: + dwEventIdentifer = 0x02; + break; + case EVENTLOG_ERROR_TYPE: + case EVENTLOG_AUDIT_FAILURE: + dwEventIdentifer = 0x03; + break; + default: + dwEventIdentifer = 0; + break; + } + // 移位获得Sev,前面给出的 wErrorType 为 EVENTLOG_ERROR_TYPE,对应着下图 “级别” 一列显示“错误”图标 + dwEventIdentifer <<= 30; + dwEventIdentifer |= static_cast(wCustumerCode); // 前面自定义了Code,对应着下图中 事件ID 20 + + hEventSource = RegisterEventSource(nullptr, WG_TUNNEL_SVR_NAME); + + if (nullptr != hEventSource) { + + LPCTSTR lpszStrings[2] = { + WG_TUNNEL_SVR_NAME, + szMsg}; //要写入日志的信息有两行,分别是 服务名,和前面给出的szMsg,对应着下图“以下是包含在事件中的信息” + + ReportEvent(hEventSource, // event log handle + wErrorType, // event type + 0, // event category + dwEventIdentifer, // event identifier + nullptr, // no security identifier + 2, // size of lpszStrings array + 0, // no binary data + lpszStrings, // array of strings + nullptr); // no binary data + DeregisterEventSource(hEventSource); + } +} + +static HMODULE InitializeWireGuardNT(void) { + const HMODULE tunnel = LoadLibraryExW(L"tunnel.dll", + nullptr, + LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); + if (!tunnel) { + TCHAR tMsg[MAX_PATH * sizeof(TCHAR)]; + StringCbPrintf(tMsg, MAX_PATH * sizeof(TCHAR), TEXT("LoadLibraryExW Error: %d\n"), GetLastError()); + LogToSystemEventLog(EVENTLOG_ERROR_TYPE, 0x01, tMsg); + return nullptr; + } + +#define X(Name) ((*(FARPROC *)&(Name) = GetProcAddress(tunnel, #Name)) == nullptr) + if (X(WireGuardTunnelService)) +#undef X + { + const DWORD LastError = GetLastError(); + FreeLibrary(tunnel); + SetLastError(LastError); + return nullptr; + } + return tunnel; +} + +int _tmain(int wargc, _TCHAR *wargv[]) { + TCHAR tMsg[MAX_PATH] = {}; + + if (wargc == 3 && !wcscmp(wargv[1], L"/service")) { + BOOL ret; + const HMODULE hModule = InitializeWireGuardNT(); + + if (!hModule || !WireGuardTunnelService) { + StringCbPrintf(tMsg, MAX_PATH, TEXT("Init WireGuardTunnelService Service Error: %d\n"), GetLastError()); + LogToSystemEventLog(EVENTLOG_ERROR_TYPE, 0x01, tMsg); + return -1; + } + + ret = WireGuardTunnelService(wargv[2]); + + if (ret) { + StringCbPrintf(tMsg, MAX_PATH, TEXT("Start WireGuardTunnelService Service Successed\n")); + LogToSystemEventLog(EVENTLOG_INFORMATION_TYPE, 0x00, tMsg); + } else { + StringCbPrintf(tMsg, MAX_PATH, TEXT("Start WireGuardTunnelService Service failed: %d\n"), GetLastError()); + LogToSystemEventLog(EVENTLOG_ERROR_TYPE, 0x02, tMsg); + } + + return ret; + } + return 0; +} + +// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 +// 调试程序: F5 或调试 >“开始调试”菜单 + +// 入门使用技巧: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 \ No newline at end of file diff --git a/NetTunnelSvr/NetTunnelSvr.vcxproj b/NetTunnelSvr/NetTunnelSvr.vcxproj new file mode 100644 index 0000000..6b8be05 --- /dev/null +++ b/NetTunnelSvr/NetTunnelSvr.vcxproj @@ -0,0 +1,138 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {0a2eedaf-f4a8-41e0-a874-2f30d1eeb55e} + NetTunnelSvr + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + copy /y $(TargetDir)*.exe $(SolutionDir)\NetTunnelApp\bin\$(ConfigurationName)\ + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/NetTunnelSvr/NetTunnelSvr.vcxproj.filters b/NetTunnelSvr/NetTunnelSvr.vcxproj.filters new file mode 100644 index 0000000..7456f6c --- /dev/null +++ b/NetTunnelSvr/NetTunnelSvr.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/NetTunnelSvr/NetTunnelSvr.vcxproj.user b/NetTunnelSvr/NetTunnelSvr.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/NetTunnelSvr/NetTunnelSvr.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/TestNetTunnelSDK/TestNetTunnelSDK.cpp b/TestNetTunnelSDK/TestNetTunnelSDK.cpp index cc89ec1..b371c1c 100644 --- a/TestNetTunnelSDK/TestNetTunnelSDK.cpp +++ b/TestNetTunnelSDK/TestNetTunnelSDK.cpp @@ -35,15 +35,7 @@ TEST_MODULE_CLEANUP(ModuleCleanup) { TEST_CLASS(TestNetTunnelSDK) { public: const int RET_OK = ERR_SUCCESS; - - TEST_METHOD(TestFindWireguardExe) { - Assert::AreEqual(RET_OK, FindWireguardExe(nullptr, 0)); - } - - TEST_METHOD(TestSetWireguardPath) { - Assert::AreEqual(RET_OK, SetWireguardPath(TEXT("C:\\Program Files\\WireGuard\\wireguard.exe"))); - } - + TEST_METHOD(TestRunPipeCmd) { #if 0 TCHAR buf[1024]; @@ -208,8 +200,12 @@ public: Assert::IsNotNull(pCfg); Assert::AreEqual(RET_OK, RemoteCtrlSvrCfgUserTunnel(2, TEXT("172.18.2.0/24"))); - + Assert::AreEqual(RET_OK, RemoteWireGuardControl(true)); Assert::AreEqual(RET_OK, LocalWireGuardControl(true, true)); + + + Assert::AreEqual(RET_OK, RemoteWireGuardControl(false)); + Assert::AreEqual(RET_OK, LocalWireGuardControl(false, false)); } }; } \ No newline at end of file diff --git a/tunnel_windows.sln b/tunnel_windows.sln index 75a6216..56abfaa 100644 --- a/tunnel_windows.sln +++ b/tunnel_windows.sln @@ -7,6 +7,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetTunnelSDK", "NetTunnelSD EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetTunnelApp", "NetTunnelApp\NetTunnelApp.csproj", "{79995848-FD05-46F5-A7FE-46265E540E32}" ProjectSection(ProjectDependencies) = postProject + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E} = {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E} {1584BAD4-DBEC-43D2-BC06-08C23F02489A} = {1584BAD4-DBEC-43D2-BC06-08C23F02489A} EndProjectSection EndProject @@ -22,6 +23,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetTunnelSDKTestApp", "NetT EndProject Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "InstallTunnelSDK", "InstallTunnelSDK\InstallTunnelSDK.vdproj", "{FE91D4D0-29A6-4C58-874F-11F6AC1D50CD}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetTunnelSvr", "NetTunnelSvr\NetTunnelSvr.vcxproj", "{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug DLL|Any CPU = Debug DLL|Any CPU @@ -152,6 +155,30 @@ Global {FE91D4D0-29A6-4C58-874F-11F6AC1D50CD}.Release|Any CPU.ActiveCfg = Release {FE91D4D0-29A6-4C58-874F-11F6AC1D50CD}.Release|x64.ActiveCfg = Release {FE91D4D0-29A6-4C58-874F-11F6AC1D50CD}.Release|x86.ActiveCfg = Release + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|Any CPU.ActiveCfg = Debug|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|Any CPU.Build.0 = Debug|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|x64.ActiveCfg = Debug|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|x64.Build.0 = Debug|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|x86.ActiveCfg = Debug|Win32 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|x86.Build.0 = Debug|Win32 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|Any CPU.ActiveCfg = Debug|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|Any CPU.Build.0 = Debug|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|x64.ActiveCfg = Debug|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|x64.Build.0 = Debug|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|x86.ActiveCfg = Debug|Win32 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|x86.Build.0 = Debug|Win32 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|Any CPU.ActiveCfg = Release|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|Any CPU.Build.0 = Release|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|x64.ActiveCfg = Release|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|x64.Build.0 = Release|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|x86.ActiveCfg = Release|Win32 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|x86.Build.0 = Release|Win32 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|Any CPU.ActiveCfg = Release|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|Any CPU.Build.0 = Release|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|x64.ActiveCfg = Release|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|x64.Build.0 = Release|x64 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|x86.ActiveCfg = Release|Win32 + {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE