How to secure a Linux server

This tutorial aims at teaching you how to secure a Linux server. I'll be using Debian for this guide. If you're using Fedora or Arch based systems, it will be slightly different. It's important that you take some precuations while setting up a server, whether that's for an OT server, a web server for your website or just something else. The steps provided in this guide will in most cases be sufficient enough. There are always more stuff you can do and it's a never-ending rabbit hole once you dive into Linux security. But hopefully this will be sufficient for your use cases.

Step #1: Changing server SSH port

When you access your server, you will most likely do this via SSH. The default port for this is 22. Instead, you want to change this port to something else to make it a little bit harder for people to know. First, login to your server using SSH: Code:

ssh root@<ip address>

Once logged in, edit your SSH configuration file by doing this: Code:

sudo nano /etc/ssh/sshd_config

This will open up the configuration file in the text editor called Nano. Go to the line that says "#Port 22". Uncomment the line by removing the hashtag and then setting it to any new port number. For this example, we will set it to "Port 22077". Again, you can basically use any random port number if you want. Save the file and close it, by pressing: Ctrl+O --> Enter --> Ctrl+X Close the connection to the server (by typing: exit) and try reconnect using SSH. This time you will get an error and you're asked to provide a port number as well. To connect to your server, you now have to provide the port number like this: Code:

ssh root@<ip address> -p 22077

Verify that it works when you provide the port parameter ("-p").

Step #2: Use SSH keys with strong encryption

Instead of simply using a username and password to authenticate via SSH, it is best to use a SSH key. That means you will not only have to provide a password when connecting to your server, but also have a key file that you keep somewhere safe. Without the key, you can not enter the server. This is basically two-factor authentication for SSH and it's much more secure than a regular password. When creating an SSH key file, you encrypt it using a cryptographic algorithm. The most commonly used is an RSA encryption, which is also the default in most cases. But there are better encryption methods out there. Instead, you want to use ED25519 encryption for your SSH keys as they are proven to be more difficult to decrypt, but at the same time they do not cause any performance issues. If you want to read more about ED25519, you can do that here: EdDSA - Wikipedia (https://en.wikipedia.org/wiki/EdDSA#Ed25519) To generate an SSH key for your server, open up a terminal on your computer. I'm assuming you're using Linux on your own computer as well. If you're using Windows, lookup how to generate SSH keys with ED25519 on Windows. It might be slightly different. And type the following into the terminal (on your computer, not the server): Code:

ssh-keygen -t ed25519 -a 100 -C "My OT Server"

When prompted, save the file to your desktop and name it anything you want, e.g. "otserver". This will create a SSH key pair. You will end up with two files on your desktop.

  • otserver

  • otserver.pub

The "otserver.pub" file is your public key file. This is the one you want to keep on your server. The other file "otserver" (without any file extension) is your private key that is used to connect to it. Think of the public file as the keyhole and the private file is the key that matches. Do not share the private key with anyone, unless you want to give them access to your server. Now you want to copy your public key ("otserver.pub") to your server. You can do this safely using the "ssh-copy-id" command. Type the following into your terminal window (on your computer, not the server), assuming your key files are located on your desktop. Change the "<ip address>" to the ip address of your server. If you use a different port than 22077, change it to the port you chose in step 1. Code:

ssh-copy-id -i ~/Desktop/otserver.pub -p 22077 root@<ip address>

The key file has now been copied ("installed") on to your server. Now we have to edit the SSH configuration to go from "password authentication" to "SSH key authentication". Connect to your server and edit the SSH configuration file: Code:

sudo nano /etc/ssh/sshd_config

Change the line "PasswordAuthentication yes" to "PasswordAuthentication no". Uncomment the line "#PubkeyAuthentication yes" by removing the hashtag. Then restart the SSH service on the server: Code:

sudo systemctl restart sshd

Exit from the server, by typing "exit" until you're out. To connect to your server using the SSH key file, type the following (assuming you're in the same directory as your private SSH key file "otserver"). Code:

ssh root@<ip address> -p 22077 -i otserver

Verify that it works fine when you provide the SSH key as identification ("-i") and that it doesn't when you don't provide it.

Step #3: Create a non-root user & disable root login

