/* * IptController.h — Inter-Packet Timing obfuscation for tgnet * Ported from telemt/tdlib-obf (MIT License, Copyright 2026 telemt community) * Adapted for tgnet: C++17, no tdlib dependencies. * * IPT uses a two-state Markov model (Burst / Idle) to add randomised delays * between TLS records, mimicking the inter-packet timing of interactive * browser sessions and defeating timing-based DPI correlation attacks. * * Burst state: lognormal delays (µ=3.5ms, σ=0.8), capped at 200ms * Idle state: heavy-tail Pareto gaps (α=1.5, scale=500ms, max=3s) * * Bypass (zero delay) for: BulkData, Keepalive, AuthHandshake */ #ifndef IPT_CONTROLLER_H #define IPT_CONTROLLER_H #include #include "DrsEngine.h" // for TrafficHint namespace stealth { struct IptParams { double burst_mu_ms{3.5}; double burst_sigma{0.8}; double burst_max_ms{200.0}; double idle_alpha{1.5}; double idle_scale_ms{500.0}; double idle_max_ms{3000.0}; // Markov transition probabilities double p_burst_stay{0.95}; // P(stay Burst | was Burst) double p_idle_to_burst{0.30}; // P(go Burst | was Idle) }; class IptController { public: explicit IptController(const IptParams ¶ms = IptParams{}); // Returns delay in microseconds before the next record should be sent. // has_pending_data: true if outgoing buffer is non-empty after this send. // hint: traffic type — BulkData/Keepalive/AuthHandshake bypass IPT (return 0). uint64_t next_delay_us(bool has_pending_data, TrafficHint hint = TrafficHint::Interactive); // Sample an idle gap delay — used by ChaffScheduler. uint64_t sample_idle_delay_us(); private: enum class State : uint8_t { Idle = 0, Burst = 1 }; static bool is_bypass(TrafficHint hint); State transition(bool has_pending_data); double sample_uniform01(); double sample_normal(); double sample_lognormal(double mu, double sigma); double sample_pareto(double u, double alpha, double scale, double max_val) const; IptParams params_; State state_{State::Idle}; bool has_spare_normal_{false}; double spare_normal_{0.0}; }; } // namespace stealth #endif // IPT_CONTROLLER_H