2 Protocol Design
ospab edited this page 2026-05-17 17:19:45 +03:00

Protocol Design

Crypto Transport DPI

Russian / Русский

Overview

OSTP (Obfuscated Secure Transport Protocol) is a UDP-based encrypted tunnel designed for maximum resistance to Deep Packet Inspection (DPI) and Traffic Shaping (TSPU) systems.

Design Principles

  1. Kerckhoffs's Principle — Security depends solely on the access key. The binary contains no protocol-specific strings or magic constants.
  2. Per-packet indistinguishability — Every byte on the wire is cryptographically random. No handshake signatures, version fields, or fixed patterns.
  3. Key-derived everything — Obfuscation masks, PSK, and even padding ranges are derived from the access key via HKDF-SHA256.

Wire Format

Handshake Packet

[session_id:4][noise_len:2][noise_payload:N][random_padding:var]
 ↑ XOR-masked                ↑ Cleartext (used to derive mask)
  • session_id (4 bytes) — Random per-session identifier, XOR-masked
  • noise_len (2 bytes) — Length of Noise payload, XOR-masked
  • noise_payload (N bytes) — Noise_NNpsk0 handshake message
  • random_padding (key-derived range) — Random bytes to prevent size fingerprinting

Data Packet (Post-Handshake)

[session_id:4][nonce:8][AEAD_ciphertext:N]
 ↑ XOR-masked   ↑ XOR-masked   ↑ ChaCha20-Poly1305 encrypted

Obfuscation Mask Derivation

The 6-byte header mask for handshake packets is derived from the Noise payload:

sample = packet[6..38]  // First 32 bytes of payload
mask   = HMAC-SHA256(obfuscation_key, sample)[0..6]
header ^= mask

For data packets, the mask is derived from the ciphertext:

sample = packet[12..44]  // First 32 bytes of ciphertext
mask   = HMAC-SHA256(obfuscation_key, sample)[0..12]
header ^= mask

Since the Noise ephemeral key is cryptographically random and the AEAD ciphertext is indistinguishable from random, the mask is unique per packet.

Key Derivation

All secrets are derived from a single access_key using 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)

The padding range is computed from pad_params:

  • pad_min = 16 + (pad_params[0] % 64) → range [16, 79]
  • pad_max = pad_min + 48 + (pad_params[1] % 128) → pad_min + [48, 175]

Different access keys produce different padding distributions, making universal size-based filters impossible.

Noise Protocol

OSTP uses the Noise_NNpsk0 pattern:

Noise_NNpsk0(psk):
  → psk, e
  ← e, ee
  • NN — No static keys (anonymous)
  • psk0 — Pre-shared key injected at position 0
  • Primitives: X25519, ChaChaPoly, BLAKE2s

The PSK is derived from the access key, preventing unauthorized parties from completing the handshake.

ARQ (Automatic Repeat Request)

OSTP includes a selective-acknowledgment ARQ layer over UDP:

Parameter Default Description
max_reorder 16384 Maximum gap between expected and received nonce
reorder_buf 8192 Maximum buffered out-of-order frames
rto 100ms Retransmission timeout
max_retries 8 Maximum retransmission attempts

DPI Resistance Analysis

What a DPI system sees

  • No magic bytes — First bytes are XOR-masked with key-derived randomness
  • No fixed packet sizes — Padding range varies per access key
  • No protocol strings in binary — HKDF salt/info derived from key hash
  • No version fields — Entire header is masked
  • UDP packets — Indistinguishable from QUIC, WireGuard, or random UDP traffic

What remains identifiable

  • UDP traffic on a fixed port — Mitigated by using common ports (443, 8443)
  • Traffic patterns — Mitigated by adaptive padding strategy
  • Noise pattern string in binary"Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s" is standard and shared by thousands of projects

← Configuration | Share Links →