The Secure Shell (SSH) Connection Protocol
updated by
- rfc-8308 — Extension Negotiation in the Secure Shell (SSH) Protocol
Extracted elements (30)
Channel numbers are local identifiers at each end of the connection and may differ on each side; any channel-related message uses the recipient's channel number. This avoids requiring a global channel namespace and allows each side to allocate numbers independently.
X11 channels opened via forwarding are independent of the session channel; closing the session does not close already-opened X11 forwardings. This allows X11 applications to outlive the shell session that launched them, matching typical desktop use patterns.
The SSH Connection Protocol is designed to run on top of SSH transport ([SSH-TRANS]) and user authentication ([SSH-USERAUTH]) layers; it relies entirely on those layers for encryption, integrity, and user authentication and does not provide these itself.
An implementation MUST NOT advertise a maximum packet size that would result in transport packets larger than its transport layer is willing to receive, and MUST NOT generate data packets larger than its transport layer is willing to send.
Client implementations SHOULD reject any session channel open requests to make it more difficult for a corrupt server to attack the client.
Client implementations SHOULD reject direct TCP/IP open requests ('direct-tcpip') for security reasons, as these messages may otherwise be used by a malicious server to probe internal networks.
Implementations MUST correctly handle window sizes of up to 2^32 - 1 bytes. The window MUST NOT be increased above 2^32 - 1 bytes.
Implementations MUST reject any X11 channel open requests if they have not previously requested X11 forwarding, preventing unauthorized X11 channel injection.
Implementations MUST reject 'forwarded-tcpip' channel open messages unless they have previously requested a remote TCP/IP port forwarding with the given port number.
It is RECOMMENDED that the x11 authentication cookie sent in an x11-req channel request be a fake, random cookie, and that it be checked and replaced by the real cookie when a connection request is received, to prevent cookie theft.
Normal precautions MUST be taken to prevent the execution of unauthorized commands when handling 'exec' channel requests.
Replies to SSH_MSG_GLOBAL_REQUEST messages MUST be sent in the same order as the corresponding requests. For channel requests, replies relating to the same channel MUST also be in order; replies for distinct channels MAY be out-of-order.
The 'x11 authentication cookie' in the x11-req message MUST be hexadecimal encoded.
Exit status and exit-signal channel requests convey command termination information. 'exit-status' carries a uint32 exit code; 'exit-signal' carries signal name (without SIG prefix), core-dump boolean, UTF-8 error message, and language tag. The channel must subsequently be closed with SSH_MSG_CHANNEL_CLOSE.
SSH_MSG_CHANNEL_EOF signals that a party will send no more data; the channel remains open for data in the other direction. This message does not consume window space. No explicit response is sent.
The SSH Connection Protocol multiplexes all terminal sessions, forwarded connections, and other channel types into a single encrypted tunnel. Channels are identified by numbers local to each end; the sender's channel number may differ from the recipient's.
IANA registry for Extended Channel Data Transfer data_type_code values. Values MUST be assigned sequentially; 0x00000002–0xFDFFFFFF require IETF CONSENSUS. Range 0xFE000000–0xFFFFFFFF is PRIVATE USE.
IANA registry for SSH channel connection failure reason codes. Values 0x00000001–0xFDFFFFFF require IETF CONSENSUS for assignment. Range 0xFE000000–0xFEFFFFFF is PRIVATE USE for locally assigned channels. Range 0xFF000000–0xFFFFFFFF is unrestricted experimental use.
It is RECOMMENDED that implementations disable all potentially dangerous features—agent forwarding, X11 forwarding, and TCP/IP forwarding—if the host key has changed without notice or explanation, as this may indicate a man-in-the-middle attack.
Uncontrolled setting of environment variables in a privileged process is a security hazard. Implementations should maintain an allowlist of permitted variable names or only set environment variables after the server process has dropped sufficient privileges.
Channel closure requires both sides to exchange SSH_MSG_CHANNEL_CLOSE. Upon receiving SSH_MSG_CHANNEL_CLOSE, a party MUST send back SSH_MSG_CHANNEL_CLOSE unless already sent. A channel is fully closed only when both sent and received; the channel number may then be reused.
Encoded terminal modes are a byte stream of opcode-argument pairs. Opcodes 1–159 take a single uint32 argument; opcodes 160–255 are undefined and terminate parsing. The stream is terminated by TTY_OP_END (opcode 0x00). TTY_OP_ISPEED (128) and TTY_OP_OSPEED (129) specify baud rates.
SSH_MSG_CHANNEL_EXTENDED_DATA carries: recipient channel (uint32), data_type_code (uint32), and data (string). Currently only SSH_EXTENDED_DATA_STDERR (1) is defined. Extended data consumes the same channel window as ordinary data.
SSH_MSG_CHANNEL_OPEN_CONFIRMATION contains: recipient channel (uint32), sender channel (uint32), initial window size (uint32), maximum packet size (uint32), and optional channel-type-specific data.
SSH_MSG_CHANNEL_OPEN contains: channel type (string, US-ASCII), sender channel (uint32), initial window size (uint32), maximum packet size (uint32), followed by channel-type-specific data.
SSH_MSG_CHANNEL_OPEN_FAILURE contains: recipient channel (uint32), reason code (uint32), description (string in UTF-8/RFC3629), and language tag (string per RFC3066). Four reason codes are defined: SSH_OPEN_ADMINISTRATIVELY_PROHIBITED (1), SSH_OPEN_CONNECT_FAILED (2), SSH_OPEN_UNKNOWN_CHANNEL_TYPE (3), SSH_OPEN_RESOURCE_SHORTAGE (4).
SSH_MSG_CHANNEL_REQUEST carries: recipient channel (uint32), request type (string, US-ASCII), want-reply (boolean), and type-specific data. Responses are SSH_MSG_CHANNEL_SUCCESS or SSH_MSG_CHANNEL_FAILURE; if the request is unrecognized, SSH_MSG_CHANNEL_FAILURE is returned.
SSH_MSG_GLOBAL_REQUEST carries a US-ASCII request name (string), a want-reply boolean, and request-specific data. Replies SSH_MSG_REQUEST_SUCCESS and SSH_MSG_REQUEST_FAILURE are sent only when want-reply is TRUE.
The 'pty-req' channel request includes: TERM variable (string), terminal width/height in characters and pixels (four uint32s), and encoded terminal modes (string). Zero dimension parameters MUST be ignored; character/row dimensions override pixel dimensions when nonzero.
The 'tcpip-forward' global request specifies address to bind (string) and port number (uint32). If port 0 is requested with want-reply TRUE, the server replies with SSH_MSG_REQUEST_SUCCESS containing the allocated port (uint32).