Locking down my VPS: The simple security steps I can’t skip [EN/FR]

Hello Hive! Right now, I’m experiencing a bit of a slowdown with my freelance projects. It shouldn’t last, so I’m taking advantage of it to continue developing LexiStep. The French V1 is almost available, by the way. It’s currently in the testing phase, and I have many technical issues to resolve before making it official.

At launch, it will be severely lacking in features, but the web app will still be largely usable as is. New features will come later.

Last Friday, to host the application, I bought a VPS. In other words, I purchased a virtual dedicated server. This server is empty, so everything needs to be set up.

I started by installing a web server, Nginx, to host my code.

Right now, I’m thinking about server security. It’s something that takes up a lot of my time, and I thought it would be interesting to share it here in this community.

Step 1: Install a Firewall (UFW)

When you start researching how to secure a VPS online, you quickly come across the concept of a firewall. And usually, in the first few lines, you can also read about "UFW" (Uncomplicated Firewall).

At first glance, when you don’t know much about it, it seems like a simple way to set up initial configurations. But before installing anything on my machine, I need to try to understand what it is.

After reading a lot, A LOT of documentation, a VPS without a firewall is exactly the same as a house without a door. Indeed, if the server has no firewall, it means it accepts all connections from the Internet.

Thus, without this tool, a hacker could:

  • Scan my server to see which ports are open (using nmap).
  • Perform brute-force attacks on SSH passwords (by testing multiple password combinations, especially with the most well-known SSH user: root).
  • Try to exploit vulnerabilities in Nginx, MySQL, or other services (if the curl command reveals too much sensitive information and the hacker sees that the database port is open).
  • Install malware or a script to mine cryptocurrencies.
  • ...

The most well-known firewall is UFW, and it can be installed simply with the following command:

sudo apt update && sudo apt install ufw -y

Once installed, you can try the following command:

sudo ufw status

This command should tell you whether your firewall is active or not.

a. Viewing Open Ports (nmap)

I learn a lot by example. So, I wanted to install nmap on my PC and scan my web application to see if I could detect open ports.

Once the installation is complete, I can run the following command:

nmap -p- mysite.com

This should return all the open ports on my server along with the services it is using. On my end, it returns nothing. This is probably a protection put in place by my provider.

However, on my server, running the following command lets me see which ports are open. By default, UFW only allows port 80 (HTTP), port 443 (HTTPS), and port 22 (SSH).

sudo ufw status

In my case, these are exactly the three open ports.

b. Testing and Securing SSH with Telnet

To check if SSH is visible to everyone, there is a very simple command:

telnet mysite.com 22

22 because SSH often uses this port. On my site, the command returned:

This means that my SSH is accessible to everyone. The first thing I can do here is to stop using port 22 for SSH and configure it to another port, specifically with this command:

sudo nano /etc/ssh/sshd_config

Then, in this file, I modified the part "#Port 22" by removing the "#" and replacing 22 with another port. To apply my changes, I then run the following command:

sudo systemctl restart sshd

Now, I need to modify my UFW firewall to allow the new port and close the old one:

sudo ufw allow 2222/tcp (2222 is not my new port)
sudo ufw deny 22/tcp

It will then be much harder for bots to find my SSH port. However, a human could still manage to do it. Still, this is a good starting point and already a solid protection measure.

Now, to further secure SSH, I can go further. When I bought my VPS, my provider (affiliate link Hostinger and non-affiliate link Hostinger) had me create an SSH key, which I blindly generated.

In fact, this is probably one of the best things I could have done to secure my SSH. Brute-force attacks rely on weak passwords. The best defense against this is to completely remove password authentication and allow only SSH keys.

That’s what Hostinger did for me—I just had to follow the steps.


At this stage, thanks to the firewall, only site visitors can access my server via HTTP and HTTPS. The SSH port is also open, but I changed the default port. I also secured the connection with an SSH key.

Step 2: Setting Up a Reverse Proxy

This concept is still a bit unclear to me, so it’s not easy to explain. But on a blog (I can’t find the source anymore), I read an interesting metaphor:

