NetTunnelWindows/NetTunnelSDKTestApp/WireGurad.cpp

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;
}