OpenSSH usually comes with a default configuration which provides high compatibility. So even old clients can still connect. However, this compatibility comes at a price because some of the ciphers / algorithms used may be open to vulnerabilities. If you want to strengthen the encryption and get an overview about known vulnarabilities with your OpenSSH Server or Client configuration, ssh-audit is for you.
Notes & Based upon
My SSH settings / configuration uses the Mozilla Security Guidelines on OpenSSH as a base. Then I refined this using the findings of ssh-audit and the SSH-Audit SSH Hardening Guides.
You can restrict the users who are allowed to SSH to your system using the Parameter AllowUsers. I would recommend to explicitely set the users who should be able to use SSH. You should not allow RootLogin nor password authentication. So the following settings may be of use for you:
AuthenticationMethods publickey
PermitRootLogin no
# AllowUsers replace-with-your-usernames,separate-by-comma
Installation
First of all you can install ssh-audit by apt-get install ssh-audit but I strongly recommend against this. Because the version in Debian’s Package Repositories is old. When I wrote this article, ssh-audit was at version 2.5.0. However the current version is 3.0.1. 2.50 did list one of the algorithms as unknown. Hence, if you really want something which tells you if your algorithms are weak – you need to keep ssh-audit up to date.
I installed ssh-audit using pip3. You may use pip3 (ssh-audit is 3.0.1), snap (no idea about the version in snap), alternatively you may get ssh-audit on github.
Usage
Server
Once you installed ssh-audit you can simply test your SSH Server by typing ssh-audit localhost. A default SSH Configuration in Debian 12 Bookworm will lead to the following result:
# general (gen) banner: SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2 (gen) software: OpenSSH 9.2p1 (gen) compatibility: OpenSSH 8.5+, Dropbear SSH 2018.76+ (gen) compression: enabled (zlib@openssh.com) # key exchange algorithms (kex) sntrup761x25519-sha512@openssh.com -- [info] available since OpenSSH 8.5 (kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76 `- [info] default key exchange since OpenSSH 6.4 (kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.4, Dropbear SSH 2013.62 `- [info] default key exchange since OpenSSH 6.4 (kex) ecdh-sha2-nistp256 -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 (kex) ecdh-sha2-nistp384 -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 (kex) ecdh-sha2-nistp521 -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 (kex) diffie-hellman-group-exchange-sha256 (3072-bit) -- [info] available since OpenSSH 4.4 `- [info] OpenSSH's GEX fallback mechanism was triggered during testing. Very old SSH clients will still be able to create connections using a 2048-bit modulus, though modern clients will use 3072. This can only be disabled by recompiling the code (see https://github.com/openssh/openssh-portable/blob/V_9_4/dh.c#L477). (kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73 (kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3 (kex) diffie-hellman-group14-sha256 -- [warn] 2048-bit modulus only provides 112-bits of symmetric strength `- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73 (kex) kex-strict-s-v00@openssh.com -- [info] pseudo-algorithm that denotes the peer supports a stricter key exchange method as a counter-measure to the Terrapin attack (CVE-2023-48795) # host-key algorithms (key) rsa-sha2-512 (2048-bit) -- [warn] 2048-bit modulus only provides 112-bits of symmetric strength `- [info] available since OpenSSH 7.2 (key) rsa-sha2-256 (2048-bit) -- [warn] 2048-bit modulus only provides 112-bits of symmetric strength `- [info] available since OpenSSH 7.2 (key) ecdsa-sha2-nistp256 -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency `- [warn] using weak random number generator could reveal the key `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 (key) ssh-ed25519 -- [info] available since OpenSSH 6.5 # encryption algorithms (ciphers) (enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5 `- [info] default cipher since OpenSSH 6.9 (enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52 (enc) aes192-ctr -- [info] available since OpenSSH 3.7 (enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52 (enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2 (enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2 # message authentication code algorithms (mac) umac-64-etm@openssh.com -- [warn] using small 64-bit tag size `- [info] available since OpenSSH 6.2 (mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2 (mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2 (mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2 (mac) hmac-sha1-etm@openssh.com -- [fail] using broken SHA-1 hash algorithm `- [info] available since OpenSSH 6.2 (mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode `- [warn] using small 64-bit tag size `- [info] available since OpenSSH 4.7 (mac) umac-128@openssh.com -- [warn] using encrypt-and-MAC mode `- [info] available since OpenSSH 6.2 (mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56 (mac) hmac-sha2-512 -- [warn] using encrypt-and-MAC mode `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56 (mac) hmac-sha1 -- [fail] using broken SHA-1 hash algorithm `- [warn] using encrypt-and-MAC mode `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 # fingerprints (fin) ssh-ed25519: SHA256:--- (fin) ssh-rsa: SHA256:--- # algorithm recommendations (for OpenSSH 9.2) (rec) -ecdh-sha2-nistp256 -- kex algorithm to remove (rec) -ecdh-sha2-nistp384 -- kex algorithm to remove (rec) -ecdh-sha2-nistp521 -- kex algorithm to remove (rec) -ecdsa-sha2-nistp256 -- key algorithm to remove (rec) -hmac-sha1 -- mac algorithm to remove (rec) -hmac-sha1-etm@openssh.com -- mac algorithm to remove (rec) !rsa-sha2-256 -- key algorithm to change (increase modulus size to 3072 bits or larger) (rec) !rsa-sha2-512 -- key algorithm to change (increase modulus size to 3072 bits or larger) (rec) -diffie-hellman-group14-sha256 -- kex algorithm to remove (rec) -hmac-sha2-256 -- mac algorithm to remove (rec) -hmac-sha2-512 -- mac algorithm to remove (rec) -umac-128@openssh.com -- mac algorithm to remove (rec) -umac-64-etm@openssh.com -- mac algorithm to remove (rec) -umac-64@openssh.com -- mac algorithm to remove # additional info (nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html> (nfo) Be aware that, while this target properly supports the strict key exchange method (via the kex-strict-?-v00@openssh.com marker) needed to protect against the Terrapin vulnerability (CVE-2023-48795), all peers must also support this feature as well, otherwise the vulnerability will still be present. The following algorithms would allow an unpatched peer to create vulnerable SSH channels with this target: chacha20-poly1305@openssh.com. If any CBC ciphers are in this list, you may remove them while leaving the *-etm@openssh.com MACs in place; these MACs are fine while paired with non-CBC cipher types.
This does not look too good, right? First I would disable all too short moduli as explained in the Mozilla Security Guidelines as well as the SSH-Audit Hardening Guide. You can do so by issuing:
awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv /etc/ssh/moduli.tmp /etc/ssh/moduli
Then I would re-create the Host-Keys with more strong settings as explained in the SSH-Audit Hardening Guide:
rm /etc/ssh/ssh_host_*
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
This will already reduce the recommendations to:
# algorithm recommendations (for OpenSSH 9.2) (rec) -ecdh-sha2-nistp256 -- kex algorithm to remove (rec) -ecdh-sha2-nistp384 -- kex algorithm to remove (rec) -ecdh-sha2-nistp521 -- kex algorithm to remove (rec) -hmac-sha1 -- mac algorithm to remove (rec) -hmac-sha1-etm@openssh.com -- mac algorithm to remove (rec) -diffie-hellman-group14-sha256 -- kex algorithm to remove (rec) -hmac-sha2-256 -- mac algorithm to remove (rec) -hmac-sha2-512 -- mac algorithm to remove (rec) -umac-128@openssh.com -- mac algorithm to remove (rec) -umac-64-etm@openssh.com -- mac algorithm to remove (rec) -umac-64@openssh.com -- mac algorithm to remove
I was using the Mozilla Security Guidelines as a Base and then added and removed algorithms from the list using the output of ssh-audit. The result is the following file which I stored in /etc/ssh/sshd_config.d/ciphers.conf
# Ciphers
HostKeyAlgorithms -ecdsa-sha2-nistp256
KexAlgorithms curve25519-sha256@libssh.org,curve25519-sha256,sntrup761x25519-sha512@openssh.com,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
Now when I issue ssh-audit again I get the following result:
# general (gen) banner: SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2 (gen) software: OpenSSH 9.2p1 (gen) compatibility: OpenSSH 8.5+, Dropbear SSH 2018.76+ (gen) compression: enabled (zlib@openssh.com) # key exchange algorithms (kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.4, Dropbear SSH 2013.62 `- [info] default key exchange since OpenSSH 6.4 (kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76 `- [info] default key exchange since OpenSSH 6.4 (kex) sntrup761x25519-sha512@openssh.com -- [info] available since OpenSSH 8.5 (kex) diffie-hellman-group-exchange-sha256 (3072-bit) -- [info] available since OpenSSH 4.4 `- [info] OpenSSH's GEX fallback mechanism was triggered during testing. Very old SSH clients will still be able to create connections using a 2048-bit modulus, though modern clients will use 3072. This can only be disabled by recompiling the code (see https://github.com/openssh/openssh-portable/blob/V_9_4/dh.c#L477). (kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73 (kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3 (kex) kex-strict-s-v00@openssh.com -- [info] pseudo-algorithm that denotes the peer supports a stricter key exchange method as a counter-measure to the Terrapin attack (CVE-2023-48795) # host-key algorithms (key) rsa-sha2-512 (4096-bit) -- [info] available since OpenSSH 7.2 (key) rsa-sha2-256 (4096-bit) -- [info] available since OpenSSH 7.2 (key) ssh-ed25519 -- [info] available since OpenSSH 6.5 # encryption algorithms (ciphers) (enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5 `- [info] default cipher since OpenSSH 6.9 (enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2 (enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2 (enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52 (enc) aes192-ctr -- [info] available since OpenSSH 3.7 (enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52 # message authentication code algorithms (mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2 (mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2 (mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2 # fingerprints (fin) ssh-ed25519: SHA256:--- (fin) ssh-rsa: SHA256:--- # additional info (nfo) Be aware that, while this target properly supports the strict key exchange method (via the kex-strict-?-v00@openssh.com marker) needed to protect against the Terrapin vulnerability (CVE-2023-48795), all peers must also support this feature as well, otherwise the vulnerability will still be present. The following algorithms would allow an unpatched peer to create vulnerable SSH channels with this target: chacha20-poly1305@openssh.com. If any CBC ciphers are in this list, you may remove them while leaving the *-etm@openssh.com MACs in place; these MACs are fine while paired with non-CBC cipher types.
Did you notice, that in the top of the ssh-audit there are these lines:
# general (gen) banner: SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2 (gen) software: OpenSSH 9.2p1 (gen) compatibility: OpenSSH 8.5+, Dropbear SSH 2018.76+ (gen) compression: enabled (zlib@openssh.com)
Add another file e.g. other.conf in /etc/ssh/sshd_config.d/ with the following content:
# the default is none.
Banner none
# the default is yes.
DebianBanner no
# general (gen) banner: SSH-2.0-OpenSSH_9.2p1 (gen) software: OpenSSH 9.2p1 (gen) compatibility: OpenSSH 8.5+, Dropbear SSH 2018.76+ (gen) compression: enabled (zlib@openssh.com)
Client
The client is even worse; because the client has much more algorithms allowed for compatibility than the server. This may be good like this – because it allows to access very old / badly configured systems. I would still suggest that you also use a strong default set of algorithms for your clients – you may offer specific more weak settings for a specific server using your .ssh/config together with a host-specific configuration/override.
Again I use the configuration from the Mozilla Security Guidelines and then I use ssh-audit for the fine-tuning. For that just run ssh-audit with the parameter -c. You can do this on your server or locally. It will start an SSH-Session on port 2222 (So I hope you don’t use that port) and wait for your client’s ssh connection. So just ssh to localhost -p 2222 if you started it locally.
When going through all the recommendations the resulting SSH configuration for my client (.ssh/config) looked like this:
# Ensure KnownHosts are unreadable if leaked - it is otherwise easier to know
# which hosts your keys have access to.
HashKnownHosts yes
# Host keys the client accepts - order here is honored by OpenSSH
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519
KexAlgorithms curve25519-sha256@libssh.org,curve25519-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
The resulting ssh-audit output, when I use my Chromebook’s Debian as a client:
# general
(gen) client IP: xx.xx.xx.xx
(gen) banner: SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u3
(gen) software: OpenSSH 8.4p1
(gen) compression: enabled (zlib@openssh.com, zlib)
# security
(cve) CVE-2021-36368 -- (CVSSv2: 3.7) trivial authentication attack to bypass FIDO tokens and SSH-ASKPASS
(cve) CVE-2021-28041 -- (CVSSv2: 7.1) double free via ssh-agent
# key exchange algorithms
(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.4, Dropbear SSH 2013.62
`- [info] default key exchange since OpenSSH 6.4
(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76
`- [info] default key exchange since OpenSSH 6.4
(kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
(kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3
(kex) diffie-hellman-group-exchange-sha256 -- [info] available since OpenSSH 4.4
(kex) ext-info-c -- [info] pseudo-algorithm that denotes the peer supports RFC8308 extensions
(kex) kex-strict-c-v00@openssh.com -- [info] pseudo-algorithm that denotes the peer supports a stricter key exchange method as a counter-measure to the Terrapin attack (CVE-2023-48795)
# host-key algorithms
(key) ssh-ed25519-cert-v01@openssh.com -- [info] available since OpenSSH 6.5
(key) ssh-ed25519 -- [info] available since OpenSSH 6.5
# encryption algorithms (ciphers)
(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5
`- [info] default cipher since OpenSSH 6.9
(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2
(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2
(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
(enc) aes192-ctr -- [info] available since OpenSSH 3.7
(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
# message authentication code algorithms
(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2
(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2
(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2
# algorithm recommendations (for OpenSSH 8.4)
(rec) +rsa-sha2-256 -- key algorithm to append
(rec) +rsa-sha2-512 -- key algorithm to append
# additional info
(nfo) Be aware that, while this target properly supports the strict key exchange method (via the kex-strict-?-v00@openssh.com marker) needed to protect against the Terrapin vulnerability (CVE-2023-48795), all peers must also support this feature as well, otherwise the vulnerability will still be present. The following algorithms would allow an unpatched peer to create vulnerable SSH channels with this target: chacha20-poly1305@openssh.com. If any CBC ciphers are in this list, you may remove them while leaving the *-etm@openssh.com MACs in place; these MACs are fine while paired with non-CBC cipher types
Now I just need to update my SSH Client version :^)
Update: 18th, February 2024
RKHunter
RKhunter’s check for PermitRootLogin is not checking the active ssh configuration (which means you simply can set PermitRootLogin no in /etc/ssh/sshd_config without restarting sshd and the RKhunter check will be fine) and RKhunter is not taking into account _all_ configuration which means it does not check /etc/ssh/sshd_config.d/ when performing the PermitRootLogin check. Which basically means even if you have PermitRootLogin no in /etc/ssh/sshd_config.d/auth.conf RKhunter will complain like below.
~# rkhunter -c --sk --rwo
Warning: The SSH configuration option 'PermitRootLogin' has not been set.
The default value may be 'yes', to allow root access.
In my configuration I limit ssh access to specific users (AllowUsers) and I commented PermitRootLogin in sshd_config while I set it to no in sshd_config.d/auth.conf. According to the Man page the default is prohibit password:
PermitRootLogin
Specifies whether root can log in using ssh(1). The argument must be yes,
prohibit-password, forced-commands-only, or no. The default is prohibit-password.
However, this default might change and hence the Warning of rkhunter is correct but it does not take additional configuration into account.
Lynis
The Lynis tool gives a few settings to consider for my SSH configuration. I put them into a configuration file which results in the following:
# * Consider hardening SSH configuration [SSH-7408]
# - Details : AllowTcpForwarding (set YES to NO)
# https://cisofy.com/lynis/controls/SSH-7408/
AllowTcpForwarding no
# * Consider hardening SSH configuration [SSH-7408]
# - Details : ClientAliveCountMax (set 3 to 2)
# https://cisofy.com/lynis/controls/SSH-7408/
ClientAliveCountMax 2
# * Consider hardening SSH configuration [SSH-7408]
# - Details : Compression (set YES to NO)
# https://cisofy.com/lynis/controls/SSH-7408/
Compression No
# * Consider hardening SSH configuration [SSH-7408]
# - Details : LogLevel (set INFO to VERBOSE)
# https://cisofy.com/lynis/controls/SSH-7408/
LogLevel Verbose
# * Consider hardening SSH configuration [SSH-7408]
# - Details : MaxSessions (set 10 to 2)
# https://cisofy.com/lynis/controls/SSH-7408/
MaxSessions 2
# * Consider hardening SSH configuration [SSH-7408]
# - Details : Port (set 22 to )
# https://cisofy.com/lynis/controls/SSH-7408/
Port 2222
# * Consider hardening SSH configuration [SSH-7408]
# - Details : TCPKeepAlive (set YES to NO)
# https://cisofy.com/lynis/controls/SSH-7408/
TCPKeepAlive no
# * Consider hardening SSH configuration [SSH-7408]
# - Details : AllowAgentForwarding (set YES to NO)
# https://cisofy.com/lynis/controls/SSH-7408/
AllowAgentForwarding no
Do not use these settings blindly. You may however consider (some of) these settings.
I doubt they increase security by much. Let’s take the Port for example: If you change the port from 22 to 2222 or from 22 to 33 or to some other port nobody knows, you’ll just stop some silly bots to try to bruteforce your SSH. But since you disabled password login it does not matter at all, right? And even if you were using password authentication (which I hope you don’t) then what stops an attacker from using a portscan / probing on which port ssh runs? You’ll make it a little bit more difficult, yeah. Extra security? I’m not sure.
Limiting the amount of sessions or increasing the log level will also not magically improve security.
Setting Compression to no is arguable. First of all, depending on your CPU, Network, and so on it might be faster to disable compression (yes). Setting Compression to no for security reasons on the other hand might only be useful with early OpenSSH versions. So if you nowadays (2024) run software from 2004 – go ahead, disable Compression. Because in 2005:
– Added a new compression method that delays the start of zlib compression until the user has been authenticated successfully. The new method (“Compression delayed”) is on by default in the server. This eliminates the risk of any zlib vulnerability leading to a compromise of the server from unauthenticated users. NB. Older OpenSSH (<3.5) versions have a bug that will cause them to refuse to connect to any server that does not offer compression when the client has compression requested. Since the new “delayed” server mode isn’t supported by these older clients, they will refuse to connect to a new server unless compression is disabled (on the client end) or the original compression method is enabled on the server (“Compression yes” in sshd_config)
OpenSSH 4.2 was released on 2005-09-01. https://www.openssh.com/txt/release-4.2
And then in 2016:
* sshd(8): Remove support for pre-authentication compression. Doing compression early in the protocol probably seemed reasonable in the 1990s, but today it’s clearly a bad idea in terms of both cryptography (cf. multiple compression oracle attacks in TLS) and attack surface. Pre-auth compression support has been disabled by default for >10 years. Support remains in the client.
OpenSSH 7.4 was released on 2016-12-19. https://www.openssh.com/txt/release-7.4
So disabling compression for security reasons in OpenSSH? I don’t think this offers additional security 🙂 However – You should check (manpage) what these settings do and consider to use (some of) them. Just as I wrote before: don’t use settings blindly.