Sécuriser un VPS

J’avais envie d’écrire sur ce sujet il y a très longtemps. Le moment est venu, la raison? Mes instances Oracle cloud free tier ont été éteinte et je ne peux pas les redémarrer. J’ai pendant 3ans hébergé 2 petites vm sur le cloud oracle gratuitement. Bien que minimaliste (1vcpu, 1go de ram, 50Go de disque) elles m’ont bien dépannée mais je pensais depuis un moment au futur, à héberger mon applicatif chez moi et avoir en front un petit vps qui fera reverse proxy pour avoir une ip fixe et stable.
Je m’intéresse depuis un moment à linux et reflechis à comment le configurer, bien entendu aujourd’hui avec l’ia ce genre d’article est deviens complètement caduque mais je trouve intéressant d’en faire un car il n’y a pas assez d’articles sur ce sujet.

Le setup

Ici je part sur un petit VPS de chez hosteroid, le VPS a 1vCPU, 1Go de ram, 25Go d’espace disque. Pour commencer un avis sur l’hébergeur: Les mots de passe saisis lors de l’inscription sont envoyés en clair par mail après l’inscription, rien n’est fait pour demander un changement de mot de passe après la connexion donc déja ca ne met pas en confiance. Ensuite, au moment de mon inscription, j’ai tout reçu m’indiquant que le serveur était ok… sauf qu’il ne l’était pas, la partition 1 prenait 2.5Go sur les 25 disponibles, le serveur n’avait pas accès à internet, après avoir passé un peu de temps a essayer de comprendre j’ai fait un ticket le soir. Le lendemain matin le support a… redéployé la vm! Avec cette fois les bon paramètres. Le prix de 20€ pour 1 an compense largement car il n’y a pas d’équivalement mais je pense qu’infomaniak malgré le prix un peu plus élevé aurait été mieux autant sur l’interface que tu la gestion de l’interface web. Autre argument, tout sur les copyright sont datés, il n’y a rien de récent dans les dates. Même chose pour les distribution, il y a bien Debian 13 mais ubuntu 26.04 n’est toujours pas disponible en octobre 2026 ce qui traduit un manque de suivi sérieux.
Dernier point, j’ai une limite de 750 gigas de traffic par mois ce qui impose une limite, même si elle est élevée et pour mes besoins c’est très large, elle existe.
En conclusion, hosteroid semble intéressant pour son prix pour des petits projets non critique et dont les informations peuvent fuiter sans conséquences graves, sinon il faut passer sur un hébergeur plus sérieux mais plus cher.

Coté technique, le serveur arrive en état brut, comme une installation faite à la maison, il faut tout configurer soit même. Contrairement à Oracle c’est complètement différent cependant cela permet d’apprendre à sécuriser un serveur.

Etape 1: Préparations

Pour commencer, on va désactiver les dépots src de la configuration d’apt:

sed -i 's/^deb-src/#deb-src/' sources.list

Tout d’abord, on met à jour le serveur avec les commandes:

apt update && apt upgrade -y

Ensuite on crée un nouvel utilisateur qui ne sera pas root et ne pourra se connecter que avec une clé ssh en ssh (sudo sera activé ensuite avec la désactivation de root):

adduser username

Sous debian, on peux prévoir de changer l’éditeur par défaut, de nano à Vim avec la commande :

update-alternatives --config editor

Pour les manipulations, on peux aussi faire en sorte d’afficher root en rouge dans le terminal pour savoir si on est root:

echo "PS1='\[\033[01;31m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]# '" >> /root/.bashrc

Etape 2: SSH

Ces étapes sont extraites de ce guide: https://messervices.cyber.gouv.fr/guides/usage-securise-dopenssh

1. Création d’une clé ssh

Pour utiliser ssh avec une connexion par clé, ce qui est recommandé par l’ANSSI on va avoir besoin d’une paire de clés. On va avoir 2 clés:

  • Une clé privée, à garder sur l’ordinateur ET A NE PAS PARTAGER
  • Une clé publique, à envoyer aux hôtes distants

Sous windows (et linux) on peux utiliser la commande:

ssh-keygen -t ed25519

Par défaut, 2 fichiers sont crée:

  • id_ed25519 qui contient la clé privée
  • _d_ed25519.pub qui contient la clé publique qui va être envoyée sur le serveur

on va ensuite ajouter les informations dans le fichier config de ssh pour simplifier la connexion dans le futur en tapant ssh <nom hote>. Dans le fichier ~/.ssh/config ajouter les lignes suivantes :

Host <server name>
    HostName <server name>
    IdentifyFile ~/.ssh/id_ed25519
    User username

2. Préparation de ssh

On va commencer par crée le dossier .ssh dans le dossier de l’utilisateur et lui ajouter notre clé:

