Based on Nekogram. Key additions: - Rebrand to FoxiGram (app name, APK name, applicationId com.foxigram.app) - Embedded Xray (VLESS+Reality) proxy client via JNI libxray.so - Bundled hidden one-tap proxies (LTE + WiFi), read-only in UI - Auto-restore proxy on restart, rebind to active network (LTE/WiFi) - Server credentials externalized to git-ignored XrayServers.java (+ template) - libxray Go source included; compiled .so, keystore, google-services.json ignored
89 lines
3.3 KiB
C++
89 lines
3.3 KiB
C++
/*
|
|
* 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 <cstdint>
|
|
#include <string>
|
|
|
|
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
|