Secure SSH Setup

What is SSH and how can we secure it.

Previously I posted on how to make some changes to SSL to improve it’s security for your users. This post I want to cover off some information on how to setup SSH to secure your server for yourself.

what is it?

Secure Shell (SSH) is a cryptographic network protocol for secure data communication, remote command-line login, remote command execution, and other secure network services between two networked computers. It connects, via a secure channel over an insecure network, a server and a client running SSH server and SSH client programs, respectively. The protocol specification distinguishes between two major versions that are referred to as SSH-1 and SSH-2. The best-known application of the protocol is for access to shell accounts on Unix-like operating systems, but it can also be used in a similar fashion for accounts on Windows. It was designed as a replacement for Telnet and other insecure remote shell protocols such as the Berkeley rsh and rexec protocols, which send information, notably passwords, in plaintext, rendering them susceptible to interception and disclosure using packet analysis.

what to protect

SSH contains a number of attack vectors that we need to cover. It should be noted that to properly protect your access to servers you should protect your client and the server. Below I’ll give options that should be set on the computer doing the access and should be set on the remote server recieving the access request. By disallowing bad security within your SSH client you are able to defeat rogue servers from exposing key information that you should protect.

key exchange

When a ssh session is opened to a remote server the SSH session begins by agreeing on a shared key. This exchange happens via Diffie-Hellman and Elliptic Curve Diffie-Hellman. Both methods provide forward secrecy. Which as previously covered in my SSL post is required to ensure that the session can’t be passively recorded and later decrypted once servers private key has been collected.

OpenSSH supports 8 key exchange protocols:

  • ecdh-sha2-nistp256: ECDH over NIST P-256 with SHA2
  • ecdh-sha2-nistp384: ECDH over NIST P-384 with SHA2
  • ecdh-sha2-nistp521: ECDH over NIST P-521 with SHA2
  • diffie-hellman-group1-sha1: 1024 bit DH with SHA1
  • diffie-hellman-group14-sha1: 2048 bit DH with SHA1
  • diffie-hellman-group-exchange-sha1: Custom DH with SHA1
  • diffie-hellman-group-exchange-sha256: Custom DH with SHA2
  • curve25519-sha256: ECDH over Curve25519 with SHA2

The first 3 options are out due to failures with NIST curves. They leak secrets through timing side channels and off-curve inputs.

We should also elimate anything that uses SHA1.

This leaves us with diffie-hellman-group-exchange-sha256 and curve25519-sha256.

Recommended /etc/ssh/sshd_config snippet:

KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256

Recommended /etc/ssh/ssh_config snippet:

Host *
    KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256

We should also regenerate our moduli file via:

ssh-keygen -G "${HOME}/moduli" -b 4096
ssh-keygen -T /etc/ssh/moduli -f "${HOME}/moduli"


Now that we have a secure channel we need a way to authenticate. Firstly the server must prove it’s who it says it is. It does this by signing the key resulting from the key exchange. It has 4 different methods for this signing to occur.

  • DSA with SHA1
  • ECDSA with SHA256, SHA384 or SHA512 depending on key size
  • Ed25519 with SHA512
  • RSA with SHA1

We want to disable DSA (due to a limitation of keys needing to be 1024) and ECDSA due to them needing randomness for signatures. If our random function is poor it can lead to our keys being recoverable. We can however either use RSA or Ed25519.

Recommended /etc/ssh/sshd_config snippet:

Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

You should also now take this oppitunity to regenerate your SSH server keys.

cd /etc/ssh
rm ssh_host_*key*
ssh-keygen -t ed25519 -f ssh_host_ed25519_key < /dev/null
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null

The client must prove its identity to the server as well. There are various methods to do that.

The simplest is password authentication. This should be disabled immediately after setting up a more secure method because it allows compromised servers to steal passwords. Password authentication is also more vulnerable to online bruteforce attacks.

Recommended /etc/ssh/sshd_config snippet:

PasswordAuthentication no
ChallengeResponseAuthentication no

Recommended /etc/ssh/ssh_config snippet:

Host *
    PasswordAuthentication no
    ChallengeResponseAuthentication no

The most common and secure method is public key authentication, basically the same process as the server authentication.

Recommended /etc/ssh/sshd_config snippet:

PubkeyAuthentication yes

Recommended /etc/ssh/ssh_config snippet:

Host *
    PubkeyAuthentication yes
    HostKeyAlgorithms [email protected],[email protected],[email protected],ssh-ed25519,ssh-rsa

Generate client keys using the following commands:

ssh-keygen -t ed25519 -o -a 100
ssh-keygen -t rsa -b 4096 -o -a 100