Files
Nils Andreas Svee 58472dbf7b docs(protocol): airlock server black-box findings
Transfer independently black-box-verified server behavior from a source-assisted
research phase conducted outside this repository. Only a sanitizer-candidate
report of black-box findings and the packet captures it referenced were admitted;
no upstream source, tests, history, harnesses, build trees, result files or
source-assisted analysis crossed the boundary. Provenance and the boundary
discipline are recorded in docs/clean-room/CLEANROOM_NOTES.md.

New upstream robustness defect (Section 22.5). An open selecting timestamps while
omitting the Clock parameter is accepted with a valid token and no Clock echoed,
and the first echo on that session is fatal to the server process, taking
unrelated sessions on the same process with it. An explicit Clock=0 is instead
rejected at open, so parameter presence is externally meaningful. Recorded as an
observed defect with a must-not-crash recommendation; the clean server's
resolution is deliberately left to the implementation work.

Also established or strengthened:

- the idle grace and maximum-duration grace are fixed additive margins across the
  settings swept, and the maximum-duration clock starts at the first echo that is
  actually served;
- a rate-limited request is the only tested drop class that keeps a session
  alive, and in one documented configuration a conforming client can observe the
  difference;
- a post-deadline packet of several tested classes consumes an expired session's
  one remaining reply, including packets that are themselves dropped;
- the reply-length cap is the bind interface's MTU on the interfaces where it was
  reachable, and a length the host cannot transmit ends the process;
- DSCP marking follows the session, with unmarked open replies and no
  cross-session leakage across interleaved sessions;
- repeated tags are last-valid-wins, with invalid-duplicate handling scoped to
  the orders actually tested, and unknown tag values are consumed as varints.

Three captures were admitted, each rewritten to the container convention already
used here and verified byte-identical in packet data and timestamps:
server-clock-absent (3 packets), server-expiry-consumption (14) and
server-dscp-interleaved (32). Two further captures were reviewed and rejected as
redundant or unsupporting; their textual results were kept instead.

Host-specific figures are labelled as such throughout, upstream defects are not
promoted to protocol requirements, observations are separated from inferences and
from recommendations, and no implementation policy is chosen here. The client
specification gains matching refinements where the two compatibility baselines
would otherwise state a lifecycle or marking rule differently.

Documentation and evidence only; no production code changed.
2026-08-12 16:24:57 +07:00
..

IRTT Packet Test Vectors

Source: Black-box captures from irtt 0.9.1 on macOS Darwin 25.3.0 arm64
Date: 2026-04-28

All vectors are from actual network captures (not constructed).


Vector 1: Open Request (no HMAC)

Scenario: Client opens session with default parameters (duration=3s, interval=1s, stats=both, tstamp=both, clock=both).
Direction: Client → Server
irtt version: 0.9.1
Command: irtt client -d 3s -i 1s 127.0.0.1:2112

Packet (24 bytes):

14 a7 5b 01 01 02 02 80 f8 82 ad 16 03 80 a8 d6
b9 07 05 06 06 06 07 06

Field breakdown:

  • Bytes 0-2: Magic 14 a7 5b
  • Byte 3: Flags 01 (Open)
  • Bytes 4-23: Parameter payload:
    • Tag 1 (ProtocolVersion): value 02 → zigzag → 1
    • Tag 2 (Duration): value 80 f8 82 ad 16 → zigzag → 3000000000 ns (3s)
    • Tag 3 (Interval): value 80 a8 d6 b9 07 → zigzag → 1000000000 ns (1s)
    • Tag 5 (ReceivedStats): value 06 → zigzag → 3 (Both)
    • Tag 6 (StampAt): value 06 → zigzag → 3 (Both)
    • Tag 7 (Clock): value 06 → zigzag → 3 (Both)

Notes:

  • No connection token field (token not yet assigned)
  • Tags 4 (Length), 8 (DSCP) omitted because values are 0
  • Tag 9 (ServerFill) omitted because not specified

Vector 2: Open Reply (no HMAC)

Scenario: Server accepts session, returns token and echoed parameters.
Direction: Server → Client
Token: 0x7896b6ab87715213

Packet (32 bytes):

14 a7 5b 03 13 52 71 87 ab b6 96 78 01 02 02 80
f8 82 ad 16 03 80 a8 d6 b9 07 05 06 06 06 07 06

