Brute-forcing is generally one of the very first vectors of attack to many servers out on the net. It’s an attack that could very much strain system resources if not handled properly. Whether you’re self-hosting your own rig or renting out a VPS, it won’t matter. Any live machine out in the open will always be subject to all sorts of attacks. The core steps shared here should be easily replicable on many systems. I would like to also preface by saying that the main motivation behind this article is the lack of simpler brute-forcing mitigation guides out in the wild. Keep in mind this is my own methodology to hardening live machines, so everybody’s own way of going about it will vary.

Before we setup the necessary software that is specialized for blocking unwanted SSH connections, we first must configure our own system to authenticate logins properly.

Core steps in order:

We will go ahead and setup an SSH key-pair as a strict means of authentication. How it all works is quite simple. The server will hold the public key (shareable) and you will hold the private key (do not share) on your local system. Attempting to match with the server’s public key will output a challenge response in which, only our private key can solve in order to grant access. We won’t need to painstakingly enter our password for each login attempt with the potential to accidentally trigger SSHGuard to lock us out. This adds a nice convenience factor too.

Generate an ssh key on your local machine:

$ ssh-keygen

Next, establish a key-pair trust with the server and login.

$ ssh-copy-id user@domainexample.com
$ ssh user@domainexample.com

Update and install:

$ sudo apt update 
$ sudo apt upgrade 
$ sudo apt install ufw sshguard rsyslog 

Now on the server, add or uncomment the following inside of /etc/ssh/sshd_config:

PubkeyAuthentication yes
PermitRootLogin no 
PasswordAuthentication no 
Port <specified port here> # any port of your choosing
ChallengeResponseAuthentication no 
UsePAM no 

Save the file and reload sshd. SSH key authentication at a specified port should now be enabled.

“Why change the default port?”

This is simply textbook security through obscurity. One could argue that this principle isn’t actually effective in the real world and only wastes time as any hacker/pentester worth their salt could see right through the veil. In our use-case here however, it’s quite effective against automated bots as long as you layer the obfuscation with other defensive measures. Overall, changing the default SSH port will make it more difficult for malicious scanners to enumerate our machine out on the open internet.

UFW setup:

$ sudo ufw allow <specified ssh port>

Edit /etc/ufw/before.rules and paste the following right after # allow all on loopback.

Be sure to type your non-default ssh enabled port here!

:sshguard - [0:0]
-A ufw-before-input -p tcp --dport <specified ssh port> -j sshguard

Short UFW explanation:

Ufw will forward all TCP connections going to the specified port to the SSHGuard chain for processing. SSHGuard will then have control to add rules to this chain based on the offending IP’s behavior.

Restart ufw.

At this stage it’s now time to setup SSHGuard and proper logging.

$ sudo systemctl enable sshguard.service
$ sudo systemctl start sshguard.service

Edit /etc/sshguard/sshguard.conf with your editor of choice.

You should be met with a configuration file resembling something like this:

#### EXAMPLE CONFIGURATION ####
# Full path to backend executable (required, no default)
BACKEND="/usr/libexec/sshguard/sshg-fw-nft-sets"

# Shell command that provides logs on standard output. (optional, no default)
# Example 1: ssh and sendmail from systemd journal:
LOGREADER="LANG=C journalctl -afb -p info -n1 -t sshd -o cat"

#### OPTIONS ####
# Block attackers when their cumulative attack score exceeds THRESHOLD.
# Most attacks have a score of 10. (optional, default 30)
THRESHOLD=30

# Block attackers for initially BLOCK_TIME seconds after exceeding THRESHOLD.
# Subsequent blocks increase by a factor of 1.5. (optional, default 120)
BLOCK_TIME=120

# Remember potential attackers for up to DETECTION_TIME seconds before
# resetting their score. (optional, default 1800)
DETECTION_TIME=1800

# IP addresses listed in the WHITELIST_FILE are considered to be
# friendlies and will never be blocked.
WHITELIST_FILE=/etc/sshguard/whitelist

You can read up more about configuring SSHGuard through the man pages or their official docs. These default values are good bases to start from. You can tweak them further depending on the severity of the attacks later.

Save the configuration and Restart SSHGuard Daemon

$ sudo systemctl restart sshguard.service

Check the SSHGuard daemon status and run a tail command to /var/log/auth.log to ensure proper logging.

$ sudo systemctl status sshguard.service
$ sudo tail -f /var/log/auth.log
Tag(s): [By: Abe] [Cybersec] [Infosec]