Imagine my server as a large store where each user is a visitor who wants information about the products I offer. Without a reverse proxy, each visitor enters the store directly and speaks with the salespeople. There’s disorder because the salespeople have to manage all the visitors themselves. If too many visitors arrive at the same time, the store becomes overcrowded, and the salespeople provide poor service. Some visitors may be malicious and try to overwhelm the store. Shopping in a mall on a Saturday—that’s what happens.

With a reverse proxy, there’s a security guard at the entrance. Visitors only see the guard, not the salespeople. The guard filters and directs each user to the right salesperson. If a salesperson falls sick (server goes down), the guard can redirect the visitor elsewhere. The guard protects the salespeople by blocking suspicious visitors before they enter.

My Nginx web server already acts as a reverse proxy. If I had used Apache2, as I do for some freelance projects, I would have had to enable and configure a module to manage the reverse proxy. With Nginx, it’s natively integrated. So, when I create my site’s configuration file, I don’t have to do much to activate the reverse proxy.


My VPS security could still be significantly improved, but we are already off to a good start. I can now focus on the rest, which is continuing development!


Version Française


Bonjour Hive ! En ce moment, j'ai un peu de mou avec mes missions freelances. Ça ne devrait pas durer, donc j'en profite pour continuer le développement de LexiStep. La V1 française est bientôt disponible d'ailleurs. Elle est actuellement en phase de tests et j'ai de nombreux soucis techniques à régler avant d'officialiser la chose.

Lors du lancement, il manquera cruellement de fonctionnalités, mais la webapp sera largement utilisable en l'état. Les nouvelles fonctionnalités viendront par la suite.

Vendredi dernier, pour héberger l'application, j'ai acheté un VPS. En d'autres termes, j'ai acheté un serveur dédié virtuel. Ce dernier est vierge et il y a donc tout à faire.

J'ai commencé par y installer un serveur web, Nginx, afin d'y héberger mon code.

En ce moment, je suis en train de réfléchir à la sécurité du serveur. C'est quelque chose qui me prend beaucoup de temps et je me suis dit qu'il serait intéressant de le partager ici, dans cette communauté.

Étape 1. Installer un pare-feu (UFW)

Lorsque l'on commence à faire des recherches sur Internet pour sécuriser un VPS, on tombe rapidement sur le concept de pare-feu. Et généralement, dans les premières lignes, on peut aussi lire "UFW" (Uncomplicated Firewall).

A priori, quand on n'y connaît pas grand-chose, ça permet de faire un premier paramétrage simplement. Mais avant d'installer quoi que ce soit sur ma machine, je dois essayer de comprendre ce que c'est.

En lisant beaucoup, BEAUCOUP de documentations, un VPS sans pare-feu, c'est exactement la même chose qu'une maison sans porte. En effet, si le serveur n'a pas de pare-feu, cela veut dire qu'il accepte toutes les connexions venant d'Internet.

