Algorithm for establishing a connection in the SSH protocol
(The initial title of the article “Algorithm of the SSH protocol” was changed according to the recommendations of Vindicar , Karroplan and other members of the habrosocommunity)
Periodically reading articles on SSH, I noticed that their authors sometimes have no idea how this protocol works. In most cases, they are limited to considering the topic of key generation and the description of options for the main commands. Even experienced system administrators often carry complete nonsense when discussing SSH operation issues, giving out opus in the style: the transmitted data is encrypted with the client's open SSH key, and decrypted as a private one, or: the RSA algorithm is used to encrypt the data.
I will try to bring some clarity to the work of the SSH protocol, and at the same time consider the role of the RSA algorithm and user authorization keys ...
The SSH protocol algorithm can be divided into three levels, each of which is located above the previous one: transport (opening a secure channel), authentication, connection. For the integrity of the picture, I will also add the network connection setup level, although officially this level is below SSH.
I will not dwell on the principle of operation of the TCP / IP stack, since this topic is well documented in RuNet. If necessary, you can easily find information.
At this stage, the client connects to the server on the TCP port specified in the Port option (default: 22) in the server configuration file / etc / ssh / sshd_config.
2.1 Identity Exchange
After the TCP connection is established, the client and the server (hereinafter referred to as the parties) exchange the SSH protocol versions and other auxiliary data necessary to determine the compatibility of the protocols and to select the operation algorithms.
2.2 Selection of algorithms: key exchange, encryption, compression, etc.
When SSH is used, quite a few algorithms are used, some of them are used for encryption, the second for key exchange, the third for compressing transmitted data, etc. At this step, the parties send each other lists of supported algorithms, the highest priority is given to the algorithms at the top of each list. Then compare the algorithms in the received lists with the algorithms available in the system, and select the first matched one in each list.
The list of available client-side key exchange algorithms (used to obtain a session key) can be viewed with the command:
The list of symmetric algorithms available in the system (used to encrypt the channel):
The list of key types for authorization at the client:
Added on the remark onix74 :
All the commands used in the publication are relevant to the version of OpenSSH 7.6 from Ubuntu 18.04 LTS.
2.3 Obtaining a session encryption key
The process of obtaining a session key may differ depending on the version of the algorithm, but in general terms it comes down to the following:
The session key is created exclusively for the period of the channel's life and is destroyed when the connection is closed.
And only now, when the client and the server have established a channel for encrypted data transfer, can they authenticate by password or key.
In general, authentication using keys is as follows:
After carrying out all the above procedures, the user is able to send commands to the server or copy files.
At this level, the following is provided: channel multiplication (the ability of multiple channels to work on a single server by combining them into one channel), tunneling, etc.
Well, now, I think, readers have quite a legitimate question: why do we need to know all these subtleties of the SSH protocol, if for everyday work there is enough knowledge of key creation commands (ssh-keygen), opening a terminal session (ssh), transferring files ( scp)?
As a response, you can recall the topic of changing the standard SSH port to another one, which constantly becomes the cause of holivar on Habr ...
In my own practice, I don’t remember a single server looking to the external network that would not be daily slapped to port 22. In a situation if SSH works on a standard port for you (and is not additionally protected by anything), even if authentication using keys only and no password selections do not frighten you, the server is still forced to do a lot of useless work because of constant requests from unscrupulous clients: establish a TCP connection, select algorithms, generate a session key, send authentication requests, write a log file.
In a situation where there is nothing on port 22, or the port is protected using iptables (or add-ons of the fail2ban type), then the attacker will be dropped at the stage of establishing a TCP connection.
The most interestingly described looks like a table *
* - the values of the parameters (high, medium, low) are relative and serve only to compare indicators.
** - meaning the consumption of server resources (processor, disk, network channel, etc.) for processing an avalanche of requests, usually going to port 22.
*** - hacking, if RSA-keys are used for authorization, is very difficult, but an unlimited number of authorization attempts makes this possible.
**** - the number of authorization attempts is limited, but the server still has to process them from a large number of intruders.
Periodically reading articles on SSH, I noticed that their authors sometimes have no idea how this protocol works. In most cases, they are limited to considering the topic of key generation and the description of options for the main commands. Even experienced system administrators often carry complete nonsense when discussing SSH operation issues, giving out opus in the style: the transmitted data is encrypted with the client's open SSH key, and decrypted as a private one, or: the RSA algorithm is used to encrypt the data.
I will try to bring some clarity to the work of the SSH protocol, and at the same time consider the role of the RSA algorithm and user authorization keys ...
The SSH protocol algorithm can be divided into three levels, each of which is located above the previous one: transport (opening a secure channel), authentication, connection. For the integrity of the picture, I will also add the network connection setup level, although officially this level is below SSH.
1. Establish a TCP connection
I will not dwell on the principle of operation of the TCP / IP stack, since this topic is well documented in RuNet. If necessary, you can easily find information.
At this stage, the client connects to the server on the TCP port specified in the Port option (default: 22) in the server configuration file / etc / ssh / sshd_config.
2. Opening a secure channel
2.1 Identity Exchange
After the TCP connection is established, the client and the server (hereinafter referred to as the parties) exchange the SSH protocol versions and other auxiliary data necessary to determine the compatibility of the protocols and to select the operation algorithms.
2.2 Selection of algorithms: key exchange, encryption, compression, etc.
When SSH is used, quite a few algorithms are used, some of them are used for encryption, the second for key exchange, the third for compressing transmitted data, etc. At this step, the parties send each other lists of supported algorithms, the highest priority is given to the algorithms at the top of each list. Then compare the algorithms in the received lists with the algorithms available in the system, and select the first matched one in each list.
The list of available client-side key exchange algorithms (used to obtain a session key) can be viewed with the command:
ssh -Q kex
The list of symmetric algorithms available in the system (used to encrypt the channel):
ssh -Q cipher
The list of key types for authorization at the client:
ssh -Q key-cert
Added on the remark onix74 :
All the commands used in the publication are relevant to the version of OpenSSH 7.6 from Ubuntu 18.04 LTS.
2.3 Obtaining a session encryption key
The process of obtaining a session key may differ depending on the version of the algorithm, but in general terms it comes down to the following:
- The server sends its key to the client (DSA, RSA or the like according to the agreement between the parties produced in clause 2.2).
- If the client connects to this server for the first time (as indicated by the absence of an entry in the /home/username/.ssh/known_hosts file at the client), then the user will be asked to trust the server key. If the connection with this server has already been established, then the client compares the sent key with the key recorded in /home/username/.ssh/known_hosts. If the keys do not match, the user will receive a warning about a possible hacking attempt. However, you can skip this check if you call ssh with the StrictHostKeyChecking option:
Also, if the user needs to delete the old server key (for example, when there is an exact certainty that the key has been changed on the server), the command is used:ssh -o StrictHostKeyChecking=no username@servername
ssh-keygen -R servername
- As soon as the client has decided on trust in the server key, using one of the implementations (the version is defined in clause 2.2) of the Diffie-Hellman algorithm, the client and server generate a session key that will be used for symmetric channel encryption.
The session key is created exclusively for the period of the channel's life and is destroyed when the connection is closed.
3. Client Authentication
And only now, when the client and the server have established a channel for encrypted data transfer, can they authenticate by password or key.
In general, authentication using keys is as follows:
- The client sends the username (username) and its public key to the server.
- The server checks in the file /home/username/.ssh/authorized_keys the presence of the public key sent by the client. If the public key is found, the server generates a random number and encrypts it with the client's public key, after which the result is sent to the client.
- The client decrypts the message with its private key and sends the result to the server.
- The server checks the result for a match with the number that it originally encrypted with the client’s public key, and if a match occurs, it considers the authentication successful.
4. Connection Level
After carrying out all the above procedures, the user is able to send commands to the server or copy files.
At this level, the following is provided: channel multiplication (the ability of multiple channels to work on a single server by combining them into one channel), tunneling, etc.
From theory to practice
Well, now, I think, readers have quite a legitimate question: why do we need to know all these subtleties of the SSH protocol, if for everyday work there is enough knowledge of key creation commands (ssh-keygen), opening a terminal session (ssh), transferring files ( scp)?
As a response, you can recall the topic of changing the standard SSH port to another one, which constantly becomes the cause of holivar on Habr ...
In my own practice, I don’t remember a single server looking to the external network that would not be daily slapped to port 22. In a situation if SSH works on a standard port for you (and is not additionally protected by anything), even if authentication using keys only and no password selections do not frighten you, the server is still forced to do a lot of useless work because of constant requests from unscrupulous clients: establish a TCP connection, select algorithms, generate a session key, send authentication requests, write a log file.
In a situation where there is nothing on port 22, or the port is protected using iptables (or add-ons of the fail2ban type), then the attacker will be dropped at the stage of establishing a TCP connection.
The most interestingly described looks like a table *
Configuration | Probability of hacking | Losses from flooding ** |
---|---|---|
Port 22, password authentication, without protection | high | high |
Port 22, authorization by keys, without protection | average *** | high |
Port 22, key authorization, protection based on limiting failed authorization attempts | low | average **** |
Non-standard port, password authentication, unprotected | high | low |
Non-standard port, authorization by keys, without protection | average *** | low |
Non-standard port, key authorization, protection based on limiting failed authorization attempts | low | low |
* - the values of the parameters (high, medium, low) are relative and serve only to compare indicators.
** - meaning the consumption of server resources (processor, disk, network channel, etc.) for processing an avalanche of requests, usually going to port 22.
*** - hacking, if RSA-keys are used for authorization, is very difficult, but an unlimited number of authorization attempts makes this possible.
**** - the number of authorization attempts is limited, but the server still has to process them from a large number of intruders.