Protocol Flow
Sequence diagrams for AWS SSM Session Manager.
Table of contents
- Overview
- Message Buffers
- Reliable Delivery
- Session Lifecycle
- Handshake Sequence
- Data Exchange
- Binary Header Format
- Payload Types
- ACK Format
- UUID Wire Format
- Port Forwarding
- Protocol Constants
- Implementation Notes
Overview
This document describes the protocol flow for AWS SSM Session Manager WebSocket communication, based on analysis of the AWS session-manager-plugin.
Message Buffers
Reliable message delivery uses two buffers:
| Buffer | Type | Capacity | Purpose |
|---|---|---|---|
| OutgoingMessageBuffer | LinkedList | 10,000 | Messages waiting for ACK |
| IncomingMessageBuffer | HashMap | 10,000 | Out-of-order messages |
RTT Tracking (Jacobson/Karels algorithm, RFC 6298):
RoundTripTime- Smoothed RTT estimateRoundTripTimeVariation- RTT varianceRetransmissionTimeout- Adaptive timeout
Reliable Delivery
Outgoing Flow
flowchart LR
A[Send Data] --> B[Add to Buffer]
B --> C[Send via WebSocket]
C --> D{ACK Received?}
D -->|Yes| E[Remove from Buffer]
D -->|No| F[Timeout 200ms]
F --> C
Incoming Flow
flowchart TD
A[Receive Message] --> B{seq vs expected?}
B -->|seq == expected| C[Process + ACK]
B -->|seq > expected| D[Buffer + ACK]
B -->|seq < expected| E[Duplicate: Drop silently]
C --> F[Increment expected]
F --> G{Buffer has next?}
G -->|Yes| C
G -->|No| H[Done]
Critical: Do NOT ACK duplicates. The sender tracks unacked messages and will stop retrying when duplicates aren’t acknowledged.
Session Lifecycle
flowchart TD
A[Connect WebSocket] --> B[Send OpenDataChannelInput]
B --> C{Agent Type?}
C -->|Modern| D[Receive HandshakeRequest]
C -->|Legacy| E[Receive Output directly]
D --> F[Send HandshakeResponse]
F --> G[Receive HandshakeComplete]
G --> H[Session Ready]
E --> H
H --> I[Data Exchange]
I --> J[channel_closed]
Handshake Sequence
sequenceDiagram
participant C as Client
participant A as Agent
Note over C,A: Modern Agents v2.3.722+
A->>C: HandshakeRequest
C->>A: ACK
C->>A: HandshakeResponse
A->>C: ACK
A->>C: HandshakeComplete
C->>A: ACK
Note over C,A: Session Ready
Data Exchange
sequenceDiagram
participant C as Client
participant A as Agent
loop Interactive Shell
C->>A: input_stream_data
A->>C: ACK
A->>C: output_stream_data
C->>A: ACK
end
Binary Header Format
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 4 | HeaderLength | Always 116 |
| 4 | 32 | MessageType | e.g. “input_stream_data” |
| 36 | 4 | SchemaVersion | Always 1 |
| 40 | 8 | CreatedDate | Unix millis |
| 48 | 8 | SequenceNumber | Message sequence |
| 56 | 8 | Flags | SYN=1, FIN=2 |
| 64 | 16 | MessageId | UUID (byte-swapped) |
| 80 | 32 | PayloadDigest | SHA-256 of payload |
| 112 | 4 | PayloadType | 1=Output, 5=Handshake, etc. |
| 116 | 4 | PayloadLength | Payload size |
Payload Types
| Type | Name | Direction | Description |
|---|---|---|---|
| 1 | Output | Agent→Client | Shell stdout |
| 2 | Error | Agent→Client | Error message |
| 3 | Size | Client→Agent | Terminal resize |
| 5 | HandshakeRequest | Agent→Client | Handshake initiation |
| 6 | HandshakeResponse | Client→Agent | Handshake reply |
| 7 | HandshakeComplete | Agent→Client | Handshake done |
| 10 | Flag | Both | Control flags |
| 11 | StdErr | Agent→Client | Shell stderr |
| 12 | ExitCode | Agent→Client | Process exit |
ACK Format
ACK messages have specific fixed values:
| Field | Value |
|---|---|
| SequenceNumber | 0 (always) |
| Flags | 3 (SYN | FIN) |
| MessageType | “acknowledge” |
Payload (JSON):
{
"AcknowledgedMessageType": "output_stream_data",
"AcknowledgedMessageId": "uuid-string",
"AcknowledgedMessageSequenceNumber": 42,
"IsSequentialMessage": true
}
UUID Wire Format
AWS uses non-standard byte order:
Standard: [MSB 0-7] [LSB 8-15]
AWS Wire: [LSB 8-15] [MSB 0-7]
Port Forwarding
sequenceDiagram
participant L as Local App
participant C as Client
participant A as Agent
participant T as Target
L->>C: TCP Connect
C->>A: Flag SYN
A->>T: TCP Connect
A->>C: Flag SYN
loop Data Transfer
L->>C: Data
C->>A: input_stream_data
A->>T: Data
T->>A: Data
A->>C: output_stream_data
C->>L: Data
end
L--xC: TCP Close
C->>A: Flag FIN
Protocol Constants
| Constant | Value |
|---|---|
| Header Length | 116 bytes |
| Schema Version | 1 |
| Max Payload | 64 KB |
| ACK Timeout | ~200ms |
| Max Retries | 3000 (5 min) |
| Buffer Capacity | 10,000 messages |
Implementation Notes
- ACK Only Non-Duplicates:
seq < expected→ drop silently - ACK Immediately: Don’t wait for processing
- UUID Byte Swap: LSB first (8-15), MSB second (0-7)
- PayloadDigest: SHA-256 of payload only
- OpenDataChannelInput: Send as TEXT, not binary
- Respect pause_publication: Stop sending immediately