Test 1: Make WinTun work

This commit is contained in:
2025-12-17 18:34:07 +01:00
parent 5e3aef78a5
commit c047cb90f0
3 changed files with 75 additions and 33 deletions

View File

@@ -80,15 +80,6 @@ FetchContent_MakeAvailable(Sodium)
FetchContent_MakeAvailable(asio) FetchContent_MakeAvailable(asio)
FetchContent_MakeAvailable(cxxopts) FetchContent_MakeAvailable(cxxopts)
# OpenSSL
find_package(OpenSSL REQUIRED)
if(OPENSSL_FOUND)
message(STATUS "Found OpenSSL version ${OPENSSL_VERSION}")
include_directories(${OPENSSL_INCLUDE_DIR})
else()
message(FATAL_ERROR "OpenSSL not found")
endif()
# --------------------------------------------------------- # ---------------------------------------------------------
# Output directories # Output directories
# --------------------------------------------------------- # ---------------------------------------------------------
@@ -108,7 +99,7 @@ endforeach()
# --------------------------------------------------------- # ---------------------------------------------------------
file(GLOB_RECURSE COMMON_SRC CONFIGURE_DEPENDS src/common/*.cpp) file(GLOB_RECURSE COMMON_SRC CONFIGURE_DEPENDS src/common/*.cpp)
add_library(common STATIC ${COMMON_SRC}) add_library(common STATIC ${COMMON_SRC})
target_link_libraries(common PUBLIC sodium OpenSSL::SSL OpenSSL::Crypto cxxopts::cxxopts) target_link_libraries(common PUBLIC sodium cxxopts::cxxopts)
target_include_directories(common PUBLIC target_include_directories(common PUBLIC
${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include
${sodium_SOURCE_DIR}/src/libsodium/include ${sodium_SOURCE_DIR}/src/libsodium/include
@@ -122,7 +113,7 @@ target_compile_definitions(common PUBLIC ASIO_STANDALONE)
# --------------------------------------------------------- # ---------------------------------------------------------
file(GLOB_RECURSE CLIENT_SRC CONFIGURE_DEPENDS src/client/*.cpp) file(GLOB_RECURSE CLIENT_SRC CONFIGURE_DEPENDS src/client/*.cpp)
add_executable(client ${CLIENT_SRC}) add_executable(client ${CLIENT_SRC})
target_link_libraries(client PRIVATE common sodium OpenSSL::SSL OpenSSL::Crypto cxxopts::cxxopts) target_link_libraries(client PRIVATE common sodium cxxopts::cxxopts)
target_include_directories(client PRIVATE target_include_directories(client PRIVATE
${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include
${sodium_SOURCE_DIR}/src/libsodium/include ${sodium_SOURCE_DIR}/src/libsodium/include
@@ -137,7 +128,7 @@ set_target_properties(client PROPERTIES OUTPUT_NAME "columnlynx_client")
# --------------------------------------------------------- # ---------------------------------------------------------
file(GLOB_RECURSE SERVER_SRC CONFIGURE_DEPENDS src/server/*.cpp) file(GLOB_RECURSE SERVER_SRC CONFIGURE_DEPENDS src/server/*.cpp)
add_executable(server ${SERVER_SRC}) add_executable(server ${SERVER_SRC})
target_link_libraries(server PRIVATE common sodium OpenSSL::SSL OpenSSL::Crypto cxxopts::cxxopts) target_link_libraries(server PRIVATE common sodium cxxopts::cxxopts)
target_include_directories(server PRIVATE target_include_directories(server PRIVATE
${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include
${sodium_SOURCE_DIR}/src/libsodium/include ${sodium_SOURCE_DIR}/src/libsodium/include

View File

@@ -28,11 +28,11 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/poll.h> #include <sys/poll.h>
#elif defined(_WIN32) #elif defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <ws2tcpip.h>
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h>
#include <wintun/wintun.h> #include <wintun/wintun.h>
#pragma comment(lib, "advapi32.lib")
#endif #endif
namespace ColumnLynx::Net { namespace ColumnLynx::Net {
@@ -127,7 +127,9 @@ namespace ColumnLynx::Net {
std::string mIfName; std::string mIfName;
int mFd; // POSIX int mFd; // POSIX
#if defined(_WIN32) #if defined(_WIN32)
HANDLE mHandle; // Windows WINTUN_ADAPTER_HANDLE mAdapter = nullptr;
WINTUN_SESSION_HANDLE mSession = nullptr;
HANDLE mHandle = nullptr;
#endif #endif
}; };
} }

View File

@@ -6,6 +6,47 @@
// This is all fucking voodoo dark magic. // This is all fucking voodoo dark magic.
#if defined(_WIN32)
static HMODULE gWintun = nullptr;
static WintunOpenAdapterFn WintunOpenAdapter;
static WintunStartSessionFn WintunStartSession;
static WintunEndSessionFn WintunEndSession;
static WintunGetReadWaitEventFn WintunGetReadWaitEvent;
static WintunReceivePacketFn WintunReceivePacket;
static WintunReleaseReceivePacketFn WintunReleaseReceivePacket;
static WintunAllocateSendPacketFn WintunAllocateSendPacket;
static WintunSendPacketFn WintunSendPacket;
static void InitializeWintun()
{
if (gWintun)
return;
gWintun = LoadLibraryExW(L"wintun.dll", nullptr,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
if (!gWintun)
throw std::runtime_error("Failed to load wintun.dll");
#define RESOLVE(name) \
name = (name##Fn)GetProcAddress(gWintun, #name); \
if (!name) throw std::runtime_error("Missing Wintun symbol: " #name);
RESOLVE(WintunOpenAdapter)
RESOLVE(WintunStartSession)
RESOLVE(WintunEndSession)
RESOLVE(WintunGetReadWaitEvent)
RESOLVE(WintunReceivePacket)
RESOLVE(WintunReleaseReceivePacket)
RESOLVE(WintunAllocateSendPacket)
RESOLVE(WintunSendPacket)
#undef RESOLVE
}
#endif // _WIN32
namespace ColumnLynx::Net { namespace ColumnLynx::Net {
// ------------------------------ Constructor ------------------------------ // ------------------------------ Constructor ------------------------------
VirtualInterface::VirtualInterface(const std::string& ifName) VirtualInterface::VirtualInterface(const std::string& ifName)
@@ -63,20 +104,23 @@ namespace ColumnLynx::Net {
Utils::log("VirtualInterface: opened macOS UTUN: " + mIfName); Utils::log("VirtualInterface: opened macOS UTUN: " + mIfName);
#elif defined(_WIN32) #elif defined(_WIN32)
// ---- Windows: Wintun (WireGuard virtual adapter) ----
WINTUN_ADAPTER_HANDLE adapter =
WintunOpenAdapter(L"ColumnLynx", std::wstring(ifName.begin(), ifName.end()).c_str());
if (!adapter)
throw std::runtime_error("Wintun adapter not found or not installed");
WINTUN_SESSION_HANDLE session = InitializeWintun();
WintunStartSession(adapter, 0x200000); // ring buffer size
if (!session) mAdapter = WintunOpenAdapter(
L"ColumnLynx",
std::wstring(ifName.begin(), ifName.end()).c_str()
);
if (!mAdapter)
throw std::runtime_error("Wintun adapter not found");
mSession = WintunStartSession(mAdapter, 0x200000);
if (!mSession)
throw std::runtime_error("Failed to start Wintun session"); throw std::runtime_error("Failed to start Wintun session");
mHandle = WintunGetReadWaitEvent(session); mHandle = WintunGetReadWaitEvent(mSession);
mFd = -1; // not used on Windows mFd = -1;
mIfName = ifName;
#else #else
throw std::runtime_error("Unsupported platform"); throw std::runtime_error("Unsupported platform");
@@ -89,9 +133,8 @@ namespace ColumnLynx::Net {
if (mFd >= 0) if (mFd >= 0)
close(mFd); close(mFd);
#elif defined(_WIN32) #elif defined(_WIN32)
// Wintun sessions need explicit stop if (mSession)
// (assuming you stored the session handle as member) WintunEndSession(mSession);
// WintunEndSession(mSession);
#endif #endif
} }
@@ -158,9 +201,12 @@ namespace ColumnLynx::Net {
#elif defined(_WIN32) #elif defined(_WIN32)
WINTUN_PACKET* packet = WintunReceivePacket(mSession, nullptr); WINTUN_PACKET* packet = WintunReceivePacket(mSession, nullptr);
if (!packet) return {}; if (!packet)
return {};
std::vector<uint8_t> buf(packet->Data,
packet->Data + packet->Length);
std::vector<uint8_t> buf(packet->Data, packet->Data + packet->Length);
WintunReleaseReceivePacket(mSession, packet); WintunReleaseReceivePacket(mSession, packet);
return buf; return buf;
@@ -206,10 +252,13 @@ namespace ColumnLynx::Net {
#elif defined(_WIN32) #elif defined(_WIN32)
WINTUN_PACKET* tx = WintunAllocateSendPacket(mSession, (DWORD)packet.size()); WINTUN_PACKET* tx =
WintunAllocateSendPacket(mSession,
static_cast<DWORD>(packet.size()));
if (!tx) if (!tx)
throw std::runtime_error("WintunAllocateSendPacket failed"); throw std::runtime_error("WintunAllocateSendPacket failed");
memcpy(tx->Data, packet.data(), packet.size()); memcpy(tx->Data, packet.data(), packet.size());
WintunSendPacket(mSession, tx); WintunSendPacket(mSession, tx);