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