When we enter the server through SSH we have so far authenticated to the "root" user account that is added to all servers by default. But that's bad practice. We typically don't want to use "root" as the username for the SSH login, because everyone knows that username. Instead, we will create a new user and then disable "root" from logging in to the server. This means anyone who wants to access your server needs to know the new username. So first, we will create a new user on the server. So make sure you are connected to it via SSH and then type the following command: Change "<username>" to whatever you want. Pick something really random. Code:

useradd -m -s /bin/bash <username> && passwd <username>

This will add a new user and then let you choose a password for it. Use a very strong and unique password that you don't use anywhere else. My recommendations: For the username, I use the old Tibia "suggested name" generation, which is basically this: "Consonant + Vowel + Consonant" a few times repeatedly. You remember the old characters names in Tibia? They were quite unique, but also easy to remember. If you want to know how to generate a such name, here's the JavaScript code for it. Simply copy-paste this into the "console" of your browser and you will get randomly generated names: Code:

function randomName() {
    let name = "";

    // Letters
    let vowels = ["a", "e", "i", "o", "u"];
    let consonants = ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z"];

    // Name and length
    let length = Math.floor(Math.random() * (10 - 5)) + 5;

    // Generate a new name
    for (let i = 0; i < length; i++) {
        if (i % 2 === 0) name += consonants[Math.floor(Math.random() * consonants.length)];
        else name += vowels[Math.floor(Math.random() * vowels.length)];
    }

    return name;
}

And run it in your browser like so: Code:

console.log(randomName());

So for example, it generated the name "wineredo", this will be my new username for the server. For the password, I'm using KeePass XC to both store and generate strong passwords. I highly recommend you get a password manager like KeePass XC. Create a strong and unique password. So when you have created your new user for the server, make sure it was created successfully. Check that it appears here: Code:

cat /etc/passwd

To make the new user able to run sudo (admin commands), check what the name of the admin group is - and then add the user to that group. In most cases, the group will simply be called "sudo". But double check it by running: Code:

visudo

Find the name of the admin group ("%"). Again, usually it is just "sudo". Once you know the name of the group, e.g. "sudo", then add the user to that user group like this: Code:

usermod -aG sudo wineredo

In my case, I add it for user "wineredo". Change it to your username. Also verify that the user was successfully added to the "sudo" group by typing: groups <username> Now try to enter elevated privileges with the new user and run an "apt update" as a test: Code:

su - <username>
sudo apt update

Now that the new user is created and can access admin rights, we will restrict the SSH access to the server. We will remove the user "root" from being able to connect, and only make it possible for this new user. Edit the SSH configuration file by opening it using the text editor Nano: Code:

sudo nano /etc/ssh/sshd_config

Change "PermitRootLogin" to "no". Add a new line anywhere in this file called "AllowUsers" followed by the usernames that you want to give SSH access to. In my case, I will only add it to my new user called "wineredo". I will type the following line into the file: Code:

AllowUsers wineredo

If you want to add multiple users, separate them by spaces on the same line. Now attempt to login using the "root" account to your server. It will result in an error. Instead, try to login using your new user account. That will work, as long as you also provide the port number and the SSH key file. Code:

ssh <username>@<ip address> -p 22077 -i otserver

Step #4: Setup and enable firewall protection

It is crucial that you install and configure a firewall on your server. Without it, you will be much more vulnerable. We will install and then set it up, and only allow certain port numbers to function on your server. Why enable all ports? Instead, we only allow the ones that are in use. And by default, we block all incoming connections - and allow all outgoing communication. Such as these ports:

  • 80 (HTTP) for the website, if you have one

  • 443 (HTTPS) for the website, if you have one

  • 3306 (MySQL) for the database, if you have one

  • 22077 (SSH) or whatever port number you chose, this is important! Otherwise you can't access via SSH!

  • 7171 & 7172 (Tibia) so that players can access your OT server.

We do this by installing "ufw" (firewall software) and then configuring it. Connect to your server and run the following with admin privileges: Code:

su - <username>
sudo apt update
sudo apt install ufw
sudo systemctl enable ufw
sudo systemctl start ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow 3306
sudo ufw allow 22077
sudo ufw allow 7171
sudo ufw allow 7172
sudo systemctl restart ufw

