SSH Hardening


Disclaimer: I am not qualified to give advice on security. If you make any changes, you are doing so on your own, at your own risk.

The other day I learnt about something called SSH hardening. It is about removing potential weak ciphers and algorithms so SSH connections will hopefully be the most secure they can be.

I also learnt there is something called the Terrapin attack against SSH when using either “ChaCha20-Poly1305” or “CBC with Encrypt-then-MAC”, which can possibly lower the security of the connection. It seems to require a “Man-in-the-middle” to intercept packets when establishing the connection, at which point it is possible to insert some packets to lower the security of the connection.

I absolutely cannot give any advice here as this is way above my head, but I found sshaudit.com which maybe can. They also provide SSH hardening guides.

If you have an SSH server open to the world you can enter its IP address on their page, and they will check for weak ciphers and give recommendations on what to change. They can also check your SSH client by providing a random port on their servers you can connect to, then check what ciphers and algorithms are offered and provide advice on what to do.

As I have servers only I connect to, and I only use OpenSSH on both the servers and the clients, I’ve restricted my setup even further from their advice. Though if that actually helps security or just hurts it, I really cannot tell. This is something I wish I knew more about but I think needs a rather long study of mathematics to understand. You should do your own investigation and due dilligence before making any changes.

There are patches available for the terrapin attack so given I control both the server and the client I will continue using “ChaCha20-Poly1305”. You should maybe not, but that is up to you to decide.

Since I only use ed25519 keys when generating SSH keys, I’ve uncommented only the ed25519 line in the host keys section in the server /etc/ssh/sshd_config file:

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

Then I’ve added the following line to the config to restrict ciphers, key- exchange algorithms and such:

KexAlgorithms [email protected],curve25519-sha256,[email protected]
Ciphers [email protected],[email protected],aes256-ctr
MACs [email protected],[email protected]
HostKeyAlgorithms ssh-ed25519

Fedora for instance will have Include statements in their configuration files which can override whatever configuration you put in, depending on where you put it, so you need to investigate this to make sure your changes actually take effect.

It seems recommended to keep RSA, possibly for compatibility reasons, but it did not seem to be used for me so I removed it.

To check what servers and client agree on, use “ssh -vv” when connecting to the server. It will give output similar to this:

debug2: local client KEXINIT proposal
debug2: KEX algorithms: [email protected],curve25519-sha256,[email protected],ext-info-c,[email protected]
debug2: host key algorithms: ssh-ed25519
debug2: ciphers ctos: [email protected],[email protected],aes256-ctr
debug2: ciphers stoc: [email protected],[email protected],aes256-ctr
debug2: MACs ctos: [email protected],[email protected]
debug2: MACs stoc: [email protected],[email protected]
debug2: peer server KEXINIT proposal
debug2: KEX algorithms: [email protected],curve25519-sha256,[email protected],ext-info-s,[email protected]
debug2: host key algorithms: ssh-ed25519
debug2: ciphers ctos: [email protected],[email protected],aes256-ctr
debug2: ciphers stoc: [email protected],[email protected],aes256-ctr
debug2: MACs ctos: [email protected],[email protected]
debug2: MACs stoc: [email protected],[email protected]

And then:

debug1: kex: algorithm: [email protected]
debug1: kex: host key algorithm: ssh-ed25519
debug1: kex: server->client cipher: [email protected] MAC: <implicit> compression: none
debug1: kex: client->server cipher: [email protected] MAC: <implicit> compression: none

Here it seems the client and server agreed on using sntrup761x25519-sha512 for the key exchange algorithm, ssh-ed25519 for the host key algorithm and chacha20-poly1305 for the cipher, which is in line with my configuration.

The same configuration added to sshd_config can be added to ssh_config to restrict what the client will use. Be aware though that users can override this when connecting to whatever server they connec to when they connect. So even if you have this in your ssh_config:

KexAlgorithms [email protected],curve25519-sha256,[email protected]
Ciphers [email protected],[email protected],aes256-ctr
MACs [email protected],[email protected]
HostKeyAlgorithms ssh-ed25519

Users can try connect from this server with this configuration to wherever else with a weaker cipher like so:

$ ssh -c aes128-cbc user@hostname

So ssh_config is only advisory. If the server doesn’t support this cipher, the connection will not succeed:

Unable to negotiate with 10.0.0.1 port 22: no matching cipher found.
Their offer: [email protected],[email protected],
aes256-ctr