Sécuriser votre serveur Linux
La sécurisation d'un serveur Linux est la première étape avant tout déploiement en production. Un VPS fraîchement créé avec une adresse IP publique reçoit des tentatives de connexion SSH automatisées en quelques minutes : des robots parcourent en permanence Internet à la recherche de mots de passe faibles, de services mal configurés et de logiciels non mis à jour. Voici les mesures essentielles, dans l'ordre où je les applique sur une nouvelle machine.
L'objectif n'est pas de rendre le serveur inviolable, ce qui n'existe pas, mais de réduire la surface d'attaque et de rendre les attaques opportunistes inefficaces. Les exemples ci-dessous visent Debian et Ubuntu ; les principes s'appliquent à toutes les distributions.
Préparer un utilisateur et une clé SSH
Avant de toucher à la configuration SSH, créez un utilisateur non privilégié et vérifiez que vous pouvez vous connecter avec une clé. C'est l'étape qui évite de s'enfermer dehors. Sur votre poste, générez une clé Ed25519 si vous n'en avez pas, puis copiez-la sur le serveur :
# Sur le serveur (en root)
adduser deploy
usermod -aG sudo deploy
# Sur votre poste
ssh-keygen -t ed25519 -C "deploy@monserveur"
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
ssh [email protected]
Ne passez à la suite qu'une fois la connexion par clé réussie avec le nouvel utilisateur, et vérifiez qu'il peut utiliser sudo.
Configuration SSH
# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Port 2222
MaxAuthTries 3
AllowUsers deploy
Chaque directive a un rôle précis :
PermitRootLogin no: le compte root, présent sur toutes les machines, est la première cible des attaques. Les administrateurs se connectent avec leur propre compte, puis utilisentsudo, ce qui laisse une trace nominative.PasswordAuthentication no: sans mot de passe, les attaques par dictionnaire deviennent inutiles. Pensez aussi àKbdInteractiveAuthentication no, sinon une authentification par mot de passe peut rester possible via PAM.Port 2222: changer de port ne protège pas contre une attaque ciblée, mais réduit fortement le bruit dans les logs.MaxAuthTries 3: limite le nombre de tentatives par connexion.AllowUsers deploy: liste blanche des comptes autorisés à se connecter. Tout autre utilisateur est refusé, même avec une clé valide.
Sur les distributions récentes, vous pouvez placer ces directives dans un fichier dédié, par exemple /etc/ssh/sshd_config.d/hardening.conf, plutôt que de modifier le fichier principal. Attention : pour chaque directive, sshd retient la première valeur lue, et les fichiers inclus sont lus au début. Avant de redémarrer, testez toujours la configuration et gardez votre session actuelle ouverte :
sudo sshd -t && sudo systemctl restart ssh
# Depuis un second terminal, avant de fermer la session actuelle :
ssh -p 2222 [email protected]
Sur Ubuntu 24.04, SSH est activé par socket systemd : après un changement de port, lancez sudo systemctl daemon-reload puis sudo systemctl restart ssh.socket pour que le nouveau port soit pris en compte.
Firewall avec UFW
Le principe du pare-feu est simple : tout refuser en entrée, puis ouvrir explicitement les seuls ports nécessaires. UFW (Uncomplicated Firewall) est une surcouche lisible à nftables/iptables, installée par défaut sur Ubuntu.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
L'ordre compte : autorisez le port SSH avant d'exécuter ufw enable, sinon la connexion en cours risque d'être coupée. Vérifiez ensuite les règles avec sudo ufw status verbose. Deux options utiles :
sudo ufw limit 2222/tcpremplace la règleallowet refuse une adresse qui tente 6 connexions ou plus en 30 secondes.sudo ufw allow from 10.0.0.0/24 to any port 5432 proto tcpouvre un port uniquement pour un réseau privé, par exemple pour une base de données.
Piège important : Docker contourne UFW. Un port publié avec -p 5432:5432 est accessible depuis Internet même si UFW ne l'autorise pas, car Docker écrit ses propres règles iptables. Publiez les ports internes sur 127.0.0.1 (-p 127.0.0.1:5432:5432) ou ne les publiez pas du tout.
Mises à jour automatiques
La majorité des compromissions exploitent des vulnérabilités connues et déjà corrigées. Le paquet unattended-upgrades installe automatiquement les mises à jour de sécurité :
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
Par défaut, seules les mises à jour de sécurité sont appliquées. Certaines, notamment celles du noyau, ne prennent effet qu'après un redémarrage. Vous pouvez autoriser un redémarrage automatique à une heure creuse dans /etc/apt/apt.conf.d/50unattended-upgrades :
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
Pour vérifier la configuration sans rien installer : sudo unattended-upgrade --dry-run --debug. Sur un serveur qui ne doit pas redémarrer seul, laissez cette option désactivée et surveillez la présence du fichier /var/run/reboot-required.
Fail2Ban
Protégez-vous contre les attaques par force brute :
sudo apt install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Fail2Ban lit les journaux, repère les échecs d'authentification répétés et bannit temporairement l'adresse IP fautive via le pare-feu. Le fichier jail.conf peut être écrasé lors des mises à jour : on travaille toujours dans jail.local. Plutôt que de copier tout le fichier, il suffit souvent d'y écrire uniquement les valeurs à surcharger :
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
[sshd]
enabled = true
port = 2222
Le backend = systemd est nécessaire sur Debian 12, où les connexions SSH sont journalisées dans journald et non plus dans /var/log/auth.log. N'oubliez pas d'indiquer le port SSH personnalisé, sinon le bannissement porterait sur le port 22. Quelques commandes utiles :
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 198.51.100.7
Réduire la surface d'attaque
Chaque service qui écoute sur le réseau est une porte potentielle. Listez les ports ouverts et désactivez tout ce qui n'est pas nécessaire :
sudo ss -tulpn
sudo systemctl disable --now cups.service # exemple : service inutile sur un serveur
Les bases de données, Redis ou les interfaces d'administration doivent écouter sur 127.0.0.1 ou sur un réseau privé, jamais sur l'interface publique. Quelques paramètres noyau renforcent aussi la pile réseau :
# /etc/sysctl.d/99-hardening.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
Appliquez-les avec sudo sysctl --system.
Logs et audit
Un serveur sécurisé doit aussi permettre de comprendre ce qui s'est passé après coup. Rendez le journal systemd persistant (Storage=persistent dans /etc/systemd/journald.conf), et envoyez les journaux vers une machine distincte : un attaquant qui obtient les droits root peut effacer les logs locaux. Pour un contrôle régulier, l'outil Lynis (sudo lynis audit system) passe en revue des centaines de points de configuration et propose des améliorations concrètes.
Checklist de sécurité
- Désactiver le login root par SSH
- Utiliser uniquement l'authentification par clé
- Configurer un firewall restrictif
- Installer et configurer Fail2Ban
- Activer les mises à jour automatiques de sécurité
- Configurer les logs centralisés
- Mettre en place un monitoring système
- Vérifier les ports ouverts avec
ss -tulpnet les ports publiés par Docker - Mettre en place des sauvegardes externalisées et tester leur restauration
La sécurité est un processus continu, pas une configuration faite une fois pour toutes : relancez un audit après chaque changement important et gardez les accès au strict nécessaire.