Step #5: Prevent bruteforce attacks

Your server will most likely end up getting a lot of bruteforce attacks where bots will try to login to it via SSH and steal/corrupt your files. This happens to millions of servers in the world every year. We can make it very difficult for someone to attempt that by limiting the amount of requests they can make to the server in a given time period. For example, if they enter the wrong SSH password 3 or 5 times we can set to block them for 1 hour. If they repeat it, it will be a 24 hour ban, and so on. This will make it more difficult for them, since they need to keep changing IP addresses over and over. To do this, we can use a program called "fail2ban" which is one of the most popular ones for mitigating bruteforce attacks. First, we will install it and then configure it (maximum login tries, bantime, etc.). Then we need to specify where we want to apply it. This is what most people forget about. They set it up, but don't enable it, which means it has no use. In our case, we want to set it for the SSH access and nothing else. We do not want to enable it on everything, for example the OT server. Imagine a player enter incorrect password and gets banned 1 year for it. That would be bad for the server. Login to the server using admin privileges and run the following: Code:

sudo apt install fail2ban
cd /etc/fail2ban
cp jail.conf jail.local
sudo nano jail.local

So with the above commands, we installed it, went to its install directory, copied the default setting file and opened it up. Now we will edit the file. Set the bantime to 60 minutes. Set the maxentry to 5 times. This means if someone will enter the wrong SSH credentials 5 times in a row, they will get a 60 minute ban. Now we need to enable the different "jails" that we want to apply fail2ban for. Each "thing" that we want to enable this for, is called a "jail". Like I mentioned above, we want to enable this for SSH. Scroll down and you will see a section for the SSH jail ("sshd"). Add the line "enabled = true" to enable this for SSH access. You can also set to whitelist some IPs, for example your home computer, for unlimited login attempts to SSH. Simply uncomment the "#ignoreip" line and then add IP addresses after it, separated by spaces. For example, if my home IP is 123.123.123.123 I will whitelist it using this line in the "sshd" jail: ignoreip 123.123.123.123 You can then also set a logpath where you will see all the connection attempts that you're getting. For example, my "sshd" jail looks like this: Code:

[sshd]
enabled = true
port = 22077
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 60
ignoreip = 123.123.123.123

I set it to be enabled for my specific port (22077), each log entry will be identified as "sshd", I gave it a log path, max entries, bantime and I whitelisted my home IP address to give unlimited login attempts. Save the file, using Ctrl+O --> Enter --> Ctrl+X After you have set up the jail for the SSH access, simply restart fail2ban and double check to make sure it is started: Code:

sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
sudo systemctl start fail2ban

Step #6: Frequently check your server and log files

That was it. You have now secured your Linux server, at least enough for most type of attacks. We have set a custom SSH port, created a new user account, disabled root login, enabled SSH key login, configured a firewall and prevent bruteforce attacks on the SSH service. There is much more that you can do if you put time and effort into learning about it. But this should be sufficient for most use cases. Now all that's left is that you frequently login and make sure everything is working as intended. Keep an eye on the SSH logs in /var/log/auth.log Store your passwords in a password manager like KeePass XC, and keep your SSH key files safe and secure. Do not share them with anyone. I recommend not storing them in any cloud service, instead keep them on a USB or external drive. You do not need to update your server and services. This is not like Windows. Unless there is some known vulnerability out there, you have no reason to update stuff all the time. When updating, sometimes some things can break. Or sometimes services stop auto-restarting. To check if for example your firewall is running, or if fail2ban is running, use the "systemctl status" command. As an admin user, run the following to check statuses for firewall and fail2ban: Code:

sudo systemctl status ufw
sudo systemctl status fail2ban

If they are not "active (running)", then enable them (enable means autostart) and then start them: Code:

sudo systemctl enable ufw
sudo systemctl enable fail2ban

sudo systemctl start ufw
sudo systemctl start ufw

And remember, security is a journey - not a destination. There's always things that can be improved. By doing something is however much better than doing nothing. Also, pick a trusted hosting provider. I can highly recommend DigitalOcean's services. They have fantastic support, good uptime and affordable prices. Good luck and I hope this helps someone out there. Also remember to make backups of your database from time to time, in case anything happens to your server.

Credits: 222222.

Last updated