Ainsi, sans cet outil, un hacker pourrait :

  • Scanner mon serveur pour voir quels ports sont ouverts (avec nmap).
  • Tester des mots de passe en brute-force sur SSH (en testant notamment plusieurs combinaisons de mots de passe avec l'utilisateur le plus connu de SSH : root).
  • Essayer d’exploiter une faille de Nginx, MySQL ou autre service (si la commande curl retourne trop d'informations sensibles et si le hacker voit que le port pour la base de données est ouvert).
  • Installer un malware ou un script pour miner des cryptos.
  • ...

Le pare-feu le plus connu est donc UFW et il s'installe simplement avec la commande :

sudo apt update && sudo apt install ufw -y

Une fois installé, vous pouvez essayer la commande :

sudo ufw status

Cette commande devrait vous dire si votre pare-feu est actif ou non.

a. Voir les ports ouverts (nmap)

J'apprends beaucoup par l'exemple. J'ai donc voulu installer nmap sur mon PC et scanner mon application web pour voir si je pouvais voir les ports ouverts.

Une fois l'installation terminée, je peux lancer la commande suivante :

nmap -p- monsite.com

Cette dernière doit me retourner tous les ports ouverts sur mon serveur ainsi que les services qu'il utilise. De mon côté, ça ne retourne rien. C'est sûrement une protection mise en place par mon prestataire.

Cela dit, sur mon serveur, en lançant la commande suivante, je peux voir quels ports sont ouverts. Par défaut, UFW ne laisse que le port 80 (HTTP), le port 443 (HTTPS) et le port 22 (SSH).

sudo ufw status

Dans mon cas, ce sont exactement les 3 ports ouverts.

b. Tester et sécuriser SSH avec Telnet

Pour savoir si SSH est visible pour tout le monde, il y a une commande très simple :

telnet monsite.com 22

22 parce que le port utilisé par SSH est souvent celui-ci. Sur mon site, la commande a donné :

Cela signifie que mon SSH est accessible à tout le monde. La première chose que je peux faire ici est de ne plus utiliser le port 22 pour SSH, mais de le configurer sur un autre port, notamment avec cette commande :

sudo nano /etc/ssh/sshd_config

Ensuite, j'ai modifié dans ce fichier la partie "#Port 22" en supprimant le "#" et en remplaçant 22 par un autre port. Pour activer mes modifications, je lance alors la commande suivante :

sudo systemctl restart sshd

Je dois à présent modifier mon pare-feu UFW pour autoriser le nouveau port et fermer l'ancien :

sudo ufw allow 2222/tcp (2222 n'est pas mon nouveau port)
sudo ufw deny 22/tcp

Il sera alors beaucoup plus difficile pour des bots de trouver mon port SSH. Mais un humain en sera toujours capable. C'est tout de même un bon point de départ et c'est déjà une bonne protection.

Maintenant, pour sécuriser SSH, je peux aller plus loin. Lorsque j'ai acheté mon VPS, mon prestataire (lien affilié Hostinger et lien non affilié Hostinger ) m'a fait créer une clé SSH que j'ai générée aveuglément.

En fait, c'est sûrement l'une des meilleures choses que j'aurais pu faire pour sécuriser mon SSH. Les attaques par brute-force sont basées sur des mots de passe faibles. La meilleure défense face à cela est de supprimer totalement l’authentification par mot de passe et de n'autoriser que les clés SSH.

C'est ce que Hostinger a fait à ma place, j'avais juste à suivre les étapes.


À ce stade, grâce au pare-feu, seuls les visiteurs du site peuvent accéder à mon serveur via HTTP et HTTPS. Le port pour SSH est également ouvert, mais j'ai changé le port par défaut. J'ai aussi sécurisé la connexion avec une clé SSH.

Étape 2 : Mise en place d'un reverse proxy

Cette notion est encore un peu floue pour moi, elle n'est donc pas évidente à expliquer. Mais sur un blog (je n'arrive plus à retrouver la source), j'ai lu une métaphore intéressante :

Imaginez mon serveur comme un grand magasin où chaque utilisateur est un visiteur qui veut obtenir des informations sur les produits que je propose. Sans reverse proxy, chaque visiteur entre directement dans le magasin et parle aux vendeurs. Il y a du désordre, car les vendeurs doivent gérer eux-mêmes tous les visiteurs. Si trop de visiteurs arrivent en même temps, le magasin est surchargé et les vendeurs conseillent mal. Certains visiteurs peuvent être malveillants et essayer de saturer le magasin. Faites vos courses un samedi dans un centre commercial, c'est ce qu'il se passe.

Avec un reverse proxy, il y a un vigile à l'entrée. Les visiteurs ne voient que le vigile, pas les vendeurs. Le vigile filtre et redirige chaque utilisateur vers le bon vendeur. Si un vendeur tombe malade (serveur en panne), le vigile peut rediriger le visiteur ailleurs. Le vigile protège les vendeurs en bloquant les visiteurs suspects avant qu’ils n’entrent.

Mon serveur web Nginx joue déjà le rôle de reverse proxy. Si j'avais utilisé Apache2, comme je l'utilise déjà pour des projets freelance, j'aurais dû activer et paramétrer un module pour gérer le reverse proxy. Sur Nginx, c'est nativement intégré. Ainsi, quand je crée le fichier de configuration de mon site, je n'ai pas grand-chose à faire pour activer le reverse proxy.


La sécurité de mon VPS pourrait encore être largement optimisée, mais nous sommes déjà sur une bonne base. Je vais donc maintenant pouvoir me concentrer sur le reste, à savoir la continuité du développement !


The English translation was done using the DeepL API.

Posted Using INLEO



0
0
0.000
0 comments