Added a basic TUN, testing the implementation.
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <columnlynx/common/net/protocol_structs.hpp>
|
||||
#include <columnlynx/common/net/virtual_interface.hpp>
|
||||
|
||||
using asio::ip::tcp;
|
||||
|
||||
@@ -25,7 +27,8 @@ namespace ColumnLynx::Net::TCP {
|
||||
Utils::LibSodiumWrapper* sodiumWrapper,
|
||||
std::array<uint8_t, 32>* aesKey,
|
||||
uint64_t* sessionIDRef,
|
||||
bool* insecureMode)
|
||||
bool* insecureMode,
|
||||
VirtualInterface* tun = nullptr)
|
||||
:
|
||||
mResolver(ioContext),
|
||||
mSocket(ioContext),
|
||||
@@ -70,5 +73,7 @@ namespace ColumnLynx::Net::TCP {
|
||||
std::chrono::steady_clock::time_point mLastHeartbeatSent;
|
||||
int mMissedHeartbeats = 0;
|
||||
bool mIsHostDomain;
|
||||
Protocol::TunConfig mTunConfig;
|
||||
VirtualInterface* mTun = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <columnlynx/common/utils.hpp>
|
||||
#include <columnlynx/common/libsodium_wrapper.hpp>
|
||||
#include <array>
|
||||
#include <columnlynx/common/net/virtual_interface.hpp>
|
||||
|
||||
namespace ColumnLynx::Net::UDP {
|
||||
class UDPClient {
|
||||
@@ -17,8 +18,9 @@ namespace ColumnLynx::Net::UDP {
|
||||
const std::string& host,
|
||||
const std::string& port,
|
||||
std::array<uint8_t, 32>* aesKeyRef,
|
||||
uint64_t* sessionIDRef)
|
||||
: mSocket(ioContext), mResolver(ioContext), mHost(host), mPort(port), mAesKeyRef(aesKeyRef), mSessionIDRef(sessionIDRef) { mStartReceive(); }
|
||||
uint64_t* sessionIDRef,
|
||||
VirtualInterface* tunRef = nullptr)
|
||||
: mSocket(ioContext), mResolver(ioContext), mHost(host), mPort(port), mAesKeyRef(aesKeyRef), mSessionIDRef(sessionIDRef), mTunRef(tunRef) { mStartReceive(); }
|
||||
|
||||
void start();
|
||||
void sendMessage(const std::string& data = "");
|
||||
@@ -35,6 +37,7 @@ namespace ColumnLynx::Net::UDP {
|
||||
std::string mPort;
|
||||
std::array<uint8_t, 32>* mAesKeyRef;
|
||||
uint64_t* mSessionIDRef;
|
||||
VirtualInterface* mTunRef;
|
||||
std::array<uint8_t, 2048> mRecvBuffer; // Adjust size as needed
|
||||
};
|
||||
}
|
||||
21
include/columnlynx/common/net/protocol_structs.hpp
Normal file
21
include/columnlynx/common/net/protocol_structs.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// protocol_structs.hpp - Network Protocol Structures
|
||||
// Copyright (C) 2025 DcruBro
|
||||
// Distributed under the terms of the GNU General Public License, either version 2 only or version 3. See LICENSES/ for details.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ColumnLynx::Protocol {
|
||||
#pragma pack(push, 1)
|
||||
struct TunConfig {
|
||||
uint8_t version;
|
||||
uint8_t prefixLength;
|
||||
uint16_t mtu;
|
||||
uint32_t serverIP;
|
||||
uint32_t clientIP;
|
||||
uint32_t dns1;
|
||||
uint32_t dns2;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
||||
@@ -21,6 +21,9 @@ namespace ColumnLynx::Net {
|
||||
std::atomic<uint64_t> sendCounter{0};
|
||||
std::chrono::steady_clock::time_point created = std::chrono::steady_clock::now();
|
||||
std::chrono::steady_clock::time_point expires{};
|
||||
uint32_t clientTunIP;
|
||||
uint32_t serverTunIP;
|
||||
uint64_t sessionID;
|
||||
Nonce base_nonce{};
|
||||
|
||||
~SessionState() { sodium_memzero(aesKey.data(), aesKey.size()); }
|
||||
@@ -29,7 +32,7 @@ namespace ColumnLynx::Net {
|
||||
SessionState(SessionState&&) = default;
|
||||
SessionState& operator=(SessionState&&) = default;
|
||||
|
||||
explicit SessionState(const SymmetricKey& k, std::chrono::seconds ttl = std::chrono::hours(24)) : aesKey(k) {
|
||||
explicit SessionState(const SymmetricKey& k, std::chrono::seconds ttl = std::chrono::hours(24), uint32_t clientIP = 0, uint32_t serverIP = 0, uint64_t id = 0) : aesKey(k), clientTunIP(clientIP), serverTunIP(serverIP), sessionID(id) {
|
||||
expires = created + ttl;
|
||||
}
|
||||
|
||||
@@ -46,6 +49,7 @@ namespace ColumnLynx::Net {
|
||||
void put(uint64_t sessionID, std::shared_ptr<SessionState> state) {
|
||||
std::unique_lock lock(mMutex);
|
||||
mSessions[sessionID] = std::move(state);
|
||||
mIPSessions[mSessions[sessionID]->clientTunIP] = mSessions[sessionID];
|
||||
}
|
||||
|
||||
// Lookup
|
||||
@@ -55,6 +59,12 @@ namespace ColumnLynx::Net {
|
||||
return (it == mSessions.end()) ? nullptr : it->second;
|
||||
}
|
||||
|
||||
std::shared_ptr<const SessionState> getByIP(uint32_t ip) const {
|
||||
std::shared_lock lock(mMutex);
|
||||
auto it = mIPSessions.find(ip);
|
||||
return (it == mIPSessions.end()) ? nullptr : it->second;
|
||||
}
|
||||
|
||||
std::unordered_map<uint64_t, std::shared_ptr<SessionState>> snapshot() const {
|
||||
std::unordered_map<uint64_t, std::shared_ptr<SessionState>> snap;
|
||||
std::shared_lock lock(mMutex);
|
||||
@@ -79,10 +89,50 @@ namespace ColumnLynx::Net {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = mIPSessions.begin(); it != mIPSessions.end(); ) {
|
||||
if (it->second && it->second->expires <= now) {
|
||||
it = mIPSessions.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size() const {
|
||||
std::shared_lock lock(mMutex);
|
||||
return static_cast<int>(mSessions.size());
|
||||
}
|
||||
|
||||
// IP management (simple for /24 subnet)
|
||||
|
||||
uint32_t getFirstAvailableIP() const {
|
||||
std::shared_lock lock(mMutex);
|
||||
uint32_t baseIP = 0x0A0A0002; // 10.10.0.2
|
||||
|
||||
// TODO: Expand to support larger subnets
|
||||
for (uint32_t offset = 0; offset < 254; offset++) {
|
||||
uint32_t candidateIP = baseIP + offset;
|
||||
if (mSessionIPs.find(candidateIP) == mSessionIPs.end()) {
|
||||
return candidateIP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lockIP(uint64_t sessionID, uint32_t ip) {
|
||||
std::unique_lock lock(mMutex);
|
||||
mSessionIPs[sessionID] = ip;
|
||||
}
|
||||
|
||||
void deallocIP(uint64_t sessionID) {
|
||||
std::unique_lock lock(mMutex);
|
||||
mSessionIPs.erase(sessionID);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::shared_mutex mMutex;
|
||||
std::unordered_map<uint64_t, std::shared_ptr<SessionState>> mSessions;
|
||||
std::unordered_map<uint64_t, uint32_t> mSessionIPs;
|
||||
std::unordered_map<uint32_t, std::shared_ptr<SessionState>> mIPSessions;
|
||||
};
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <arpa/inet.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <sys/socket.h>
|
||||
#include <sys/kern_control.h>
|
||||
@@ -24,8 +25,11 @@
|
||||
#include <net/if_utun.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
#include <wintun/wintun.h>
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#endif
|
||||
@@ -36,12 +40,31 @@ namespace ColumnLynx::Net {
|
||||
explicit VirtualInterface(const std::string& ifName);
|
||||
~VirtualInterface();
|
||||
|
||||
bool configureIP(uint32_t clientIP, uint32_t serverIP,
|
||||
uint8_t prefixLen, uint16_t mtu);
|
||||
|
||||
std::vector<uint8_t> readPacket();
|
||||
void writePacket(const std::vector<uint8_t>& packet);
|
||||
|
||||
const std::string& getName() const;
|
||||
int getFd() const; // for ASIO integration (on POSIX)
|
||||
int getFd() const; // For ASIO integration (on POSIX)
|
||||
|
||||
static inline std::string ipToString(uint32_t ip) {
|
||||
struct in_addr addr;
|
||||
addr.s_addr = ip; // expected in network byte order
|
||||
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
if (!inet_ntop(AF_INET, &addr, buf, sizeof(buf)))
|
||||
return "0.0.0.0";
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
private:
|
||||
bool mApplyLinuxIP(uint32_t clientIP, uint32_t serverIP, uint8_t prefixLen, uint16_t mtu);
|
||||
bool mApplyMacOSIP(uint32_t clientIP, uint32_t serverIP, uint8_t prefixLen, uint16_t mtu);
|
||||
bool mApplyWindowsIP(uint32_t clientIP, uint32_t serverIP, uint8_t prefixLen, uint16_t mtu);
|
||||
|
||||
std::string mIfName;
|
||||
int mFd; // POSIX
|
||||
#if defined(_WIN32)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <columnlynx/common/utils.hpp>
|
||||
#include <columnlynx/common/libsodium_wrapper.hpp>
|
||||
#include <columnlynx/common/net/session_registry.hpp>
|
||||
#include <columnlynx/common/net/protocol_structs.hpp>
|
||||
|
||||
namespace ColumnLynx::Net::TCP {
|
||||
class TCPConnection : public std::enable_shared_from_this<TCPConnection> {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <columnlynx/common/utils.hpp>
|
||||
#include <columnlynx/server/net/tcp/tcp_connection.hpp>
|
||||
#include <columnlynx/common/libsodium_wrapper.hpp>
|
||||
#include <columnlynx/common/net/protocol_structs.hpp>
|
||||
|
||||
namespace ColumnLynx::Net::TCP {
|
||||
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
#include <columnlynx/common/net/udp/udp_message_type.hpp>
|
||||
#include <columnlynx/common/utils.hpp>
|
||||
#include <array>
|
||||
#include <columnlynx/common/net/virtual_interface.hpp>
|
||||
|
||||
namespace ColumnLynx::Net::UDP {
|
||||
class UDPServer {
|
||||
public:
|
||||
UDPServer(asio::io_context& ioContext, uint16_t port, bool* hostRunning, bool ipv4Only = false)
|
||||
: mSocket(ioContext), mHostRunning(hostRunning)
|
||||
UDPServer(asio::io_context& ioContext, uint16_t port, bool* hostRunning, bool ipv4Only = false, VirtualInterface* tun = nullptr)
|
||||
: mSocket(ioContext), mHostRunning(hostRunning), mTun(tun)
|
||||
{
|
||||
asio::error_code ec;
|
||||
|
||||
@@ -43,13 +44,15 @@ namespace ColumnLynx::Net::UDP {
|
||||
|
||||
void stop();
|
||||
|
||||
void sendData(const uint64_t sessionID, const std::string& data);
|
||||
|
||||
private:
|
||||
void mStartReceive();
|
||||
void mHandlePacket(std::size_t bytes);
|
||||
void mSendData(const uint64_t sessionID, const std::string& data);
|
||||
asio::ip::udp::socket mSocket;
|
||||
asio::ip::udp::endpoint mRemoteEndpoint;
|
||||
std::array<uint8_t, 2048> mRecvBuffer; // Adjust size as needed
|
||||
bool* mHostRunning;
|
||||
VirtualInterface* mTun;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user