Establishing an SSH connection to a remote service involves multiple stages. Each one of these stages will use some form of encryption, and there are configuration settings that control which cryptographic algorithms can be used at each step.
The default selection of algorithms for each stage should be good enough for the majority of deployment scenarios. Sometimes, however, a compliance rule, or a set of legacy servers, or something else, requires a change in this selection. Perhaps a legacy system or piece of hardware that is still in production is not compatible with the current encryption schemes and requires legacy algorithms to be enabled again. Or a compliance rule that isn’t up-to-date with the current crypto standards doesn’t allow a more advanced cipher.
Be careful when restricting cryptographic algorithms in SSH, specially on the server side. You can inadvertently lock yourself out of a remote system!
Algorithm configuration general rules
Most of the configuration options that take a list of cryptographic algorithms follow a defined set of rules. The first algorithm in the list that the client offers to the server, which matches an offer from the server, is what will be selected. The rules are as follows:
The lists are algorithm names separated by commas. For example,
Ciphers firstname.lastname@example.org,email@example.com replace the current set of ciphers with the two named algorithms.
Instead of specifying the full list, which will replace the existing default one, some manipulations are allowed. If the list starts with:
The specified algorithm(s) will be appended to the end of the default set. For example,
MACs +hmac-sha2-512,hmac-sha2-256will append both Message Authentication Code (MAC) algorithms to the end of the current set.
The specified algorithm(s) will be removed from the default set. For example,
KexAlgorithms -diffie-hellman-group1-sha1,diffie-hellman-group14-sha1will remove both key exchange algorithms from the current set.
The specified ciphers will be placed at the beginning of the default set. For example,
PubkeyAcceptedAlgorithms ^ssh-ed25519,ecdsa-sha2-nistp256will move both signature algorithms to the start of the set.
*) are also allowed, but be careful to not inadvertently include or exclude something that wasn’t intended.
With rare exceptions, the list of algorithms can be queried by running
ssh -Q <config>, where
<config> is the configuration setting name. For example,
ssh -Q ciphers will show the available list of ciphers.
The output of the
ssh -Q <name>command will not take into consideration the configuration changes that may have been made. It cannot therefore be used to test the crypto configuration changes.
It’s not the goal of this documentation to repeat the excellent upstream documentation (see references). Instead, we will show the configuration options, and some examples of how to use them.
Here are the configuration settings that control the cryptographic algorithms selection. Unless otherwise noted, they apply to both the server and the client.
List of symmetric ciphers. Examples include
List of Message Authentication Code algorithms, used for data integrity protection. The
-etmversions calculate the MAC after encryption and are considered safer. Examples include
This option is not available in OpenSSH upstream, and is provided via a patch that Ubuntu and many other Linux Distributions carry. It lists the key exchange (kex) algorithms that are offered for Generic Security Services Application Program Interface (GSSAPI) key exchange, and only applies to connections using GSSAPI. Examples include
List of available key exchange (kex) algorithms. Examples include
This is a server-only configuration option. It lists the available host key signature algorithms that the server offers. Examples include
List of signature algorithms that will be accepted for public key authentication. Examples include
List of algorithms that certificate authorities (CAs) are allowed to use to sign certificates. Certificates signed using any other algorithm will not be accepted for public key or host-based authentication. Examples include
To check what effect a configuration change has on the server, it’s helpful to use the
-T parameter and
grep the output for the configuration key you want to inspect. For example, to check the current value of the
Ciphers configuration setting after having set
Ciphers ^3des-cbc in
$ sudo sshd -T | grep ciphers ciphers 3des-cbc,firstname.lastname@example.org,aes128-ctr,aes192-ctr,aes256-ctr,email@example.com,firstname.lastname@example.org
The output will include changes made to the configuration key. There is no need to restart the service.
Here are some examples of how the cryptographic algorithms can be selected in OpenSSH.
Which cipher was used?
One way to examine which algorithm was selected is to add the
-v parameter to the
For example, assuming password-less public key authentication is being used (so no password prompt), we can use this command to initiate the connection and exit right away:
$ ssh -v <server> exit 2>&1 | grep "cipher:" debug1: kex: server->client cipher: email@example.com MAC: <implicit> compression: none debug1: kex: client->server cipher: firstname.lastname@example.org MAC: <implicit> compression: none
In the above case, the
chacha20 cipher was automatically selected. We can influence this decision and only offer one algorithm:
$ ssh -v -c aes128-ctr <server> exit 2>&1 | grep "cipher:" debug1: kex: server->client cipher: aes128-ctr MAC: email@example.com compression: none debug1: kex: client->server cipher: aes128-ctr MAC: firstname.lastname@example.org compression: none
For the other stages in the
ssh connection, like key exchange, or public key authentication, other expressions for the
grep command have to be used. In general, it will all be visible in the full
Remove AES 128 from server
Let’s configure an OpenSSH server to only offer the AES 256 bit variant of symmetric ciphers for an
First, let’s see what the default is:
$ sudo sshd -T | grep ciphers ciphers email@example.com,aes128-ctr,aes192-ctr,aes256-ctr,firstname.lastname@example.org,email@example.com
Now let’s make our change. On the server, we can edit
/etc/ssh/sshd_config and add this line:
And then check what is left:
$ sudo sshd -T | grep ciphers ciphers firstname.lastname@example.org,aes192-ctr,aes256-ctr,email@example.com
To activate the change,
ssh has to be restarted:
$ sudo systemctl restart ssh.service
After we restart the service, clients will no longer be able to use AES 128 to connect to it:
$ ssh -c aes128-ctr <server> Unable to negotiate with 10.0.102.49 port 22: no matching cipher found. Their offer: firstname.lastname@example.org,aes192-ctr,aes256-ctr,email@example.com
Prioritize AES 256 on the client
If we just want to prioritise a particular cipher, we can use the “
^” character to move it to the front of the list, without disabling any other cipher:
$ ssh -c ^aes256-ctr -v <server> exit 2>&1 | grep "cipher:" debug1: kex: server->client cipher: aes256-ctr MAC: firstname.lastname@example.org compression: none debug1: kex: client->server cipher: aes256-ctr MAC: email@example.com compression: none
In this way, if the server we are connecting to does not support AES 256, the negotiation will pick up the next one from the list. If we do that on the server via
Ciphers -aes256*, this is what the same client, with the same command line, now reports:
$ ssh -c ^aes256-ctr -v <server> exit 2>&1 | grep "cipher:" debug1: kex: server->client cipher: firstname.lastname@example.org MAC: <implicit> compression: none debug1: kex: client->server cipher: email@example.com MAC: <implicit> compression: none