rfc(0015): Pluggable Transport Skins for DPI resistance

- RFC-0015: Complete specification for censorship-resistant L0
- Transport Skins: RAW, MIMIC_HTTPS, MIMIC_DNS, MIMIC_VIDEO, STEGO
- Polymorphic Noise Generator (PNG): Per-session traffic shaping
- Anti-fingerprinting: TLS JA3 parroting, ECH, DoH tunneling
- Gherkin BDD: 50+ scenarios for TDD implementation

Targets: GFW, RKN, Iran/Turkmenistan edge cases
Kenya compliant: Embedded-only, no cloud calls

Features:
- transport_skins.feature: Skin selection, probing, defense
- polymorphic_noise.feature: PNG determinism, distributions

Next: Sprint 5 implementation (MIMIC_HTTPS + PNG core)
This commit is contained in:
Markus Maiwald 2026-02-03 17:17:52 +01:00
parent 65f9af6b5d
commit 03c6389063
3 changed files with 858 additions and 0 deletions

View File

@ -0,0 +1,393 @@
# RFC-0015: Pluggable Transport Skins (PTS)
**Status:** Draft
**Author:** Frankie (Silicon Architect)
**Date:** 2026-02-03
**Target:** Janus SDK L0 Transport Layer
**Classification:** CRYPTOGRAPHIC / CENSORSHIP-RESISTANT
---
## Summary
Transport Skins provide **pluggable censorship resistance** for Libertaria's L0 Transport layer. Each "skin" wraps the standard LWF (Lightweight Wire Format) frame to mimic benign traffic patterns, defeating state-level Deep Packet Inspection (DPI) as deployed by China's GFW, Russia's RKN, Iran's Filternet, and similar adversaries.
**Core Innovation:** Per-session **Polymorphic Noise Generator (PNG)** ensures no two sessions ever exhibit identical traffic patterns.
---
## Threat Model
### Adversary Capabilities (GFW-Class)
| Technique | Capability | Our Counter |
|-----------|------------|-------------|
| Magic Byte Detection | Signature matching at line rate | Skins remove/replace magic bytes |
| TLS Fingerprinting (JA3/JA4) | Statistical TLS handshake analysis | utls-style parroting (Chrome/Firefox mimicry) |
| SNI Inspection | Cleartext server name identification | ECH (Encrypted Client Hello) + Domain Fronting |
| Packet Size Analysis | Fixed MTU detection | Probabilistic size distributions |
| Timing Correlation | Inter-packet timing patterns | Exponential/Gamma jitter |
| Flow Correlation | Long-term traffic statistics | Epoch rotation (100-1000 packets) |
| Active Probing | Sending test traffic to suspected relays | Honeytrap responses + IP blacklisting |
| DNS Manipulation | Poisoning, blocking, inspection | DoH (DNS-over-HTTPS) tunneling |
### Non-Goals
- **Traffic confirmation attacks** (end-to-end correlation): Out of scope; use L2 Membrane mixing
- **Physical layer interception**: Out of scope; requires steganographic hardware
- **Compromised endpoints**: Out of scope; requires TEE/SEV-SNP attestation
---
## Architecture
```
┌─────────────────────────────────────────────────────────────────────────┐
│ RFC-0015: TRANSPORT SKINS │
│ "Submarine Camouflage" │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ L3+ Application │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ LWF FRAME │ │
│ │ • 1350 bytes (configurable) │ │
│ │ • XChaCha20-Poly1305 encrypted │ │
│ │ • Magic bytes: LWF\0 (internal only) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ POLYMORPHIC NOISE GENERATOR (PNG) │ │
│ │ • ECDH-derived per-session seed │ │
│ │ • Epoch-based profile rotation (100-1000 packets) │ │
│ │ • Deterministic both ends (same seed = same noise) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ SKIN SELECTOR │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────────┐ ┌───────────┐ ┌───────────┐ │ │
│ │ │ RAW │ │MIMIC_HTTPS │ │MIMIC_DNS │ │MIMIC_VIDEO│ │ │
│ │ │ UDP │ │WebSocket/TLS│ │DoH Tunnel │ │HLS chunks │ │ │
│ │ └────┬────┘ └──────┬──────┘ └─────┬─────┘ └─────┬─────┘ │ │
│ │ │ │ │ │ │ │
│ │ └──────────────┴───────────────┴──────────────┘ │ │
│ │ │ │ │
│ │ Auto-selection via probing │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ NETWORK (ISP/GFW/RKN sees only the skin's traffic pattern) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## Polymorphic Noise Generator (PNG)
### Design Principles
1. **Per-session uniqueness:** ECDH handshake secret seeds ChaCha20 RNG
2. **Deterministic:** Both peers derive identical noise from shared secret
3. **Epoch rotation:** Profile changes every N packets (prevents long-term analysis)
4. **Distribution matching:** Sample sizes/timing from real-world captures
### Noise Parameters (Per Epoch)
```zig
pub const EpochProfile = struct {
// Packet size distribution
size_distribution: enum { Normal, Pareto, Bimodal, LogNormal },
size_mean: u16, // e.g., 1440 bytes
size_stddev: u16, // e.g., 200 bytes
// Timing distribution
timing_distribution: enum { Exponential, Gamma, Pareto },
timing_lambda: f64, // For exponential: mean inter-packet time
// Dummy packet injection
dummy_probability: f64, // 0.0-0.15 (0-15% fake packets)
dummy_distribution: enum { Uniform, Bursty },
// Epoch boundaries
epoch_packet_count: u32, // 100-1000 packets before rotation
};
```
### Seed Derivation
```
Session Secret (ECDH) → HKDF-SHA256 → 256-bit PNG Seed
┌───────────────────────┐
│ ChaCha20 RNG State │
└───────────────────────┘
┌───────────────────────┐
│ Epoch Profile Chain │
│ (deterministic) │
└───────────────────────┘
```
---
## Transport Skins
### Skin 0: RAW (Unrestricted Networks)
**Use case:** Friendly jurisdictions, LAN, high-performance paths
| Property | Value |
|----------|-------|
| Protocol | UDP direct |
| Port | 7844 (default) |
| Overhead | 0% |
| Latency | Minimal |
| Kenya Viable | ✅ Yes |
**Wire format:**
```
[LWF Frame: 1350 bytes]
```
---
### Skin 1: MIMIC_HTTPS (Standard Censorship Bypass)
**Use case:** GFW, RKN, corporate firewalls (90% coverage)
| Property | Value |
|----------|-------|
| Protocol | WebSocket over TLS 1.3 |
| Port | 443 |
| SNI | Domain fronting capable (ECH preferred) |
| Overhead | ~5% (TLS + WS framing) |
| Latency | +50-100ms |
| Kenya Viable | ✅ Yes |
**TLS Fingerprinting Defense:**
- utls-style parroting (exact Chrome/Firefox JA3 signatures)
- HTTP/2 settings matching browser defaults
- ALPN: `h2, http/1.1`
**Wire format:**
```
TLS 1.3 Record Layer {
Content Type: Application Data (23)
TLS Ciphertext: {
WebSocket Frame {
FIN: 1
Opcode: Binary (0x02)
Masked: 0 (server→client) / 1 (client→server)
Payload: [PNG Noise] + [LWF Frame]
}
}
}
```
**WebSocket Handshake (Cover):**
```
GET /api/v3/stream HTTP/1.1
Host: cdn.cloudflare.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: <base64(random)>
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...
```
---
### Skin 2: MIMIC_DNS (Deep Censorship Bypass)
**Use case:** UDP blocked, HTTPS throttled, Iran/Turkmenistan edge cases
| Property | Value |
|----------|-------|
| Protocol | DNS-over-HTTPS (DoH) |
| Endpoint | 1.1.1.1, 8.8.8.8, 9.9.9.9 |
| Overhead | ~300% (Base64url encoding) |
| Latency | +200-500ms |
| Kenya Viable | ⚠️ Marginal (bandwidth-heavy) |
**DNS Tunnel Defenses:**
- **DoH not raw DNS:** Blends with real DoH traffic
- **Query distribution:** Match real DoH query timing (not regular intervals)
- **Label entropy:** Use dictionary words for subdomain labels (not base32)
**Wire format:**
```
POST /dns-query HTTP/2
Host: cloudflare-dns.com
Content-Type: application/dns-message
Accept: application/dns-message
Body: DNS Message {
Question: <LWF fragment encoded as DNS query name>
QTYPE: TXT (or HTTPS for larger payloads)
}
```
---
### Skin 3: MIMIC_VIDEO (High-Bandwidth Bypass)
**Use case:** Video-streaming-whitelisted networks, QoS prioritization
| Property | Value |
|----------|-------|
| Protocol | HTTPS with HLS (HTTP Live Streaming) chunk framing |
| Mimics | Netflix, YouTube, Twitch |
| Overhead | ~10% (HLS `.ts` container) |
| Latency | +100-200ms |
| Kenya Viable | ✅ Yes |
**Wire format:**
```
HTTP/2 200 OK
Content-Type: video/mp2t
X-LWF-Sequence: <epoch_packet_num>
Body: [HLS MPEG-TS Container] {
Adaptation Field: [PNG padding]
Payload: [LWF Frame]
}
```
---
### Skin 4: STEGO_IMAGE (Nuclear Option)
**Use case:** Total lockdown, emergency fallback only
| Property | Value |
|----------|-------|
| Protocol | HTTPS POST to image hosting (Imgur, etc.) |
| Stego Method | Generative steganography (StyleGAN encoding) |
| Bandwidth | ~1 byte per image (extremely slow) |
| Latency | Seconds to minutes |
| Kenya Viable | ❌ Emergency only |
**Note:** Traditional LSB steganography is broken against ML detection. Use generative encoding only.
---
## Automatic Skin Selection
### Probe Sequence
```zig
pub const SkinProbe = struct {
/// Attempt skin selection with timeouts
pub async fn auto_select(relay: RelayEndpoint) !TransportSkin {
// 1. RAW UDP (fastest, 100ms timeout)
if (try probe_raw(relay, 100ms)) {
return .raw;
}
// 2. HTTPS WebSocket (500ms timeout)
if (try probe_https(relay, 500ms)) {
return .mimic_https(relay);
}
// 3. DNS Tunnel (1s timeout)
if (try probe_dns(relay, 1s)) {
return .mimic_dns(relay);
}
// 4. Nuclear option (no probe, async only)
return .stego_async(relay);
}
};
```
### Multi-Path Agility (MPTCP-Style)
```zig
pub const MultiSkinSession = struct {
primary: TransportSkin, // 90% bandwidth (HTTPS)
secondary: TransportSkin, // 10% bandwidth (DNS keepalive)
/// If primary throttled, signal via secondary
pub fn adapt_to_throttling(self: *Self) void {
if (self.primary.detect_throttling()) {
self.secondary.signal_endpoint_switch();
}
}
};
```
---
## Active Probing Defenses
### Honeytrap Responses
When probed without valid session state:
1. **HTTPS Skin:** Respond as legitimate web server (nginx default page)
2. **DNS Skin:** Return NXDOMAIN or valid A record (not relay IP)
3. **Rate limit:** Exponential backoff on failed handshakes
### Reputation Tokens
Prevent rapid relay scanning:
```
Client → Relay: ClientHello + PoW (Argon2, 100ms)
Relay → Client: ServerHello (only if PoW valid)
```
---
## Implementation Phases
### Phase 1: Foundation (Sprint 5)
- [ ] PNG core (ChaCha20 RNG, epoch rotation)
- [ ] RAW skin (baseline)
- [ ] MIMIC_HTTPS skin (WebSocket + TLS)
- [ ] utls fingerprint parroting
- [ ] Automatic probe selection
### Phase 2: Deep Bypass (Sprint 6)
- [ ] MIMIC_DNS skin (DoH tunnel)
- [ ] ECH support (Encrypted Client Hello)
- [ ] Active probing defenses
- [ ] Multi-path agility
### Phase 3: Advanced (Sprint 7)
- [ ] MIMIC_VIDEO skin (HLS framing)
- [ ] Distribution matching from real captures
- [ ] Steganography (generative only)
- [ ] Formal security audit
---
## Kenya Compliance Check
| Skin | RAM | Binary Size | Cloud Calls | Viable? |
|------|-----|-------------|-------------|---------|
| RAW | <1MB | +0KB | None | |
| MIMIC_HTTPS | <2MB | +50KB (TLS) | None (embedded TLS) | |
| MIMIC_DNS | <1MB | +10KB | DoH to public resolver | |
| MIMIC_VIDEO | <2MB | +20KB (HLS) | None | |
| STEGO | >100MB | +500MB (ML models) | Image host upload | ❌ |
---
## Security Considerations
### TLS Fingerprinting (Critical)
**Risk:** Rustls default JA3 signature is trivially blockable.
**Mitigation:** Mandatory utls parroting; exact Chrome/Firefox match.
### DNS Tunnel Detectability (High)
**Risk:** Base32 subdomains have high entropy (4.8 vs 2.5 bits/char).
**Mitigation:** Use DoH to major providers; dictionary-word labels.
### Flow Correlation (Medium)
**Risk:** Long-term traffic statistics identify protocol.
**Mitigation:** PNG epoch rotation; per-session uniqueness.
---
## References
1. **utls:** [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) — TLS fingerprint parroting
2. **Snowflake:** [Tor Project](https://snowflake.torproject.org/) — WebRTC pluggable transport
3. **Conjure:** [refraction.network](https://refraction.network/) — Refraction networking
4. **ECH:** RFC 9446 — Encrypted Client Hello
5. **DoH:** RFC 8484 — DNS over HTTPS
---
*"The submarine wears chameleon skin. The hull remains the same."*
⚡️

View File

@ -0,0 +1,251 @@
Feature: RFC-0015 Polymorphic Noise Generator (PNG)
As a Libertaria protocol developer
I want cryptographically secure per-session traffic shaping
So that state-level DPI cannot fingerprint or correlate sessions
Background:
Given the PNG is initialized with ChaCha20 RNG
And the entropy source is the ECDH shared secret
# ============================================================================
# Seed Derivation and Determinism
# ============================================================================
Scenario: PNG seed derives from ECDH shared secret
Given Alice and Bob perform X25519 ECDH
And the shared secret is 32 bytes
When Alice derives PNG seed via HKDF-SHA256
And Bob derives PNG seed via HKDF-SHA256
Then both seeds should be 256 bits
And the seeds should be identical
And the derivation should use "Libertaria-PNG-v1" as context
Scenario: Different sessions produce different seeds
Given Alice and Bob perform ECDH for Session A
And Alice and Bob perform ECDH for Session B
When PNG seeds are derived for both sessions
Then the seeds should be different
And the Hamming distance should be ~128 bits
Scenario: PNG seed has sufficient entropy
Given 1000 independent ECDH handshakes
When PNG seeds are derived for all sessions
Then no seed collisions should occur
And the distribution should pass Chi-square randomness test
# ============================================================================
# Epoch Profile Generation
# ============================================================================
Scenario: Epoch profile contains all noise parameters
Given a PNG with valid seed
When the first epoch profile is generated
Then it should contain size_distribution variant
And size_mean and size_stddev parameters
And timing_distribution variant
And timing_lambda parameter
And dummy_probability between 0.0 and 0.15
And epoch_packet_count between 100 and 1000
Scenario: Sequential epochs are deterministic
Given a PNG with seed S
When epoch 0 profile is generated
And epoch 1 profile is generated
And a second PNG with same seed S
When epoch 0 and 1 profiles are generated again
Then all corresponding epochs should match exactly
Scenario: Different seeds produce uncorrelated epochs
Given PNG A with seed S1
And PNG B with seed S2
When 10 epochs are generated for both
Then size_mean of corresponding epochs should not correlate
And timing_lambda values should not correlate
And Kolmogorov-Smirnov test should show different distributions
# ============================================================================
# Packet Size Noise
# ============================================================================
Scenario Outline: Packet size distributions match theoretical models
Given the epoch profile specifies <distribution> distribution
And size_mean = <mean> bytes
And size_stddev = <stddev> bytes
When 10000 packet sizes are sampled
Then the empirical distribution should match theoretical <distribution>
And the Chi-square test p-value should be > 0.05
Examples:
| distribution | mean | stddev |
| Normal | 1440 | 200 |
| Pareto | 1440 | 400 |
| Bimodal | 1200 | 300 |
| LogNormal | 1500 | 250 |
Scenario: Packet sizes stay within valid bounds
Given any epoch profile
When packet sizes are sampled
Then all sizes should be >= 64 bytes
And all sizes should be <= 1500 bytes (Ethernet MTU)
And sizes should never exceed interface MTU
Scenario: Bimodal distribution matches video streaming
Given video streaming capture data
And epoch specifies Bimodal distribution
When PNG samples packet sizes
Then the two modes should be at ~600 bytes and ~1440 bytes
And the ratio should be approximately 1:3
And the distribution should match YouTube 1080p captures
# ============================================================================
# Timing Noise (Inter-packet Jitter)
# ============================================================================
Scenario Outline: Timing distributions match theoretical models
Given the epoch profile specifies <distribution> timing
And timing_lambda = <lambda>
When 10000 inter-packet delays are sampled
Then the empirical distribution should match theoretical <distribution>
Examples:
| distribution | lambda |
| Exponential | 0.01 |
| Gamma | 0.005 |
| Pareto | 0.001 |
Scenario: Timing jitter prevents clock skew attacks
Given an adversary measures inter-packet timing
When the PNG applies jitter with Exponential distribution
Then the coefficient of variation should be high (>0.5)
And timing side-channel attacks should fail
Scenario: Maximum latency bound enforcement
Given real-time voice application requirements
And maximum acceptable latency of 500ms
When timing noise is applied
Then no single packet should be delayed >500ms
And 99th percentile latency should be <300ms
# ============================================================================
# Dummy Packet Injection
# ============================================================================
Scenario: Dummy injection rate follows probability
Given dummy_probability = 0.10 (10%)
When 10000 transmission opportunities occur
Then approximately 1000 dummy packets should be injected
And the binomial 95% confidence interval should contain the count
Scenario: Dummy packets are indistinguishable from real
Given a mix of real and dummy packets
When examined by adversary
Then packet sizes should have same distribution
And timing should follow same patterns
And entropy analysis should not distinguish them
Scenario: Bursty dummy injection pattern
Given dummy_distribution = Bursty
And dummy_probability = 0.15
When dummies are injected
Then they should arrive in clusters (bursts)
And inter-burst gaps should follow exponential distribution
And intra-burst timing should be rapid
# ============================================================================
# Epoch Rotation
# ============================================================================
Scenario: Epoch rotates after packet count threshold
Given epoch_packet_count = 500
When 499 packets are transmitted
Then the profile should remain unchanged
When the 500th packet is transmitted
Then epoch rotation should trigger
And a new epoch profile should be generated
Scenario: Epoch rotation preserves session state
Given an active encrypted session
And epoch rotation triggers
When the new epoch begins
Then encryption keys should remain valid
And sequence numbers should continue monotonically
And no rekeying should be required
Scenario: Maximum epoch duration prevents indefinite exposure
Given epoch_packet_count = 1000
And a low-bandwidth application sends 1 packet/minute
When 60 minutes elapse with only 60 packets
Then the epoch should rotate anyway (time-based fallback)
And the maximum epoch duration should be 10 minutes
# ============================================================================
# Integration with Transport Skins
# ============================================================================
Scenario: PNG noise applied before skin wrapping
Given MIMIC_HTTPS skin is active
And an LWF frame of 1350 bytes
When PNG adds padding noise
Then the total size should follow epoch's distribution
And the padding should be added before TLS encryption
And the WebSocket frame should contain padded payload
Scenario: PNG noise subtraction by receiving peer
Given PNG adds 50 bytes of padding to a packet
When the packet arrives at destination
And the peer uses same PNG seed
Then the padding should be identifiable
And the original 1350-byte LWF frame should be recoverable
Scenario: Different skins use same PNG instance
Given a session starts with RAW skin
And PNG is seeded
When skin switches to MIMIC_HTTPS
Then the PNG should continue same epoch sequence
And noise patterns should remain consistent
# ============================================================================
# Statistical Security Tests
# ============================================================================
Scenario: NIST SP 800-22 randomness tests
Given 1MB of PNG output (ChaCha20 keystream)
When subjected to NIST statistical test suite
Then all 15 tests should pass
Including Frequency, Runs, FFT, Template matching
Scenario: Dieharder randomness tests
Given 10MB of PNG output
When subjected to Dieharder test suite
Then no tests should report "WEAK" or "FAILED"
Scenario: Avalanche effect on seed changes
Given PNG seed S1 produces output stream O1
When one bit is flipped in seed (S2 = S1 XOR 0x01)
And output stream O2 is generated
Then O1 and O2 should differ in ~50% of bits
And the correlation coefficient should be ~0
# ============================================================================
# Performance and Resource Usage
# ============================================================================
Scenario: PNG generation is fast enough for line rate
Given 1 Gbps network interface
And 1500 byte packets
When PNG generates noise for each packet
Then generation time should be <1μs per packet
And CPU usage should be <5% of one core
Scenario: PNG memory footprint is minimal
Given the PNG is initialized
When measuring memory usage
Then ChaCha20 state should use 136 bytes
And epoch profile should use 64 bytes
And total PNG overhead should be <1KB per session
Scenario: PNG works on constrained devices
Given a device with 10MB RAM (Kenya compliance)
When 1000 concurrent sessions are active
Then total PNG memory should be <10MB
And each session PNG overhead should be <10KB

View File

@ -0,0 +1,214 @@
Feature: RFC-0015 Pluggable Transport Skins
As a Libertaria node operator in a censored region
I want to automatically select camouflaged transport protocols
So that my traffic evades detection by state-level DPI (GFW, RKN, etc.)
Background:
Given the L0 transport layer is initialized
And the node has a valid relay endpoint configuration
And the Polymorphic Noise Generator (PNG) is seeded with ECDH secret
# ============================================================================
# Skin Selection and Probing
# ============================================================================
Scenario: Automatic skin selection succeeds with RAW UDP
Given the network allows outbound UDP to port 7844
When the skin probe sequence starts
And the RAW UDP probe completes within 100ms
Then the transport skin should be "RAW"
And the LWF frames should be sent unmodified over UDP
Scenario: Automatic skin selection falls back to HTTPS
Given the network blocks UDP port 7844
And HTTPS traffic to port 443 is allowed
When the RAW UDP probe times out after 100ms
And the HTTPS WebSocket probe completes within 500ms
Then the transport skin should be "MIMIC_HTTPS"
And the LWF frames should be wrapped in WebSocket frames over TLS 1.3
Scenario: Automatic skin selection falls back to DNS tunnel
Given the network blocks all UDP except DNS
And blocks HTTPS to non-whitelisted domains
When the RAW UDP probe times out
And the HTTPS probe times out after 500ms
And the DNS DoH probe completes within 1s
Then the transport skin should be "MIMIC_DNS"
And the LWF frames should be encoded as DNS queries over HTTPS
Scenario: Automatic skin selection reaches nuclear option
Given the network implements deep packet inspection on all protocols
And all previous probes fail
When the probe sequence reaches the steganography fallback
Then the transport skin should be "STEGO_IMAGE"
And the user should be warned of extreme latency
# ============================================================================
# Polymorphic Noise Generator (PNG)
# ============================================================================
Scenario: PNG generates per-session unique noise
Given two independent sessions to the same relay
And both sessions complete ECDH handshake
When Session A derives PNG seed from shared secret
And Session B derives PNG seed from its shared secret
Then the PNG seeds should be different
And the epoch profiles should be different
And the packet size distributions should not correlate
Scenario: PNG generates deterministic noise for session peers
Given a single session between Alice and Bob
And they complete ECDH handshake
When Alice derives PNG seed from shared secret
And Bob derives PNG seed from same shared secret
Then the PNG seeds should be identical
And Alice's noise can be subtracted by Bob
Scenario: PNG epoch rotation prevents long-term analysis
Given a session using MIMIC_HTTPS skin
And the epoch length is set to 500 packets
When 499 packets have been transmitted
Then the packet size distribution should follow Profile A
When the 500th packet is transmitted
Then the epoch should rotate
And the packet size distribution should follow Profile B
And Profile B should be different from Profile A
Scenario: PNG matches real-world distributions
Given MIMIC_HTTPS skin with Netflix emulation
When the PNG samples packet sizes
Then the distribution should be Pareto with mean 1440 bytes
And the distribution should match Netflix video chunk captures
# ============================================================================
# MIMIC_HTTPS Skin (WebSocket over TLS)
# ============================================================================
Scenario: HTTPS skin mimics Chrome TLS fingerprint
Given the transport skin is "MIMIC_HTTPS"
When the TLS handshake initiates
Then the ClientHello should match Chrome 120 JA3 signature
And the cipher suites should match Chrome defaults
And the extensions order should match Chrome
And the ALPN should be "h2,http/1.1"
Scenario: HTTPS skin WebSocket handshake looks legitimate
Given the transport skin is "MIMIC_HTTPS"
When the WebSocket upgrade request is sent
Then the HTTP headers should include legitimate User-Agent
And the request path should look like a real API endpoint
And the Origin header should be set appropriately
Scenario: HTTPS skin hides LWF magic bytes
Given an LWF frame with magic bytes "LWF\0"
When wrapped in MIMIC_HTTPS skin
Then the wire format should be TLS ciphertext
And the magic bytes should not appear in cleartext
And DPI signature matching should fail
Scenario: HTTPS skin with domain fronting
Given the relay supports domain fronting
And the cover domain is "cdn.cloudflare.com"
And the real endpoint is "relay.libertaria.network"
When the TLS handshake initiates
Then the SNI should be "cdn.cloudflare.com"
And the HTTP Host header should be "relay.libertaria.network"
Scenario: HTTPS skin with ECH (Encrypted Client Hello)
Given the relay supports ECH
And the client has ECH config for the relay
When the TLS handshake initiates
Then the ClientHelloInner should contain real SNI
And the ClientHelloOuter should have encrypted SNI
And passive DPI should not see the real destination
# ============================================================================
# MIMIC_DNS Skin (DoH Tunnel)
# ============================================================================
Scenario: DNS skin uses DoH not raw DNS
Given the transport skin is "MIMIC_DNS"
When a DNS query is sent
Then it should be an HTTPS POST to 1.1.1.1
And the Content-Type should be "application/dns-message"
And not use raw port 53 UDP
Scenario: DNS skin avoids high-entropy labels
Given the transport skin is "MIMIC_DNS"
When encoding LWF data as DNS queries
Then subdomain labels should use dictionary words
And the Shannon entropy should be < 3.5 bits/char
And not use Base32/Base64 encoding
Scenario: DNS skin matches real DoH timing
Given the transport skin is "MIMIC_DNS"
When sending queries
Then the inter-query timing should follow Gamma distribution
And not be perfectly regular
And should match Cloudflare DoH query patterns
# ============================================================================
# Anti-Fingerprinting and Active Defense
# ============================================================================
Scenario: Active probe receives honeytrap response
Given an adversary sends probe traffic to relay
And the probe has no valid session cookie
When the relay receives the probe
Then it should respond as nginx default server
And return HTTP 200 with generic index.html
And not reveal itself as Libertaria relay
Scenario: Rate limiting on failed handshakes
Given an adversary attempts rapid handshake scanning
When more than 10 failed handshakes occur from same IP in 1 minute
Then subsequent connections should be rate limited
And exponential backoff should apply
Scenario: PoW prevents relay enumeration
Given the relay requires proof-of-work
When a client connects without valid PoW
Then the connection should be rejected
When a client connects with valid Argon2 PoW (100ms compute)
Then the connection should proceed to handshake
# ============================================================================
# Multi-Path Agility
# ============================================================================
Scenario: Primary skin throttling triggers fallback
Given primary skin is MIMIC_HTTPS at 90% bandwidth
And secondary skin is MIMIC_DNS at 10% bandwidth
When GFW detects and throttles HTTPS traffic
Then the secondary channel should signal endpoint switch
And the primary should migrate to new relay IP
Scenario: Seamless skin switching without rekeying
Given an active session with MIMIC_HTTPS
When the skin switches to MIMIC_DNS due to blocking
Then the LWF encryption keys should remain valid
And no re-handshake should be required
And in-flight packets should not be lost
# ============================================================================
# Error Handling and Edge Cases
# ============================================================================
Scenario: All probes fail raises alert
Given all network paths are blocked
When the skin probe sequence completes
And no viable skin is found
Then the user should receive "Network severely restricted" alert
And manual configuration option should be offered
Scenario: Skin mid-session failure recovery
Given a session is active with MIMIC_HTTPS
When the TLS connection drops unexpectedly
Then automatic reconnection should attempt same skin first
And fallback to next skin after 3 retries
Scenario: Invalid skin configuration is rejected
Given the configuration specifies unknown skin "MIMIC_UNKNOWN"
When the transport initializes
Then initialization should fail with "Invalid skin"
And fallback to automatic selection should occur