Securing Your Web Server on a VPS: A Step-by-Step Guide
There are several reasons why a developer would want to manage their own servers. Servers, especially VPS (Virtual Private Server), have become very affordable resources. They allow us to test, build, host our projects and do many other things.
Whatever use you make of a server, it must be protected, because an intrusion could have serious repercussions. In this article, I explain how to secure a VPS simply in 5 simple steps.
1/ Update your system
This may sound basic to you, but one of the primary reasons for finding flaws in web servers is system obsolescence. Not updating your systems regularly is a real danger for your business.
Even if you have just requested the installation of your VPS from your host, you will benefit from updating your system before moving on to the rest of this article. Indeed, hosts often use backups or snapshots to create new servers. So, there is a good chance that the packages on your system need updates.
Run the following commands:
$ sudo apt update
$ sudo apt upgrade -y
2/ Change root
password
I'm not sure it's worth explaining. Change your root
password.
$ sudo su
$ passwd
New password:
Retype new password:
passwd: password updated successfully
$ exit
The root
account is the “super-administrator” account. He has all the rights. If there is an account that we refuse to leave in the hands of hackers, it is this one.
But changing the root
account password is not enough. You will see that a little further in the rest of the article.
3/ Create a new user
Another tip to avoid problems on your server: don't use root
. I see at least two reasons for this:
- everyone has a
root
user on their machine by default. It's easy for a hacker to guess root
has all rights on the machine. If a person finds the root account password, he can do anything on the machine
The best solution to prevent this problem is to use a different account to manage your machine. To do this, use the following command:
$ adduser nameOfTheUser
Adding user `nameOfTheUser' ...
Adding new group `nameOfTheUser' (1001) ...
Adding new user `nameOfTheUser' (1001) with group `nameOfTheUser' ...
Creating home directory `/home/nameOfTheUser' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for nameOfTheUser
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
After answering all the questions of the utility, let's tell the system that this new user will be able to perform actions usually dedicated to the superuser without being one.
The idea is to be able to say “I'm not a superuser, give me no rights” but temporarily, when the situation requires it, tell the system “in fact, I'm the superuser, let me do this one-time action”.
$ adduser nameOfTheUser sudo
sudo adduser nameOfTheUser sudo
Adding user `nameOfTheUser' to group `sudo' ...
Adding user nameOfTheUser to group sudo
Done.
Now you will be able to type the sudo
command from your new user account without receiving a system denial. You can also connect in SSH directly with this user.
4/ Change SSH access
Now that only you know the password for the root account, and you no longer use it to connect to the server, it's time to go a little further.
What are the problems we might encounter? Brute force attack. You no longer use the root
account, but it is still usable. Using randomly generated passwords until one works is a method that still works today.
The method would also work on the second account that we created above.
To remedy this, we'll modify the SSH configuration somewhat to log in using an RSA key rather than a password. To be able to log in with a key, you first need... a key.
So let's generate ours on our local computer (not the server).
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
-t
allows you to indicate the type of key you want to create. We want an RSA key.-b
specifies the size of the key. I usually put 4096 so that it is twice as long, complex and solid as the default 2048 bites. But, you can put the size you want. Just tell yourself that depending on the power of your computer, the more you ask for a long key, the longer it will take to generate (and use?) it.-C
allows you to add a comment to facilitate your organization.
The command will ask you for a passphrase. It is a sentence that must be indicated to use the key. A kind of password to protect the key. You can leave it out, but it is strongly recommended that you do put one.
Once the key is generated, you will find two new files on your local machine.
$ ls ~/.ssh
id_rsa id_rsa.pub
id_rsa
is your private key. Not to be communicated under any circumstances. It must not leave your machine and allows you to decrypt the data that is sent to you.id_rsa.pub
is the public version of your key. To communicate to those with whom you wish to communicate. It does not make it possible to decrypt the data, but only to encrypt them. In other words, it allows people to write messages that only your private key can decrypt.
As I just said, the private key will not move from your machine. However, to be able to communicate with the server, the server must have your public key. So, we have to send it to him.
No need to open the file and copy-paste anything, there's a command for that:
$ ssh-copy-id -i ~/.ssh/id_rsa nameOfTheUser@ipOfTheServer
This command will create the ~/.ssh
folder in your user's account on the server. Then, it will create the file ~/ssh/authorized_keys
in which it will add the public key linked to the private key id_rsa
.
Normally, this command sends all public keys from your local machine to the server. To avoid this, we use -i
to tell it which key to send.
You can now connect without passwords to the server by doing ssh nameOfTheUser@ipOfTheServer
. Only the passphrase will be requested if you have specified one.
Since it is possible to log in without passwords, all we have to do is disable the login with passwords. Thus, the risk of brute force will be eliminated. To do this, on the server, edit the following lines in the /etc/ssh/sshd_config
file to have these values:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
With these settings, it will be impossible to log in with the root account whether you know the password or not. All other accounts will be inaccessible with a password, but accessible if you have the correct RSA key.
Last detail, the standard port used by SSH is 22. It means that everyone knows this port. To make the access a little more complicated, a good practice is to change this port to a value between 1024 and 6665.
In the same /etc/ssh/sshd_config
file, modify the following line with the value of your choice:
Port 5489
To validate these changes, restart the SSH agent as follows:
$ sudo systemctl restart ssh
Your server now looks a bit more like a fortress. ssh nameOfTheUser@ipOfTheServer
will no longer work. You will need, in addition to the user and the IP, to indicate the port that you have chosen previously. The password will not be requested, you will need the RSA key to be able to connect.
$ ssh nameOfTheUser@ipOfTheServer -p 2345 -i ~/.ssh/id_rsa
Enter passphrase for key '~/.ssh/id_rsa':
5/ Enable a firewall
The firewall allows you to control who can connect to your server and how. The idea is to avoid leaving windows open in our fortress. We will therefore explicitly specify what we allow as a connection to our server.
Most Linux distributions have iptables
and ufw
installed by default. I use UFW. I will therefore explain to you the basic rules that I apply for the security of my servers. To learn more about how this tool works, I recommend this article from DigitalOcean.
We start by disabling the firewall while we make our changes:
$ sudo ufw disable
Next, I change the default rules so that all incoming connections are denied, and all outgoing connections are allowed:
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
Next, we'll allow SSH connections. Otherwise, we will no longer have a way to connect to the server.
$ sudo ufw allow 2345/tcp
Change 2345
to the port you chose for SSH in the previous step.
Now we can activate the firewall.
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
As we no longer use the default SSH port, if you still have connections using port 22 (on another terminal, for example), UFW warns you that you may lose your connection.
Now you have all the basics to secure your servers. There are of course many other things that one can implement to secure a server, but with the 5 steps in this article, you will have a server that is much less vulnerable to attacks.
I have also prepared for those who wish it a print which includes all the commands of this article, a glossary and an explanation of the changes of the sshd_config
file. Nothing more than what is in this article, but the idea is to have a cheat sheet to quickly secure your server.
If you are a premium member of the club, log in and download it there. Otherwise, you can find “VPS/server security cheatsheet” on the store to buy it without becoming a member :
The French version of the PDF can be found on the shop or at the bottom of the French article.