TESTING: protocol version 2

This commit is contained in:
2026-02-10 13:27:15 +01:00
parent 316498c745
commit 14298453b3
15 changed files with 110 additions and 74 deletions

View File

@@ -17,7 +17,10 @@ namespace ColumnLynx {
bool insecureMode;
std::string configPath;
std::shared_ptr<Net::VirtualInterface> virtualInterface;
uint64_t sessionID;
uint32_t sessionID;
uint64_t recv_cnt;
uint64_t send_cnt;
uint32_t noncePrefix;
~ClientState() { sodium_memzero(aesKey.data(), aesKey.size()); }
ClientState(const ClientState&) = delete;
@@ -28,8 +31,8 @@ namespace ColumnLynx {
explicit ClientState() = default;
explicit ClientState(std::shared_ptr<Utils::LibSodiumWrapper> sodium, SymmetricKey& k, bool insecure,
std::string& config, std::shared_ptr<Net::VirtualInterface> tun, uint64_t session)
: sodiumWrapper(sodium), aesKey(k), insecureMode(insecure), configPath(config), virtualInterface(tun), sessionID(session) {}
std::string& config, std::shared_ptr<Net::VirtualInterface> tun, uint32_t session, uint64_t recv, uint64_t send)
: sodiumWrapper(sodium), aesKey(k), insecureMode(insecure), configPath(config), virtualInterface(tun), sessionID(session), recv_cnt(recv), send_cnt(send) {}
};
class ClientSession {
@@ -54,7 +57,21 @@ namespace ColumnLynx {
// Get the virtual interface
const std::shared_ptr<Net::VirtualInterface>& getVirtualInterface() const;
// Get the session ID
uint64_t getSessionID() const;
uint32_t getSessionID() const;
uint64_t getRecvCount() const {
std::shared_lock lock(mMutex);
return mClientState->recv_cnt;
}
uint64_t getSendCount() const {
std::shared_lock lock(mMutex);
return mClientState->send_cnt;
}
uint32_t getNoncePrefix() const {
std::shared_lock lock(mMutex);
return mClientState->noncePrefix;
}
// Setters
void setSodiumWrapper(std::shared_ptr<Utils::LibSodiumWrapper> sodiumWrapper);
@@ -62,7 +79,21 @@ namespace ColumnLynx {
void setInsecureMode(bool insecureMode);
void setConfigPath(const std::string& configPath);
void setVirtualInterface(std::shared_ptr<Net::VirtualInterface> virtualInterface);
void setSessionID(uint64_t sessionID);
void setSessionID(uint32_t sessionID);
void incrementRecvCount() {
std::unique_lock lock(mMutex);
mClientState->recv_cnt++;
}
void incrementSendCount() {
std::unique_lock lock(mMutex);
mClientState->send_cnt++;
}
void setNoncePrefix(uint32_t prefix) {
std::unique_lock lock(mMutex);
mClientState->noncePrefix = prefix;
}
private:
mutable std::shared_mutex mMutex;

View File

@@ -97,7 +97,7 @@ namespace ColumnLynx::Net::TCP {
std::string mHost, mPort;
uint8_t mServerPublicKey[32]; // Assuming 256-bit public key
std::array<uint8_t, 32> mSubmittedChallenge{};
uint64_t mConnectionSessionID;
uint32_t mConnectionSessionID;
SymmetricKey mConnectionAESKey;
asio::steady_timer mHeartbeatTimer;
std::chrono::steady_clock::time_point mLastHeartbeatReceived;

View File

@@ -27,8 +27,9 @@ namespace ColumnLynx::Net {
std::chrono::steady_clock::time_point expires{}; // Time of expiry
uint32_t clientTunIP; // Assigned IP
uint32_t serverTunIP; // Server IP
uint64_t sessionID; // Session ID
uint32_t sessionID; // Session ID
Nonce base_nonce{};
uint32_t noncePrefix;
~SessionState() { sodium_memzero(aesKey.data(), aesKey.size()); }
SessionState(const SessionState&) = delete;
@@ -36,7 +37,7 @@ namespace ColumnLynx::Net {
SessionState(SessionState&&) = default;
SessionState& operator=(SessionState&&) = default;
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) {
explicit SessionState(const SymmetricKey& k, std::chrono::seconds ttl = std::chrono::hours(24), uint32_t clientIP = 0, uint32_t serverIP = 0, uint32_t id = 0) : aesKey(k), clientTunIP(clientIP), serverTunIP(serverIP), sessionID(id) {
expires = created + ttl;
}
@@ -44,6 +45,11 @@ namespace ColumnLynx::Net {
void setUDPEndpoint(const asio::ip::udp::endpoint& ep) {
udpEndpoint = ep;
}
void setBaseNonce() {
Utils::debug("Generating random base nonce for session " + std::to_string(sessionID));
randombytes_buf(base_nonce.data(), base_nonce.size());
}
};
class SessionRegistry {
@@ -52,19 +58,19 @@ namespace ColumnLynx::Net {
static SessionRegistry& getInstance() { static SessionRegistry instance; return instance; }
// Insert or replace a session entry
void put(uint64_t sessionID, std::shared_ptr<SessionState> state);
void put(uint32_t sessionID, std::shared_ptr<SessionState> state);
// Lookup a session entry by session ID
std::shared_ptr<const SessionState> get(uint64_t sessionID) const;
std::shared_ptr<const SessionState> get(uint32_t sessionID) const;
// Lookup a session entry by IPv4
std::shared_ptr<const SessionState> getByIP(uint32_t ip) const;
// Get a snapshot of the Session Registry
std::unordered_map<uint64_t, std::shared_ptr<SessionState>> snapshot() const;
std::unordered_map<uint32_t, std::shared_ptr<SessionState>> snapshot() const;
// Remove a session by ID
void erase(uint64_t sessionID);
void erase(uint32_t sessionID);
// Cleanup expired sessions
void cleanupExpired();
@@ -78,15 +84,15 @@ namespace ColumnLynx::Net {
uint32_t getFirstAvailableIP(uint32_t baseIP, uint8_t mask) const;
// Lock IP to session ID; Do NOT call before put() - You will segfault!
void lockIP(uint64_t sessionID, uint32_t ip);
void lockIP(uint32_t sessionID, uint32_t ip);
// Unlock IP from session ID
void deallocIP(uint64_t sessionID);
void deallocIP(uint32_t 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>> mSessions;
std::unordered_map<uint32_t, uint32_t> mSessionIPs;
std::unordered_map<uint32_t, std::shared_ptr<SessionState>> mIPSessions;
};
}

View File

@@ -65,27 +65,6 @@ namespace ColumnLynx::Utils {
return std::string(reinterpret_cast<const char*>(data), length);
}
inline constexpr uint64_t cbswap64(uint64_t x) {
return ((x & 0x00000000000000FFULL) << 56) |
((x & 0x000000000000FF00ULL) << 40) |
((x & 0x0000000000FF0000ULL) << 24) |
((x & 0x00000000FF000000ULL) << 8) |
((x & 0x000000FF00000000ULL) >> 8) |
((x & 0x0000FF0000000000ULL) >> 24) |
((x & 0x00FF000000000000ULL) >> 40) |
((x & 0xFF00000000000000ULL) >> 56);
}
// host -> big-endian (for little-endian hosts) - 64 bit
inline constexpr uint64_t chtobe64(uint64_t x) {
return cbswap64(x);
}
// big-endian -> host (for little-endian hosts) - 64 bit
inline constexpr uint64_t cbe64toh(uint64_t x) {
return cbswap64(x);
}
template <typename T>
T cbswap128(const T& x) {
static_assert(sizeof(T) == 16, "cbswap128 requires a 128-bit type");

View File

@@ -44,7 +44,7 @@ namespace ColumnLynx::Net::TCP {
void disconnect(bool echo = true);
// Get the assigned session ID
uint64_t getSessionID() const;
uint32_t getSessionID() const;
// Get the assigned AES key; You should probably access this via the Session Registry instead
std::array<uint8_t, 32> getAESKey() const;
@@ -65,7 +65,7 @@ namespace ColumnLynx::Net::TCP {
std::shared_ptr<MessageHandler> mHandler;
std::function<void(std::shared_ptr<TCPConnection>)> mOnDisconnect;
std::array<uint8_t, 32> mConnectionAESKey;
uint64_t mConnectionSessionID;
uint32_t mConnectionSessionID;
AsymPublicKey mConnectionPublicKey;
asio::steady_timer mHeartbeatTimer;
std::chrono::steady_clock::time_point mLastHeartbeatReceived;

View File

@@ -61,7 +61,7 @@ namespace ColumnLynx::Net::UDP {
void stop();
// Send UDP data to an endpoint; Fetched via the Session Registry
void sendData(const uint64_t sessionID, const std::string& data);
void sendData(uint32_t sessionID, const std::string& data);
private:
// Start receiving UDP data