Field breakdown:

  • Bytes 0-2: Magic 14 a7 5b
  • Byte 3: Flags 03 (Open | Reply)
  • Bytes 4-11: Connection token 13 52 71 87 ab b6 96 78 (LE: 0x7896b6ab87715213)
  • Bytes 12-31: Parameter payload (same as request — no restrictions)

Vector 3: Echo Request (no HMAC, default stats+timestamps)

Scenario: First test packet, sequence 0, default settings.
Direction: Client → Server
Token: 0x7896b6ab87715213, Seq: 0

Packet (60 bytes):

14 a7 5b 00 13 52 71 87 ab b6 96 78 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

Field breakdown:

  • Bytes 0-2: Magic 14 a7 5b
  • Byte 3: Flags 00 (no flags — echo request from client)
  • Bytes 4-11: Connection token
  • Bytes 12-15: Sequence number 00 00 00 00 (LE: 0)
  • Bytes 16-19: Received count (zeroed placeholder)
  • Bytes 20-27: Received window (zeroed placeholder)
  • Bytes 28-35: Receive wall timestamp (zeroed placeholder)
  • Bytes 36-43: Receive mono timestamp (zeroed placeholder)
  • Bytes 44-51: Send wall timestamp (zeroed placeholder)
  • Bytes 52-59: Send mono timestamp (zeroed placeholder)

Notes: All stats and timestamp fields are zeroed in echo requests. They serve as placeholders to reach the negotiated packet length.


Vector 4: Echo Reply (no HMAC, default stats+timestamps)

Scenario: Server reply to seq 2, third packet in session.
Direction: Server → Client
Token: 0x7896b6ab87715213, Seq: 2, Recv Count: 3, Window: 0x07

Packet (60 bytes):

14 a7 5b 02 13 52 71 87 ab b6 96 78 02 00 00 00
03 00 00 00 07 00 00 00 00 00 00 00 b8 1a 33 0c
86 6d aa 18 de 26 35 95 00 00 00 00 80 4d 33 0c
86 6d aa 18 b2 57 35 95 00 00 00 00

Field breakdown:

  • Bytes 0-2: Magic 14 a7 5b
  • Byte 3: Flags 02 (Reply)
  • Bytes 4-11: Connection token
  • Bytes 12-15: Sequence number 02 00 00 00 (LE: 2)
  • Bytes 16-19: Received count 03 00 00 00 (LE: 3)
  • Bytes 20-27: Received window 07 00 00 00 00 00 00 00 (LE: 0x07, bits 0-2 set)
  • Bytes 28-35: Receive wall timestamp b8 1a 33 0c 86 6d aa 18 (LE int64)
  • Bytes 36-43: Receive mono timestamp de 26 35 95 00 00 00 00 (LE int64)
  • Bytes 44-51: Send wall timestamp 80 4d 33 0c 86 6d aa 18 (LE int64)
  • Bytes 52-59: Send mono timestamp b2 57 35 95 00 00 00 00 (LE int64)

Window interpretation (for seq 2):

  • Bit 0 (0x01): Seq 2 received ✓
  • Bit 1 (0x02): Seq 1 received ✓
  • Bit 2 (0x04): Seq 0 received ✓

Vector 5: Close Request (no HMAC)

Scenario: Client sends close after test.
Direction: Client → Server
Token: 0x7896b6ab87715213

Packet (12 bytes):

14 a7 5b 04 13 52 71 87 ab b6 96 78

Field breakdown:

  • Bytes 0-2: Magic 14 a7 5b
  • Byte 3: Flags 04 (Close)
  • Bytes 4-11: Connection token

Vector 6: HMAC Open Request

Scenario: Client opens session with HMAC key "testkey".
Direction: Client → Server
HMAC key: ASCII "testkey" (7 bytes)

Packet (40 bytes):

14 a7 5b 09 ff 90 16 a7 aa 53 78 16 9e c3 a2 d5
54 dc 30 36 01 02 02 80 d0 ac f3 0e 03 80 a8 d6
b9 07 05 06 06 06 07 06

Field breakdown:

  • Bytes 0-2: Magic 14 a7 5b
  • Byte 3: Flags 09 (Open | HMAC)
  • Bytes 4-19: HMAC ff 90 16 a7 aa 53 78 16 9e c3 a2 d5 54 dc 30 36
  • Bytes 20-39: Parameter payload

HMAC cross-checked with a separately written Python script (HMAC-MD5 over the entire packet with the HMAC field zeroed).


Vector 7: HMAC Echo Request

