Securing a SSH Server

Categories:

in

Secure Shell is a prime target for any attacker wanting to gain access to your machine, the default configuration is reasonably secure, but there is plenty of room for improvement, this is particularly important when setting up a machine for the first time over SSH, attacks can and do occur within hours so securing it must be done quickly.

Strong password

You would think that this is pretty obvious, but it’s still surprising how often people choose weak passwords, you generally don’t need to go over the top with them to be secure against attack, a few basic guidelines are:

  • Use at least 8 characters
  • Do not use any common words
  • Add numbers and or symbols
  • Do not reuse passwords
  • Preferably use a password manager (I.E keepass)

Public key authentication

Public key authentication allows you to avoid using passwords entirely, which is very convenient, this is done by generating a key pair on your machine, which consists of a public key and a private key, the public key is added to the authorized_keys file on the server, typically ‘~/.ssh/authorized_keys’ for a specific user, the users SSH client then authenticates by decrypting a challenge that is sent by the server using their public key, this ensures that only the person with the matching private key can login.

The most obvious downside to this is you need to keep the private key safe, you can optionally add a passphrase during key creation for more security but on the whole using public key authentication without a password is safer than just a regular password, password authentication can be disabled on the server making brute force attacks practically impossible.

The key pair is created by using the ssh-keygen program, a number of different cryptographic algorithms are available but for optimal security RSA 4096 bit and ed25519 are the only choices I would recommend, the latter is preferred due to the smaller key size and greater speed, but may not be compatible with all software.

ssh-keygen -b 4096 -t rsa
ssh-keygen -t ed25519

Here is an example of generating a SSH key pair:

ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519): ~/.ssh/test_ed25519
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in test.
Your public key has been saved in test.pub.
The key fingerprint is:
SHA256:k1mQZaxnwsaoQlOZtAWSnyisZhOSK1i8qPp3m0eRhqw test@hostname
The key\'s randomart image is:
+--[ED25519 256]--+
|  .oo+. .+o      |
|  ..+o  .o.      |
|.o +.o = o.      |
|+o* o + X+o      |
|+*.o o oS=       |
|*+o E   ..       |
|= ..   .         |
|.   . ...        |
|o... .oo         |
+----[SHA256]-----+

Windows users can use Putty to generate keys and perform other SSH operations.

This will generate ‘~/.ssh/test_ed25519’ and ‘~/.ssh/test_ed25519.pub’, the public key ‘test_ed25519.pub’ can then be added to the server, either manually or using the ssh-copy-id program which requires establishing a regular SSH connection, for example:

ssh-copy-id -i test_ed22519.pub remote_server.com

If the remote user is different from the local user simply use user@remote_server.com instead, if you have password authentication disabled this method is not possible. Here is an example of the manual method with root connecting and the test user account already existing.

scp ~/.ssh/test_ed25519.pub root@remote_server.com:/home/test/
ssh root@remote_server.com
mkdir -m 700 /home/test/.ssh
chown test:test /home/test/.ssh
cat /home/test/test_ed25519.pub >> /home/test/.ssh/authorized_keys
chmod 600 /home/test/.ssh/authorized_keys
chown test:test /home/test/.ssh/authorized_keys
rm /home/test/test_ed25519.pub

This does the following:

  • Transfer public key to ‘/home/test’ on the remote server via Secure CoPy (SCP)
  • Connect to remote server as root
  • Create the .ssh directory and set permission
  • Copy the public key in to the authorized_keys file and set permission
  • Remove the public key file

Once that is done the user can connect to the remote server, if the private key is in ~/.ssh and named id_ed25519 (or as appropriate) it will be automatically used, alternatively it can be specified manually with the -i argument, if the key requires a pass phrase you will be prompted for it.

Disable password authentication

This is strongly recommended once you have public key authentication setup, simply add the following to /etc/ssh/sshd_config and restart the daemon with systemctl restart sshd

PasswordAuthentication no

Use Sshguard

If you really need to have password logins enabled it is strongly recommended you use sshguard, this program monitors login attempts and can ban temporarily or permanently if there are too many failures, it supports a number of firewalls including the easy to use ufw, you can read more about configuring it here.

Use strong encryption

Without going in to extensive detail the following algorithms have been chosen with maximum security in mind, weak ones are not included it all.

Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr,aes256-cbc

KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

MACs umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

Note: The space between lines is important!

Disable root login

Having root login enabled is completely unnecessary, if you need root access you can use su or sudo from a regular user.

PermitRootLogin no

Disable forwarding

If you are not using features like X11 forwarding, ssh-agent forwarding and so on you can and should disable them, you can do this individually or disable all forwarding with:

DisableForwarding yes

Change server port

Using the default port 22 is essentially waving a big red flag, unless you have a specific reason to stick to port 22 you should use something else, this is much less useful if you have other common services running on the same server like HTTP.

Conclusion

There are a few more options that can be used to improve security so I suggest reading the sshd and sshd_config man pages, however for the vast majority of users this is more than sufficient to guarantee security against most attacks.

Below is a full example sshd_config:

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

Port 22
#Port 12400
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

# Use 'sudo ssh-keygen -A' to generate default keys
HostKey /etc/ssh/ssh_host_ed25519_key
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
PermitEmptyPasswords no
PermitRootLogin no
ChallengeResponseAuthentication no

UsePAM yes
DisableForwarding yes
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr,aes256-cbc

KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

MACs umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

# override default of no subsystems
Subsystem sftp /usr/lib/ssh/sftp-server