mkdir -p /home/username/.ssh && chmod 0700 /home/username/.ssh

On va ensuite crée le fichier authorized_keys qui contiendra notre clé:

vim /home/username/.ssh/authorized_keys
  • Ajouter ensuite le contenu du fichier “id_ed25519.pub” dans ce fichier.

  • Enfin, changer les permissions du fichier:

chmod 600 /home/username/.ssh/authorized_keys

si lancé en tant que root, changer le propriétaire du fichier:

chown username:username /home/username/.ssh/authorized_keys

A partir de maintenant on peux se connecter en ssh avec notre utilisateur sur le serveur.

3. La modification du fichier de configuration

On va maintenant modifier des paramètres du serveur ssh:

  • Le port: Pour changer le port, on peux retirer le # de la ligne et modifier la valeur du port :
    Port 22
    
  • On force la vérification complèteme des informations avec la ligne StrictModes:
    StrictModes yes
    
  • Pour la connexion on active les lignes suivantes:
LoginGraceTime 2m
MaxAuthTries 3
  • On désactive la connexion de root comme on a un utilisateur qui peux se connecter:
PermitRootLogin no
  • Optionnel: Activer la commande qui affiche les infos de la dernière connexion:
PrintLastLog yes
  • On désactive le X11Forwarding (il ne servira pas car x11 n’est pas installé et ne le sera pas):
X11Forwarding no
  • Désactiver l’accès à SSH depuis un nom DNS, décommenter la ligne:
UseDNS no
  • Etablir la liste des utilisateurs qui peuvent se connecter en Ajoutant la ligne:
AllowUsers <user1> <user2> ...

Note: normalement il faudrait mettre cette liste dans /etc/ssh/sshd_config.d/50-allowusers.conf

  • A configurer pour les accès en réseau interne, en entreprise ou en réseau local, limiter l’accès aux personnes qui ont le droit de se connecter en SSH:

    • Pour les utilisateurs:
      AllowUsers username@[plageip]/[masque]
      
    • Pour les groupes:
      AllowGroups groupname@[plageip]/[masque]
      
  • Enfin, on autorise que les connexion via des clé en désactivant la connexion par mot de passe:

echo 'AuthenticationMethods publickey' >> /etc/ssh/sshd_config

4. SFTP

Par défaut SSH fournis un serveur SFTP accessible.

Cas 1: Désactiver sftp

La meilleure solution pour un service exposé, pour désactiver le FTP, il faut changer la ligne:

Subsystem      sftp    /usr/lib/openssh/sftp-server

par:

Subsystem sftp /bin/false
Cas 2: crée un chroot pour le sftp

La config est à faire. il y a plusieurs moyens de le faire: pour un groupe ou pour un utilisateur.

Etape 3: nftables

Il nous faut maintenant un firewall pour bloquer les ports crtique (base de données) et laisser ouvert ceux qui doivent l’être (ssh, serveur web).

Pour installer nftables sur Debian:

apt install nftables

On va ensuite modifier le fichier /etc/nftables.conf:

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
        chain input {
                type filter hook input priority filter; policy drop; # par défaut: drop les requetes (bonne pratique)
                iif lo accept # localhost
                ct state established,related accept # accepte les connexions déja commencées
                ct state invalid drop # bloque les connexions invalides
                ip protocol icmp accept # laisse le ping actif
                ip6 nexthdr icmpv6 drop # ping ipv6
                tcp dport { 80,443 } accept # ports serveurs web
                tcp dport 22 accept # ssh
                log prefix "NFT-INPUT-DROP: "
                drop
        }
        chain forward {
                type filter hook forward priority filter; policy drop;
        }
        chain output {
                type filter hook output priority filter; policy accept;

        }
}

Pour vérifier le fichier, on peux utiliser la commande:

nft -c -f /etc/nftables.conf

Pour prendre en compte les modifications:

nft -f /etc/nftables.conf

Sous debian, il faut activer le service:

systemctl enable --now nftables.service

Etape 4: Installer fail2ban

Maintenant on va pouvoir bannir les ip qui vont tenter des connexion bizarres sur les serveurs.

On commence par installer fail2ban:

apt install fail2ban

On va modifier plusieurs lignes dans la section DEFAULT du fichier /etc/fail2ban/jail.conf:

# Banni l'ip pour environ 1an
bantime = 8500h 
# Banni si il y a trop de tentatives en 1h
findtime = 10m
maxretry = 3
banaction = nftables-multiport
banaction_allports = nftables-allports

Dans [sshd] ajouter la ligne:

enabled = true

Dans [apache-auth] ajouter la ligne:

enabled = true

Dans [apache-badbots] ajouter la ligne:

enabled = true

Dans [apache-noscripts] ajouter la ligne:

enabled = true

