Extreme SSH Hardening

Results from a Mozilla SSH Observatory Scan

SSH (Secure Shell) is a great tool, but if you ever expose SSH to the internet, you’ll soon discover a multitude of internet bots and bad actors pummeling your server.

There is a clever way of mitigating this attack vector passively. Some of you might know this already, but the idea is to configure SSH to maximum You can audit the SSH security of a website if the standard port 22 is exposed using The Mozilla Observatory Tool.

Warning: This will break legacy systems. Here’s an example of a /etc/ssh/sshd_config file in a nutshell.

HostKey /etc/ssh/ssh_host_ed25519_key
KexAlgorithms curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com
MACs hmac-sha2-512-etm@openssh.com

GSSAPIAuthentication no
UsePrivilegeSeparation sandbox

LogLevel VERBOSE
SyslogFacility AUTHPRIV
Subsystem sftp internal-sftp -f AUTHPRIV -l INFO

UsePAM yes
PrintMotd no
Compression no
PermitRootLogin no
PasswordAuthentication no
AuthenticationMethods publickey
ChallengeResponseAuthentication no
AuthorizedKeysFile .ssh/authorized_keys

A configuration like this prevents almost 99% of attackers from reaching or getting pass the negotiation stage. The most you’ll see in your system log is the following.

sshd: Connection from x.x.x.x port x on x.x.x.x port 22
sshd: Connection closed by x.x.x.x port x [preauth]
sshd: Connection from x.x.x.x port x on x.x.x.x port 22
sshd: Connection closed by x.x.x.x port x [preauth]

What did we do? First we let SSH support the most modern cipher, key exhange algorithm, and MAC (message authentication code). This is what kills legacy systems and also bots.

HostKey /etc/ssh/ssh_host_ed25519_key
KexAlgorithms curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com
MACs hmac-sha2-512-etm@openssh.com

Let it also log everything, including every file modified when you use SSH to mount a remote file system.

LogLevel VERBOSE
SyslogFacility AUTHPRIV
Subsystem sftp internal-sftp -f AUTHPRIV -l INFO

Force public key authentication only and deny root login.

PermitRootLogin no
PasswordAuthentication no
AuthenticationMethods publickey
ChallengeResponseAuthentication no

If you really need root login you can do something like this;

PermitRootLogin prohibit-password

Or activate this setting more strictly using match patterns.

Match Address 192.168.1.*,10.0.3.1
  PermitRootLogin prohibit-password

Updated 14 January 2020