/* * StealthTlsHello.h * Ported from telemt/tdlib-obf (MIT License, Copyright 2026 telemt community) * Adapted for tgnet — C++17, no tdlib dependencies, OpenSSL only. * * Replaces the single static TLS ClientHello in ConnectionSocket.cpp with * a multi-profile implementation that mimics real browser fingerprints * to evade DPI. Profiles: Chrome133, Chrome131, Chrome147_Win, * Firefox148, Firefox149, Safari26, iOS14, Android OkHttp. * * Usage (in ConnectionSocket.cpp, where getDefault() is called): * * // Replace: * TlsHello hello = TlsHello::getDefault(); * hello.setDomain(currentSecretDomain); * uint32_t size = hello.writeToBuffer(tempBuffer->bytes); * * // With: * uint32_t size = stealth::buildStealthTlsHello( * currentSecretDomain, * (const uint8_t*)currentSecret.data(), currentSecret.size(), * ConnectionsManager::getInstance(instanceNum).getCurrentTime(), * tempBuffer->bytes); */ #ifndef STEALTH_TLS_HELLO_H #define STEALTH_TLS_HELLO_H #include #include namespace stealth { // Browser profiles — ordered by Android relevance/weight enum class BrowserProfile : uint8_t { Chrome133 = 0, // weight 50 — primary Chrome131 = 1, // weight 20 Chrome120 = 2, // weight 15 Chrome147_Windows = 3, // weight 10 (desktop-ish, used on Android too) Chrome147_IOSChromium = 4, // weight 30 (mobile Chromium) Firefox148 = 5, // weight 15 Firefox149_Windows = 6, // weight 10 Safari26_3 = 7, // weight 5 (rare on Android, keep for diversity) IOS14 = 8, // weight 5 Android11_OkHttp = 9, // weight 30 — Android-native fingerprint COUNT = 10, }; // Build a TLS ClientHello mimicking the given browser profile. // // domain — SNI hostname extracted from proxy secret (e.g. "cloudflare.com") // secret — raw proxy secret bytes (used for HMAC key material, 16+ bytes) // secret_len — length of secret // unix_time — current unix timestamp (from ConnectionsManager::getCurrentTime) // profile — which browser to mimic // out — destination buffer; must be >= 8192 bytes (tempBuffer->bytes) // // Returns number of bytes written to out. uint32_t buildTlsHelloForProfile( const std::string &domain, const uint8_t *secret, size_t secret_len, int32_t unix_time, BrowserProfile profile, uint8_t *out); // Select a profile deterministically per (destination, time-bucket, per-run salt). // The same destination always picks the same profile within a 24h window, // but rotates daily — prevents long-term fingerprinting. BrowserProfile pickProfile( const std::string &destination, int32_t unix_time, uint32_t per_run_salt); // All-in-one: pick profile + build hello. // This is the main entry point to call from ConnectionSocket.cpp. // Returns number of bytes written. uint32_t buildStealthTlsHello( const std::string &domain, const uint8_t *secret, size_t secret_len, int32_t unix_time, uint8_t *out); // Call once at startup (e.g. in ConnectionsManager::init) to initialise // the per-run entropy salt used by pickProfile. void initStealthSalt(); } // namespace stealth #endif // STEALTH_TLS_HELLO_H