It may be a surprise to many that most cyber attacks are relatively straight forward, exploiting well known vulnerabilities. So if you’re thinking of exposing your server to the internet, you should definitely think about server hardening.

Server hardening is all about making your server secure by cutting out unnecessary risks. Think of it like locking all the doors and windows in your house.

The way I harden my machines is by following this checklist of actions when setting-up a machine.

1. Installing Fail2Ban: The bouncer for your exclusive club.#

Start off as usual by updating the package listings:

sudo apt update

then install fail2ban:

sudo apt install fail2ban

During the installation it sets up a background service, which is usually disabled by default as it can have undesired effects due to its default settings. To verify this use the systemctl command:

systemctl status fail2ban.service

Configuring Fail2Ban:#

Before we make any changes, lets make a backup so we always have something to fall back on: sudo cp /etc/fail2ban/jail.local /etc/fail2ban/jail.local.bak

Use whichever file editor you prefer and open /etc/fail2ban/jail.local you can now enable the ssh section by removing the # in the ssh section ([sshd]) and adding an enabled = True line under the header. Now you can add other settings such as ban time and max retries. This is my current configuration:

enabled = true
bantime = 4w
maxretry = 3

When you’re finished editing, save the file and enable the service to run automatically by running systemctl enable:

sudo systemctl enable fail2ban

you can then manually start for the first time using systemctl start:

sudo systemctl start fail2ban

To verify use systemctl status:

sudo systemctl status fail2ban

If it is failing to boot and showing this:

ERROR   Failed during configuration: Have not found any log file for sshd jail

In my case it turns out I was running a systemd-based OS, so no logs were stored in files, instead you would use journalctl to access the logs. To get fail2ban to use journalctl just change the backend variable.

backend = systemd

Testing fail2ban:#

from another device, one that you won’t be using to log into your main server, try to ssh into the main server using false credentials. After a couple tries the response should change from Permissin denied to Connection refused or Connection timed out.

on your server you can see the new rule created in your iptables by fail2ban by using the command:

sudo iptables -S | grep f2b

If it has banned the IP it would show up as:

-N f2b-sshd
-A INPUT -p tcp -m multiport --dports 22 -j f2b-sshd
-A f2b-sshd -s 192.168.0.222/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -j RETURN

where 192.168.0.222 is the banned IP address.

2. SSH Keys:#

Generating key-pairs:#

To generate a ket pair run the ssh-keygen command. I like to add a few extra flags to mine so I usually run:

ssh-keygen -b 4096 -t rsa

Follow the prompts given by the command. I’d recommend using a passphrase if you’ll be working from multiple client systems or keeping it on removable media.

Propagating the public key to a remote system:#

To send the public key you can use the command:

ssh-copy-id username@target_server

3. Disabling Passwords#

Since we’re now using ssh keys we should now disable password authentication, we can do this by editing the ssh config file located at /etc/ssh/sshd_config.

TIP: before getting our hands dirty in the config file, it may be wise to make a copy of the default configuration. You can do it with this command: sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

Find PasswordAuthentication and set it to no:

PasswordAuthentication no

4. X11 Forwarding: because it’s not just about looks#

X11 forwarding can expose your server to security risks such as key logging and privilege escalation. It’s better to avoid enabling it unless necessary. We can do this by editing the ssh config file located at /etc/ssh/sshd_config.

TIP: before getting our hands dirty in the config file, it may be wise to make a copy of the default configuration. You can do it with this command: sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

Find X11Forwarding and set it to no:

X11Forwarding no

5. Changing SSH ports:#

Changing SSH ports prevents anyone from using automated attacks, as the default port used by ssh is 22. We can change it by editing the ssh config file located at /etc/ssh/sshd_config.

TIP: before getting our hands dirty in the config file, it may be wise to make a copy of the default configuration. You can do it with this command: sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

Find Port and set it to any available port(1024 = 65536):

Port 12345

6. Disabling root logins#

We should disable logins to the root account through ssh as it helps attackers who are brute-forcing, as the username is all ways root so they have one less thing to guess. More importantly the root account as unlimited access rights. We can disable this by editing the ssh config file located at /etc/ssh/sshd_config.

TIP: before getting our hands dirty in the config file, it may be wise to make a copy of the default configuration. You can do it with this command: sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

Find PermitRootLogin and set it to no:

PermitRootLogin no

Conclusion: Your first line of defence is set#

By configuring features such as SSH key authentication, setting up Fail2Ban, and hardening the SSH daemon, your server is no longer a low-hanging fruit for attackers.

Remember, securing a server isn’t a one-time task—it’s an ongoing process. Regularly update your system and keep refining your configurations to stay ahead of evolving threats. Congratulations on fortifying your system! You’ve now turned your server into an exclusive club where only those with the right credentials can enter. Happy hosting! 🚀