This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Дизайн протокола
English / Английский | ← Главная
Обзор
OSTP (Ospab Stealth Transport Protocol) — UDP-протокол зашифрованного туннелирования, разработанный для максимальной устойчивости к системам DPI и ТСПУ.
Принципы проектирования
- Принцип Керкгоффса — безопасность зависит исключительно от ключа доступа. Бинарник не содержит специфичных для протокола строк или магических констант.
- По-пакетная неразличимость — каждый байт на проводе криптографически случаен. Нет сигнатур хендшейка, полей версии или фиксированных паттернов.
- Всё выводится из ключа — маски обфускации, PSK и даже диапазон паддинга выводятся из ключа доступа через HKDF-SHA256.
Wire-формат
Пакет хендшейка
[session_id:4][noise_len:2][noise_payload:N][random_padding:var]
↑ XOR-маскирован ↑ Открытый текст (из него выводится маска)
- session_id (4 байта) — случайный идентификатор сессии, XOR-маскирован
- noise_len (2 байта) — длина Noise-полезной нагрузки, XOR-маскирован
- noise_payload (N байтов) — сообщение хендшейка Noise_NNpsk0
- random_padding (key-derived диапазон) — случайные байты против размерного фингерпринтинга
Пакет данных (после хендшейка)
[session_id:4][nonce:8][AEAD_ciphertext:N]
↑ XOR-маскирован ↑ XOR-маскирован ↑ ChaCha20-Poly1305
Вывод маски обфускации
Маска для 6-байтного заголовка хендшейка выводится из Noise-payload:
sample = packet[6..38] // Первые 32 байта payload
mask = HMAC-SHA256(obfuscation_key, sample)[0..6]
header ^= mask
Для пакетов данных маска выводится из шифротекста:
sample = packet[12..44] // Первые 32 байта шифротекста
mask = HMAC-SHA256(obfuscation_key, sample)[0..12]
header ^= mask
Вывод ключей
Все секреты выводятся из одного access_key через HKDF-SHA256 (RFC 5869):
key_hash = SHA-256(access_key)
salt = key_hash[0..16]
info = key_hash[16..32]
prk = HMAC-SHA256(salt, access_key)
obfuscation_key = HKDF-Expand(prk, info || 0x01, 8)
psk = HKDF-Expand(prk, info || 0x02, 32)
pad_params = HKDF-Expand(prk, info || 0x03, 2)
Диапазон паддинга:
pad_min = 16 + (pad_params[0] % 64)→ [16, 79]pad_max = pad_min + 48 + (pad_params[1] % 128)→ pad_min + [48, 175]
Разные ключи → разные размеры пакетов. Универсальный фильтр по размеру невозможен.
Noise-протокол
OSTP использует паттерн Noise_NNpsk0:
Noise_NNpsk0(psk):
→ psk, e
← e, ee
- NN — без статических ключей (анонимный)
- psk0 — pre-shared key внедряется на позиции 0
- Примитивы: X25519, ChaChaPoly, BLAKE2s
PSK выводится из ключа доступа — без валидного ключа хендшейк невозможен.
ARQ (Automatic Repeat Request)
| Параметр | По умолчанию | Описание |
|---|---|---|
max_reorder |
16384 | Максимальный разрыв между ожидаемым и полученным nonce |
reorder_buf |
8192 | Максимум буферизованных пакетов не по порядку |
rto |
100мс | Таймаут ретрансмиссии |
max_retries |
8 | Максимум попыток ретрансмиссии |
Анализ устойчивости к DPI
Что видит DPI-система
- Нет magic bytes — первые байты XOR-маскированы
- Нет фиксированных размеров — паддинг зависит от ключа
- Нет строк протокола в бинарнике — salt/info выводятся из хеша ключа
- Нет полей версии — весь заголовок замаскирован
- UDP-пакеты — неотличимы от QUIC, WireGuard или случайного UDP
Что остаётся идентифицируемым
- UDP-трафик на фиксированном порту (смягчается использованием 443, 8443)
- Анализ паттернов трафика (смягчается адаптивным паддингом)
- Строка Noise-паттерна в бинарнике — стандартная, используется тысячами проектов