718 lines
24 KiB
C++
718 lines
24 KiB
C++
/* SPDX-License-Identifier: GPL-2.0
|
|
*
|
|
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
|
*/
|
|
|
|
#include <winsock2.h>
|
|
#include <Windows.h>
|
|
#include <ws2ipdef.h>
|
|
#include <ws2tcpip.h>
|
|
#include <iphlpapi.h>
|
|
#include <bcrypt.h>
|
|
#include <wincrypt.h>
|
|
#include <sysinfoapi.h>
|
|
#include <winternl.h>
|
|
#include <stdio.h>
|
|
#include <wbemcli.h>
|
|
#include "wireguard.h"
|
|
#include "common.h"
|
|
#include "tunnel.h"
|
|
#include "network.h"
|
|
|
|
#include <strsafe.h>
|
|
#include <spdlog/spdlog.h>
|
|
|
|
#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<std::codecvt_utf8_utf16<wchar_t>, 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<UINT16>(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_FLAG>(
|
|
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;
|
|
} |