Dans [nginx-http-auth] ajouter la ligne:

enabled = true

Dans [nginx-botsearch] ajouter la ligne:

enabled = true

La configuration est à adapter en fonction des besoins des services.

Etape 5 (optionnelle): activer les unattended-upgrades

Commencer par installer le paquet:

apt install unattended-upgrades

Ensuite on va générer le fichier de config avec la commande

dpkg-reconfigure --priority=low unattended-upgrades

Nous pouvons maintenant personnalisé notre configuration qui se trouve dans /etc/apt/apt.conf.d/50unattended-upgrades :

  • Décommenter la ligne suivante:
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
  • Décommenter et modifier la ligne suivante:
Unattended-Upgrade::Remove-Unused-Dependencies "false";
  • On peux limiter la bande passante (en ko/s) utilisée pour les mises à jours avec la ligne à décommenter:
Acquire::http::Dl-Limit "1024"; // Autorise 1Mo/s de bande passantes pour les mises à jour
  • Pour les redémarrage:
    • On peux Désactiver le reboot automatique car il peux redémarrer n’importe quand le serveur:
    Unattended-Upgrade::Automatic-Reboot "false";
    
    • On peux également choisir de redémarrer à une heure précise:
    Unattended-Upgrade::Automatic-Reboot "true"; // autorise le reboot
    Unattended-Upgrade::Automatic-Reboot-Time "07:00"; // a 7h du matin
    Unattended-Upgrade::Automatic-Reboot-WithUsers "false"; // ne redémarre pas si un utilisateur est connecté
    
  • Activer les logs:
Unattended-Upgrade::SyslogEnable "true";

On va maintenant aller dans /etc/apt/apt.conf.d/20auto-upgrades et ajouter ces lignes:

APT::Periodic::Update-Package-Lists "4"; // lance apt update tous les X jours
APT::Periodic::Download-Upgradeable-Packages "4"; // Télécharge les mises à jours sans les appliquer tous les X jours
APT::Periodic::Unattended-Upgrade "7"; // lance le script de mise à jour tous les X jours
APT::Periodic::AutocleanInterval "14"; // lance apt autoremove touts les X jours

Pour terminer avec les mises à jours automatique, on va éditer le fichier timer de service:

systemctl edit apt-daily-upgrade.timer

Ensuite changer l’heure à laquelle le service doit effectuer les mises à jour. Personnellement je trouve que 7h est une bonne heure, en cas de problème je peux rapidement intervenir et il s’agit de moments où il y a le moins de traffic.

[Timer]
OnCalendar=*-*-* 7:00
RandomizedDelaySec=60m
Persistent=true

On redémarre le service:

systemctl edit apt-daily.timer

On change maintenat le apt daily:

systemctl edit apt-daily.timer

On change la config:

[Timer]
OnCalendar=
OnCalendar=06:00
RandomizedDelaySec=0

On termine par redémarrer le timer:

systemctl restart apt-daily.timer

Pour vérifier, on peux utiliser la commande:

systemctl status apt-daily.timer apt-daily-upgrade.timer

Pour éviter les problèmes, on peux couper les services avant la mise à jour puis les redémarrer après la mise à jour. De mon coté je pense qu’utiliser le fichier /etc/apt/apt.conf.d/50unattended-upgrades est bien, sinon il faut en créer un autre. Voici le contenu pour nginx:

Dpkg::Pre-Invoke {"systemctl stop nginx";};
Dpkg::Post-Invoke {"systemctl start nginx";};

Etape 6 (optionnelle): Activer sudo et désactiver root

Par défault sur debian et sur beaucoup de services un compte root est crée et rien d’autre. Pour des raisons de sécurité et simplicité il peux être intéressant d’utiliser sudo plutot que la connexion root.

On commence par installer sudo:

apt install sudo

Ensuite on ajoute notre utilisateur au groupe sudo:

usermod -aG sudo username

Pour désactiver root:

usermod -p '!' root 

Notre utilisateur aura accès à sudo et le compte root ne pourra plus se conecté. Si besoin de réactiver le compte root, il faut utiliser la commande:

sudo passwd root

En vrac

Autoriser les services utilisateur à fonctionner après la deconnexion de l’utilisateur

Il faut lancer la commande:

sudo loginctl enable-linger $USER

Sources

https://wiki.debian.org/fr/PeriodicUpdates https://dev.to/lyraalishaikh/unattended-upgrades-without-surprises-debianubuntu-patch-automation-with-audit-logs-and-klc https://wiki.blablalinux.be/fr/debian-unattended-upgrades https://slash-root.fr/debian-configuration-complete-dunattended-upgrades-pour-une-securite-sans-effort/ https://www.linuxtricks.fr/wiki/debian-activer-les-mises-a-jour-automatique-avec-unattended-upgrades