Scenario: Echo request with HMAC, seq 0.
Direction: Client → Server
Token: 0x4387e9eb5d3fca59, HMAC key: "testkey"

Packet (76 bytes):

14 a7 5b 08 d9 87 4f 82 b3 13 10 31 59 ad 2c 8f
6b da ef ff 59 ca 3f 5d eb e9 87 43 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

Field breakdown:

  • Bytes 0-2: Magic
  • Byte 3: Flags 08 (HMAC)
  • Bytes 4-19: HMAC
  • Bytes 20-27: Connection token 59 ca 3f 5d eb e9 87 43
  • Bytes 28-31: Sequence number 00 00 00 00
  • Bytes 32-75: Stats + timestamp placeholders (zeroed)

Vector 8: HMAC Close Request

Scenario: Close with HMAC.
Direction: Client → Server
Token: 0x4387e9eb5d3fca59, HMAC key: "testkey"

Packet (28 bytes):

14 a7 5b 0c f5 cd 0f a9 de 9d 7d 66 8d 91 a5 32
48 0e 42 e0 59 ca 3f 5d eb e9 87 43

Field breakdown:

  • Bytes 0-2: Magic
  • Byte 3: Flags 0c (Close | HMAC)
  • Bytes 4-19: HMAC
  • Bytes 20-27: Connection token

Vector 9: No-Test Mode (Open+Close Request)

Scenario: Client opens and immediately closes.
Direction: Client → Server

Packet (25 bytes):

14 a7 5b 05 01 02 02 80 e0 ba 84 bf 03 03 80 a8
d6 b9 07 05 06 06 06 07 06

Field breakdown:

  • Bytes 0-2: Magic
  • Byte 3: Flags 05 (Open | Close)
  • Bytes 4-24: Parameter payload
    • Tag 1: ProtocolVersion = 1
    • Tag 2: Duration = 60000000000 ns (60s, default)
    • Tag 3: Interval = 1000000000 ns (1s, default)
    • Tag 5: ReceivedStats = 3 (Both)
    • Tag 6: StampAt = 3 (Both)
    • Tag 7: Clock = 3 (Both)

Vector 10: No-Test Mode (Open+Close Reply)

Scenario: Server acknowledges no-test open+close.
Direction: Server → Client

Packet (33 bytes):

14 a7 5b 07 00 00 00 00 00 00 00 00 01 02 02 80
e0 ba 84 bf 03 03 80 a8 d6 b9 07 05 06 06 06 07
06

Field breakdown:

  • Bytes 0-2: Magic
  • Byte 3: Flags 07 (Open | Reply | Close)
  • Bytes 4-11: Connection token 00 00 00 00 00 00 00 00 (ZERO)
  • Bytes 12-32: Parameter payload

Notes: In no-test mode, the server returns a zero connection token. The Close flag in this context means "acknowledged close" not "rejected."


Vector 11: Minimal Echo Packet (no stats, no timestamps)

Scenario: Echo request with stats=none, tstamp=none.
Direction: Client → Server
Token: 0xa0316fa25c61154e, Seq: 0

Packet (16 bytes):

14 a7 5b 00 4e 15 61 5c a2 6f 31 a0 00 00 00 00

Field breakdown:

  • Bytes 0-2: Magic
  • Byte 3: Flags 00
  • Bytes 4-11: Connection token
  • Bytes 12-15: Sequence number

This is the absolute minimum echo packet size.


Vector 12: Midpoint Timestamps (both clocks)

Scenario: Echo reply with stats=both, tstamp=midpoint, clock=both.
Direction: Server → Client

Packet (44 bytes):

14 a7 5b 02 91 a4 1e 7a f0 14 f6 62 00 00 00 00
01 00 00 00 01 00 00 00 00 00 00 00 f7 0e 2c 93
a2 6d aa 18 5a 5f 14 47 03 00 00 00

Field breakdown:

  • Bytes 0-2: Magic
  • Byte 3: Flags 02 (Reply)
  • Bytes 4-11: Token
  • Bytes 12-15: Seq 00 00 00 00 (0)
  • Bytes 16-19: Recv count 01 00 00 00 (1)
  • Bytes 20-27: Recv window 01 00 00 00 00 00 00 00
  • Bytes 28-35: Midpoint wall timestamp
  • Bytes 36-43: Midpoint mono timestamp

Notes: Only midpoint timestamps present. No receive/send timestamp fields. Confirms midpoint is mutually exclusive with receive+send.