Skip to content

Latest commit

 

History

History
169 lines (127 loc) · 6.85 KB

PROTOCOLS.md

File metadata and controls

169 lines (127 loc) · 6.85 KB

SSH Protocol Layers

Overview

SSH consists of multiple protocols in several layers, as described in brief at SSH Architecture and in full detail in RFC 4251. The layers are, from lowest to highest:

  1. A connection-oriented underlying transport protocol (usually TCP).
  2. The SSH transport layer.
  3. Other protocols that send messages via the SSH transport layer, including the transport layer itself (for negotiating its own parameters), the SSH user authentication layer and the SSH connection layer.

Protocol Layer Details

Underlying Transport Protocol

As per RFC 4253 §4, this is any 8-bit clean, binary-transparent transport. (Usually this will be TCP.) Ideally it should protect against errors, as SSH aborts the connection upon encountering a transport error.

SSH Transport Protocol

Packet Format

This starts with the connection banner after which all exchanges are in a fixed packet format:

field type contents
len uint32 length l of all packet data following this word
padlen byte p, length of padding below
payload byte[d] length d = l - p - 1
padding byte[p] random data
MAC byte[m] (unencrypted) Message Authentication Code; m = MAC length

Messages

Though it's not terribly clear from the RFCs, the payload above always consists of fields, the first of which is always a message type identifier. The address space of these identifiers is shared amongst all the higher-level protocols that use the SSH transport protocols. The message type identifiers fall in to the following ranges:

Values Protocol Purpose
1-19 SSH-TRANS Transport layer generic (disconnect, debug etc.)
20-29 SSH-TRANS Algorithm negotiation
30-49 SSH-TRANS Key exchange (varies w/auth method)
50-59 SSH-USERAUTH User authentication generic
60-79 SSH-USERAUTH User auth specific (varies w/auth method)
80-89 SSH-CONNECT Connection protocol generic
90-127 SSH-CONNECT Channel-related messages
128-191 Reserved
192-255 Local extensions

Note that the SSH transport protocol has its own set of messages run over the basic packet format of that protocol. There is a list of the generic message numbers for all protocols.

Connection Setup

As well as defining the base packet format, the SSH transport protocol also defines the initial parts of the connection setup, which are:

a) Session key setup, typically using Diffie Hellman key exchange. This creates an encrypted (but not authenticated) connection between the client and the server that is protected from eavesdropping by a third party.

b) Authentication of the server via verification by the client of a host public key sent to the client by the server.

c) One or more "service requests" from the client to the server. This will typically be a request for the ssh-userauth service, part of which requests that the ssh-connection service be started if the client authentication is successful.

After the first two steps all transport-layer packets are encrypted and authenticated. (During the course of the connection, the encryption parameters may be re-negotiated, e.g., to re-key the connection.)

Note that this setup is the only time the client ever checks the identity of the server; from this point all future messages in the transport protocol are known to come via the connection to that server but no further checks are done. This implies, for example, that higher-level messages could be generated by another host and just relayed by the server, such as in the case where SSH agent forwarding is used.

SSH User Authentication Protocol

Once the transport level connection has been set up and the server has accepted a request from the client for the ssh-userauth service, the client may send authentication requests to the server.

All SSH_MSG_USERAUTH_REQUEST messages start with the following four fields:

Field    | Type   | Description
---------|--------|---------------------------------------------
msg.type | byte   | Always `SSH_MSG_USERAUTH_REQUEST`
username | string | (in UTF-8)
service  | string | service to start if auth is successful (e.g., `ssh-connection`)
method   | string | [method name][U§5], e.g., `publickey` or `password`

We discuss here only the publickey authentication method. In this case the client constructs an SSH_MSG_USERAUTH_REQUEST message which inlcudes the above and several further fields:

  • The fifth field is a boolean. FALSE indicates that this is a check to see if an authentication with a given public key would be acceptable; TRUE indicates that this is an actual signed authentication request.

  • The sixth and seventh fields are the public key algorithm name and the public key itself.

  • The eighth field, present only if the fifth field is TRUE, is a signature as described below.

The server response depends on the fifth field:

  • If FALSE, the response is SSH_MSG_USERAUTH_PK_OK if the server will accept an attempt to authenticate with the key or SSH_MSG_USERAUTH_FAILURE if it will not accept such an attempt.

  • If TRUE, the response is SSH_MSG_USERAUTH_SUCCESS if the server could verify the signature and no further authentications are needed, or SSH_MSG_USERAUTH_FAILURE if either it couldn't verify the signature or if it could but further authentication is needed.

The signature is over the session identifier (from the lower-level protocol, usually SSH-TRANS) prefixed to the SSH_MSG_USERAUTH_REQUEST message. This is described in [U§1] as "the exchange hash H from the first key exchange."

SSH Connection Layer Protocol