Debian Server 18.04 with UFW & Fail2Ban

debian, server, ssh, fail2ban

This is how I set up my VPS as a base for whatever I’m going to do with it. When done we’ll have Debian 18.04 server with a user with root privelieges, a SSH key to login with instead of a password and UncomplicatedFirewall (UFW) and Fail2Ban which will block IP addresses of failed authentication tries.

SSH

An SSH key is an important step to take to keep your server out of reach for non-authorized people. If this is unfamiliar to you I recommend to take a look at: ssh.com. In this example we will create a RSA key pair.

If you don’t already have an SSH key we need to create one. This key is required to connect to the server.

Open the terminal and run the command ssh-keygen. Without any options we will create a standard RSA key.

Important: Make sure to create a strong password and keep it in a safe place. If the password is forgotten or the keyfile is gone, you’ll never get access to the server again.

Creating the key

First off, we will create the key

ssh-keygen

We will then see an output like this

Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
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:BTX7[...]qa0Q user@host
The key's randomart image is:
+---[RSA 3072]----+
|*+ooo   ..o   .  |
|. o+ o o o + . + |
| +  + * o + + . o|
|oE   o o . o = + |
|o       S   = X o|
| o         . % * |
|. .         B =  |
| o         o     |
|.                |
+----[SHA256]-----+

This will generate two files for us in ~/.ssh

This means that it’s not possible to brute force the server as the server needs the private key to actually allow login.

If we cat the public key, we see something like this

$ cat .ssh/id_rsa.pub 
ssh-rsa AAAA[...]LI8= user@host

Copy the key to server

To copy the key to the server we can use following command

ssh-copy-id -i ~/.ssh/id_rsa.pub user@ip-of-server

The key will be added to a file called authorized_keys and we need to make sure it has the right permissions which should be 700 for the directory and 600 for the file itself

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Log in to the server

We will now connect via SSH to our server with our key

ssh user@ip-of-server

Note: If you choose a different name or path for the key we need to use the -i option to specify the path for it. To avoid this we can create a SSH config which I’ve a post about here.

First time connecting we will se a message like this, just type “yes” and give the password for the SSH key

The authenticity of host '<ip> (<ip>)' can't be established.
ECDSA key fingerprint is SHA256:p5Ew[...]a/PQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '<ip>' (ECDSA) to the list of known hosts.
user@<ip>'s password: 

Make sure the system is up to date

apt update
apt upgrade

Create a user

Now we can create our user and give it root privileges. We will in a later step remove the ability to login as root throught SSH. We will need this user to login.

adduser <user>
usermod -aG sudo user

With the first command we creating the user and give it a user name, but we also added it to the sudo group.

SSH

We need to copy the SSH public key from the root user to our new user

rsync --archive --chown=<username>:<username> /root/.ssh /home/<username>/

Notice the / after the path, this is to prevent the folder .ssh to be moved as well

Since we now have the key in our user we can deny the root user to login with SSH and require the SSH key to be able to login

vim /etc/ssh/sshd_config

Find these rows, uncomment them and change the values to no

PermitRootLogin
PasswordAuthentication
UsePAM
ChallengeResponseAuthentication

To put the changes to action we can restart the SSH daemon

systemctl reload ssh

Firewall

We will use UFW (Uncomplicated Firewall) as our firewall

By default UFW blocks all incoming connections, so we will need to allow the ports for ssh, http and https and activate the firewall

ufw default deny
ufw allow 22
ufw allow 80
ufw allow 443
ufw enable

Fail2Ban

Fail2Ban keeps track of who tries to connect to your server via SSH. With the help of this program, we can ban IPs that repeatedly attempt to connect but fail.

Download Fail2Ban

# apt install fail2ban

We need to copy the default configuration file:

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Then edit the file we just created jail.local

vim /etc/fail2ban/jail.local

Here we will change a few things, these are the settings I like

bantime = 60
findtime = 30
maxretry = 3

What the value means:

bantime = Number of minutes the ban should apply
findtime = The login attempts interval maxretry = How many tries that needs to be done in the findtime interval to be banned

And then we need to find the row with [sshd] and add this below it

enabled = true

Now we’ve: