Introduction

SSH is a widely used protocol to access remote devices. The problem with SSH is at the authentication stage, Brute force attacks are one of the ways an SSH connection can be compromised. A malicious actor will constantly hammer the remote host with different passwords until it can gain access. With further configuration of SSH we can make the service a lot more secure.

Configure SSH

Famous last words: Configuring SSH like many things in Linux is as simple as editing a few config files

Always be sure to create a backup file it’s very easy to end up locking yourself out of a device.

I would recommend practising on a machine that is not critical.

Create SSH Keys

SSH keys use public and private key encryption for authentication.

To create a set of keys, on the client do:

ssh-keygen

You will be asked where you want to save the keys, I recommend the
default location
for less hair pulling later.

Enter file in which to save the key (/home/user/.ssh/id_rsa):

You will be asked to enter a password for the ssh keys, be sure to use a strong password.

Enter passphrase (empty for no passphrase):

Once that is done you will see a confirmation screen like the one below

Output
Your identification has been saved in /home/user/.ssh/id_rsa
Your public key has been saved in /home/user/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:tIurljnWJRBc1RnHUJQ5GtND7p9HWKnjV6zjE9AFR1Y [email protected]
The key's randomart image is:
+---[RSA 3072]----+
|   . .....oX=o.oE|
|    o     =oB  oo|
|     .  .  +.+ o.|
|    .  . .... o+ |
|     .  S   .+. +|
|      ....  ..o+.|
|     +.o.    .=o.|
|    * ..     .oo |
|   o.o.       .. |
+----[SHA256]-----+

Copy SSH Keys

Quick note: [email protected] is the username on the remeote host you would like to copy your public key to.

ssh-copy-id [email protected]

If asked to confirm the connection to the remote host answer yes, this happens when a new machine with an unknown identity wants to connect to the client.

Output
The authenticity of host 'host(host)' can't be established.
ECDSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx.
Are you sure you want to continue connecting (yes/no)? yes

You will then be asked to enter a password for the user on the remote host

Output
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:

If successful you should be able to access the device using the SSH key

To verify this, SSH to the device and it should ask for the Keys’s password not the users

Enter passphrase for key '/home/user/.ssh/id_rsa':

Modify SSH Config

create a backup

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

open the original file in a text editor

sudo vim /etc/ssh/sshd_config

For a new user this might be daunting. Take your time and you will be fine 😊

Lines we want to modify

Quick note: you may need to uncomment some lines as well as add a few

  • Protocol 2 - add to line 15
  • Port 2222 - modify line 17
  • PermitRootLogin no - modify line 36
  • Max Auth Tries 5 - modify line 38
  • PasswordAuthentication no - modify line 60
  • PermitEmptyPasswords no -modify line 61
  • AllowUsers ahmza - add line 67
  • ClientAliveInterval 180 - modify line 104
#       $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $

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

# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Include /etc/ssh/sshd_config.d/*.conf

Protocol 2

Port 2222
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

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

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
PermitRootLogin no
#StrictModes yes
MaxAuthTries 5
#MaxSessions 10

#PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no

AllowUsers ahmza

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
ClientAliveInterval 180
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

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

# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server

Now lets explain what we just did

  • Protocol 2 - released in 2006, SSH2 introduced improved encryption algorithms.
  • Port 2222 - The port number can be whatever number you want. Choose something other than 22 this will help hide your device from malicious actors
  • PermitRootLogin no - If the root account were to be compromised then the attacker has full control of the system so we stop it from being able to log in.
  • MaxAuthTries 5 - After 5 failed attempts the remote host blocks requests from that IP for a period of time.
  • PasswordAuthentication no - We have the SSH key installed so we no longer need to have password authentication.
  • PermitEmptyPasswords no - We don’t want to allow empty passwords to be used as authentication for obvious reasons.
  • AllowUsers username - Add the usernames of users you want to be able to connect to the remote host and other users trying to connect will be dropped.
  • Client Alive Interval 180 - Drop the connection after a certain period of inactivity

Check were able to connect

restart sshd service

sudo systemctl restart sshd

Keep the current SSH connection open and create a new session.

If you are able to connect to the remote hosts then you are all set. If not then you still have the initial connection to the remote host to roll back the changes and troubleshoot.

Success

Setting up Fail2Ban

Fail2Ban is an intrusion prevention tool. Although we are slowing bots down with MaxAuthTries the attacker is still able to carry on brute forcing. Which is what Fail2Ban is for, it actually blocks the connections from that IP.

Install Fail2Ban

We will install Fail2Ban on the remote host First upgrade any packages, then install Fail2Ban

sudo apt update && sudo apt upgrade
sudo apt install fail2ban

Now we need to enable the service so it starts when the remote host starts

sudo systemctl enable --now fail2ban

Configure Fail2Ban

The Fail2Ban config file we want to edit is called jail.local located in /etc/fail2ban/ open jail.local in your editor of choice

sudo vim /etc/fail2ban/jail.local

The config for Fail2Ban is a lot shorter than sshd so this should be quick

[DEFAULT]
    bantime = 8h
    ignoreip = 127.0.0.1 <ip addresses to be ignored>
    ignoreself = true

[sshd]
    enabled = true
    port = 2222
    filter = sshd
    logpath = /var/log/auth.log
    maxretry = 3
    findtime = 10m

[Default] - Settings in here apply to all jails

  • bantime - how long the ban will last
  • ignoreip - IP addresses to ignore
  • ignoreself - stops from locking itself out

[sshd] - this is the jail for sshd

  • enabled - decides weather the jail is active or not
  • port - the port number the service
  • filter - tells the jail which filter to use from /etc/fail2ban/filter.d
  • logpath - where the log you want fail2ban to read is
  • maxretry - Times the client can attempt a login before being banned
  • findtime - An amount of time which maxretry must occur to trigger a ban for example in 10 minutes if 3 failed login attempts are made the ban the IP

Restart Fail2Ban to load the configuration

sudo systemctl restart fail2ban

Testing Fail2Ban

To test Fail2Ban lets create a test user and set a password for the user

sudo useradd test
sudo passwd test

open the sshd config

sudo vim /etc/ssh/sshd_config

modify the line PasswordAuthentication to say yes and add the test user to AllowUsers

PasswordAuthentication yes
AllowUsers user test

restart the sshd service

sudo systemctl restart sshd

Attempt to login to the remote host using the test account using an incorrect password. After 3 failed attempts it should say connection refused.

ssh [email protected] -p 2222

Fail2Ban should do something along the lines of …

Your browser does not support video.

log back in as your normal user, remove the test user and restore the sshd config.

To remove the user

sudo userdel test

restore the /etc/ssh/sshd_config file

sudo vim /etc/ssh/sshd_config

Set PasswordAuthentication back to no and remove test from AllowUsers

PasswordAuthentication no
AllowUsers user

Conclusion

well done, you managed to make it through all that !! At least now you can be reassured that if them pesky brute-force attackers decide to target your machine they wont have a fun time being in Jail 🤣 sorry bad joke.

By now you have managed to setup an ssh key for a client and copy it to a remote host, re-configure the sshd config to lockdown authentication and last but not least install and configure Fail2Ban to block pesky attackers.