Улучшить TLS-маскировку, ввести версионирование протокола, добавить тесты и нагрузочный инструмент
Маскировка: - ChangeCipherSpec middlebox-compat запись после ClientHello/ServerHello — без неё последовательность типов TLS-записей отличала нас от настоящего браузера даже при идеальном JA3/JA4-отпечатке. - SNI-aware stealth fallback: невалидный клиент проксируется на запрошенный им хост, а не всегда на один и тот же decoy — иначе активное зондирование с разными SNI на одном IP получало одинаковый ответ. Резолв только в публичные IP (защита от SSRF на внутреннюю сеть ноды через подставной SNI). - Профиль браузера привязан к session_id, а не к номеру попытки реконнекта: раньше при нескольких быстрых ретраях с одного IP летели ClientHello Chrome→Edge→Firefox подряд — сама по себе аномалия для DPI. - Бакетный паддинг Data/UdpData кадров вместо полного отсутствия паддинга; джиттер перед ServerHello вместо мгновенного детерминированного ответа. Версионирование: - PROTOCOL_VERSION в session_id ClientHello — сервер узнаёт версию клиента до отправки чего-либо и может включать версионно-зависимое поведение (сейчас — CCS) только для тех, кто его понимает. Позволяет катить будущие несовместимые изменения протокола без синхронного flag-day релиза. Тесты (core, было 0): - Round-trip тесты TLS-записей/hello-сообщений/кадров/кодека. - Полный цикл хендшейка с реальным выводом ключей на обеих сторонах. - Вся SSRF-защита (hostname/IP валидация, v4/v6). - Интеграционные тесты по настоящему TCP: легитимный хендшейк и stealth-fallback на мусорный ClientHello. tools/loadtest — нагрузочный тест поверх настоящего скомпилированного netrunner-server (реальный процесс, метрики RSS/CPU из /proc) и настоящего публичного клиентского API. Попутно найден и обойдён гоночный баг: Connect-кадр в ClientHandler::connect() уходит через try_send ещё до того, как поднимется хоть одна нога тунеля, и молча теряется при синтетической нагрузке. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -32,9 +32,11 @@
|
||||
//! - **Stream ID** — id логического потока внутри туннеля (нечётные у клиента,
|
||||
//! чётные у сервера — так стороны не конфликтуют за номера).
|
||||
//! - **Type** — [`FrameType`]: `Connect`/`Data`/`Close`/`Heartbeat`/`UdpConnect`/`UdpData`.
|
||||
//! - **Padding** — случайные байты переменной длины: ломают анализ длин пакетов.
|
||||
//! Добавляется только к управляющим кадрам; кадры `Data`/`UdpData` не паддятся
|
||||
//! (их и так много, паддинг бил бы по throughput).
|
||||
//! - **Padding** — ломает анализ длин пакетов. Управляющие кадры получают
|
||||
//! 0..255 случайных байт; `Data`/`UdpData` выравниваются до ближайшего
|
||||
//! "круглого" бакета (256/512/1024/2048/4096/8192, см. `Frame::into_bytes`)
|
||||
//! — кроме кадров, уже близких к максимальному размеру (крупные закачки),
|
||||
//! где паддинг только бил бы по throughput без выигрыша в приватности.
|
||||
//!
|
||||
//! ## Конвейер кодирования
|
||||
//!
|
||||
|
||||
Reference in New Issue
Block a user