Protocol Flow

Sequence diagrams for AWS SSM Session Manager.

Table of contents

  1. Overview
  2. Message Buffers
  3. Reliable Delivery
    1. Outgoing Flow
    2. Incoming Flow
  4. Session Lifecycle
  5. Handshake Sequence
  6. Data Exchange
  7. Binary Header Format
  8. Payload Types
  9. ACK Format
  10. UUID Wire Format
  11. Port Forwarding
  12. Protocol Constants
  13. 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 estimate
  • RoundTripTimeVariation - RTT variance
  • RetransmissionTimeout - 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

  1. ACK Only Non-Duplicates: seq < expected → drop silently
  2. ACK Immediately: Don’t wait for processing
  3. UUID Byte Swap: LSB first (8-15), MSB second (0-7)
  4. PayloadDigest: SHA-256 of payload only
  5. OpenDataChannelInput: Send as TEXT, not binary
  6. Respect pause_publication: Stop sending immediately

Copyright © 2026. Distributed under the MIT license.