Sécuriser un serveur dédié avec firewall et Fail2ban

Un serveur dédié fraîchement installé attire très vite les robots. SSH, HTTP, SMTP, IMAP, WordPress, Webmail : chaque service exposé devient une petite sonnette sur laquelle quelqu’un finit par appuyer.

La bonne nouvelle, c’est qu’il n’est pas nécessaire de transformer son serveur en bunker administratif. Il faut surtout appliquer une règle simple : ouvrir uniquement les ports utiles, journaliser proprement, puis bannir les comportements répétitifs avec Fail2ban.

Historiquement, on faisait cela avec des scripts iptables lancés au démarrage. Aujourd’hui, sur Debian et Ubuntu récents, il vaut mieux utiliser UFW pour un serveur simple, ou nftables pour une configuration plus fine. Fail2ban vient ensuite compléter le dispositif.

Faut-il encore utiliser iptables ?

Pas pour une nouvelle configuration.

iptables existe toujours, mais il sert souvent de couche de compatibilité vers nftables. Sur Debian, nftables est le framework par défaut depuis Debian 10. Sur Ubuntu récent, l’outil iptables-nft utilise également le backend nftables.

En clair : si vous démarrez aujourd’hui, évitez les vieux scripts dans /etc/init.d/. Ils fonctionnent parfois encore, mais ils compliquent la maintenance. Et la maintenance, c’est déjà assez drôle comme ça un dimanche soir.

Pour un serveur web classique, je recommande cette approche :

  • UFW pour un serveur simple : SSH, HTTP, HTTPS, éventuellement mail.
  • nftables pour une configuration avancée : règles personnalisées, sets, rate limiting, routage, politique réseau plus stricte.
  • Fail2ban pour bannir les IP qui abusent des services exposés.

Choisissez une seule méthode principale. Ne mélangez pas UFW, nftables natif, firewalld et scripts iptables maison sur le même serveur. Sinon, vous ne configurez plus un firewall : vous lancez une escape room.

Avant de toucher au firewall : gardez une porte de secours

Avant d’activer une politique restrictive, ouvrez toujours une seconde session SSH. Gardez-la connectée pendant toute la configuration.

Ensuite, identifiez vos ports réellement utilisés :

sudo ss -tulpn

Vous pouvez aussi vérifier les services actifs :

systemctl --type=service --state=running

Sur un serveur web classique, vous aurez souvent besoin de ces ports :

ServicePortExposition recommandée
SSH22 ou port personnaliséRestreindre à votre IP si possible
HTTP80Ouvert au public
HTTPS443Ouvert au public
SMTP25Seulement si le serveur gère le mail
Submission587Seulement pour le mail authentifié
IMAPS993Seulement si le serveur héberge des boîtes mail
POP3S995À éviter si IMAP suffit
Webmin10000Restreindre à votre IP ou VPN

Le principe est simple : si un port n’a pas de raison claire d’être public, il ne doit pas être public.

Distingo, le livret à 2%

Option recommandée : configurer UFW

UFW convient très bien à la majorité des serveurs dédiés web. Il simplifie la gestion du firewall sans vous obliger à écrire des règles nftables à la main.

Installez UFW :

sudo apt update
sudo apt install ufw

Définissez d’abord les politiques par défaut :

sudo ufw default deny incoming
sudo ufw default allow outgoingCode language: JavaScript (javascript)

Autorisez SSH avant d’activer le firewall. Si votre SSH utilise le port 22 :

sudo ufw allow 22/tcp

Si vous utilisez un port SSH personnalisé, remplacez le port :

sudo ufw allow 2222/tcp

Encore mieux : si vous avez une IP fixe, limitez SSH à cette IP :

sudo ufw allow from 203.0.113.10 to any port 22 proto tcpCode language: CSS (css)

Autorisez ensuite le web :

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Si votre serveur gère aussi le courrier, ajoutez seulement les ports nécessaires :

sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp

Activez ensuite UFW :

sudo ufw enable

Vérifiez l’état du firewall :

sudo ufw status verbose
sudo ufw status numbered

Pour supprimer une règle, utilisez son numéro :

sudo ufw delete 3Code language: JavaScript (javascript)

Tester le firewall depuis l’extérieur

Ne testez pas uniquement depuis le serveur lui-même. Testez aussi depuis votre machine locale ou depuis une autre connexion.

Depuis votre poste :

nc -vz example.com 22
nc -vz example.com 80
nc -vz example.com 443Code language: CSS (css)

Avec Nmap, vous pouvez faire un contrôle plus complet :

nmap -Pn -p 1-10000 example.comCode language: CSS (css)

Sur le serveur, surveillez les connexions et les logs pendant vos tests :

sudo journalctl -f
sudo tail -f /var/log/auth.logCode language: JavaScript (javascript)

Sur certaines distributions, les logs SSH passent surtout par le journal systemd. Dans ce cas, utilisez :

sudo journalctl -u ssh -f
sudo journalctl -u sshd -f

Option avancée : une base nftables propre

Si vous préférez piloter le firewall directement avec nftables, n’activez pas UFW en parallèle. Choisissez nftables comme source de vérité.

Installez nftables :

sudo apt update
sudo apt install nftables

Activez le service :

sudo systemctl enable nftables
sudo systemctl start nftables

Éditez la configuration principale :

sudo nano /etc/nftables.conf

Voici une base raisonnable pour un serveur web avec SSH, HTTP et HTTPS :

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0;
        policy drop;

        iif "lo" accept

        ct state established,related accept
        ct state invalid drop

        ip protocol icmp accept
        ip6 nexthdr ipv6-icmp accept

        tcp dport 22 accept
        tcp dport { 80, 443 } accept

        counter drop
    }

    chain forward {
        type filter hook forward priority 0;
        policy drop;
    }

    chain output {
        type filter hook output priority 0;
        policy accept;
    }
}Code language: JavaScript (javascript)

Testez la syntaxe avant de charger les règles :

sudo nft -c -f /etc/nftables.conf

Chargez ensuite la configuration :

sudo systemctl reload nftables

Listez les règles actives :

sudo nft list rulesetCode language: PHP (php)

Si vous hébergez aussi un serveur mail, ajoutez les ports nécessaires dans la règle TCP :

tcp dport { 22, 25, 80, 443, 587, 993 } accept

Évitez d’ouvrir POP3, IMAP non chiffré, FTP ou des interfaces d’administration publiques sans filtrage IP. Ce sont des invitations. Et les robots adorent les invitations.

Installer Fail2ban

Le firewall décide quels ports existent. Fail2ban, lui, observe les logs et bannit les IP qui échouent trop souvent. Il est particulièrement utile pour SSH, Postfix, Dovecot, Nginx, Apache ou certains endpoints applicatifs.

Installez Fail2ban :

sudo apt update
sudo apt install fail2ban

Ne modifiez pas directement jail.conf. Créez un fichier local dédié :

sudo nano /etc/fail2ban/jail.local

Pour un serveur utilisant UFW, vous pouvez démarrer avec cette configuration :

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
banaction = ufw

[sshd]
enabled = true
port = ssh
mode = normalCode language: PHP (php)

Remplacez 203.0.113.10 par votre IP d’administration. Si votre port SSH n’est pas le port 22, adaptez aussi port :

[sshd]
enabled = true
port = 2222
mode = normalCode language: JavaScript (javascript)

Redémarrez Fail2ban :

sudo systemctl enable fail2ban
sudo systemctl restart fail2ban

Vérifiez son état :

sudo fail2ban-client status
sudo fail2ban-client status sshd

Pour voir les logs Fail2ban :

sudo journalctl -u fail2ban -f
sudo tail -f /var/log/fail2ban.logCode language: JavaScript (javascript)

Fail2ban avec nftables

Si votre firewall principal utilise nftables, configurez Fail2ban pour bannir avec nftables plutôt qu’avec iptables.

Dans /etc/fail2ban/jail.local, utilisez par exemple :

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
banaction = nftables
banaction_allports = nftables[type=allports]

[sshd]
enabled = true
port = ssh
mode = normalCode language: PHP (php)

Selon la version empaquetée par votre distribution, l’action nftables peut s’appeler différemment. Vous pouvez vérifier les actions disponibles :

ls /etc/fail2ban/action.d/ | grep nft

Après redémarrage, contrôlez que les bans apparaissent bien :

sudo fail2ban-client status sshd
sudo nft list rulesetCode language: PHP (php)

Bannir et débannir une IP avec Fail2ban

Pour bannir manuellement une IP dans la jail SSH :

sudo fail2ban-client set sshd banip 198.51.100.25Code language: CSS (css)

Pour la débannir :

sudo fail2ban-client set sshd unbanip 198.51.100.25Code language: CSS (css)

Pour lister les IP bannies :

sudo fail2ban-client status sshd

Ajouter une protection Fail2ban pour Nginx

Fail2ban peut aussi surveiller Nginx. Par exemple, la jail nginx-http-auth bloque les authentifications HTTP répétées.

Ajoutez dans /etc/fail2ban/jail.local :

[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 5Code language: JavaScript (javascript)

Si vos logs Nginx sont ailleurs, adaptez logpath. Sur un serveur multi-sites, vous pouvez utiliser un motif :

logpath = /var/log/nginx/*error.logCode language: JavaScript (javascript)

Rechargez ensuite Fail2ban :

sudo systemctl restart fail2ban
sudo fail2ban-client status nginx-http-auth

Ajouter une protection Fail2ban pour Postfix et Dovecot

Si le serveur héberge le mail, protégez aussi Postfix et Dovecot. Les attaques par dictionnaire sur SMTP et IMAP sont très fréquentes.

Exemple de jails :

[postfix]
enabled = true
port = smtp,submission
backend = systemd
maxretry = 5

[dovecot]
enabled = true
port = imaps,pop3s
backend = systemd
maxretry = 5Code language: JavaScript (javascript)

Si votre distribution journalise dans des fichiers classiques, utilisez plutôt les chemins de logs adaptés, souvent sous /var/log/mail.log.

sudo journalctl -u postfix -f
sudo journalctl -u dovecot -f
sudo tail -f /var/log/mail.logCode language: JavaScript (javascript)

Renforcer SSH avant de compter sur Fail2ban

Fail2ban aide, mais il ne remplace pas une configuration SSH propre. Le meilleur ban reste celui qui n’a jamais besoin d’arriver.

Éditez la configuration SSH :

sudo nano /etc/ssh/sshd_config

Vérifiez ces directives :

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30

Testez la configuration avant de redémarrer SSH :

sudo sshd -t

Puis rechargez SSH :

sudo systemctl reload ssh
sudo systemctl reload sshd

La commande exacte dépend du nom du service sur votre distribution. Si l’une échoue, l’autre est souvent la bonne.

Bonnes pratiques pour ne pas se verrouiller dehors

  • Gardez une session SSH ouverte pendant vos changements.
  • Autorisez SSH avant d’activer le firewall.
  • Testez depuis une autre connexion avant de fermer votre session.
  • Ajoutez votre IP fixe dans ignoreip côté Fail2ban.
  • Documentez vos ports ouverts dans un fichier d’administration.
  • Évitez de mélanger UFW, nftables natif et scripts iptables.
  • Surveillez les logs après chaque modification.

Commandes de diagnostic utiles

Voir les ports ouverts :

sudo ss -tulpn

Voir les règles UFW :

sudo ufw status numbered

Voir les règles nftables :

sudo nft list rulesetCode language: PHP (php)

Voir les jails Fail2ban :

sudo fail2ban-client status

Voir une jail précise :

sudo fail2ban-client status sshd

Voir les logs SSH :

sudo journalctl -u ssh -f
sudo journalctl -u sshd -f
sudo tail -f /var/log/auth.logCode language: JavaScript (javascript)

Voir les logs Fail2ban :

sudo journalctl -u fail2ban -f
sudo tail -f /var/log/fail2ban.logCode language: JavaScript (javascript)

Quelle configuration choisir ?

Pour un serveur WordPress, WooCommerce ou un serveur web classique, choisissez UFW + Fail2ban. C’est lisible, rapide à maintenir, et suffisant dans la majorité des cas.

Pour un serveur plus complexe, avec routage, conteneurs, règles réseau avancées ou politique multi-services stricte, choisissez nftables + Fail2ban. Vous gagnerez en contrôle, mais vous devrez documenter davantage.

Dans les deux cas, le plus important reste la cohérence. Un firewall simple, compris et vérifié vaut mieux qu’une forteresse copiée-collée dont personne ne connaît les oubliettes.

Besoin d’un serveur vraiment propre ?

Je configure, sécurise et optimise des serveurs web pour WordPress, WooCommerce et les projets PHP exigeants. L’objectif : moins de bruit dans les logs, moins de surface d’attaque, et plus de sérénité au quotidien.

  • configuration firewall UFW ou nftables ;
  • durcissement SSH, Fail2ban, TLS et services exposés ;
  • optimisation Nginx, PHP-FPM, Redis, MariaDB ou MySQL ;
  • audit de sécurité et nettoyage des configurations historiques ;
  • migration de serveurs et remise à plat d’environnements WordPress.

Si votre serveur a grandi par couches successives, je peux vous aider à le remettre au carré. Contactez-moi et on regarde ça sérieusement.

Articles connexes

FAQ

UFW remplace-t-il iptables ?

UFW ne remplace pas le firewall du noyau Linux. Il fournit une interface simple pour gérer les règles. Sur les distributions modernes, ces règles s’appuient souvent sur le backend nftables via les outils de compatibilité.

Faut-il utiliser UFW ou nftables ?

Utilisez UFW pour un serveur web simple. Utilisez nftables si vous avez besoin d’une configuration réseau avancée, plus explicite ou plus fine.

Fail2ban suffit-il à sécuriser SSH ?

Non. Fail2ban limite les attaques répétées, mais SSH doit d’abord être renforcé : connexion par clé, désactivation du login root, désactivation des mots de passe et limitation du nombre d’essais.

Puis-je utiliser UFW et nftables en même temps ?

Techniquement, certains composants peuvent coexister. En pratique, évitez de gérer des règles nftables natives tout en utilisant UFW. Vous risquez de rendre l’ordre des règles difficile à comprendre.

Quel port SSH faut-il utiliser ?

Changer le port SSH réduit le bruit automatisé dans les logs, mais ce n’est pas une vraie mesure de sécurité. Les clés SSH, les restrictions IP et la désactivation des mots de passe comptent davantage.

Pourquoi mon IP est-elle bannie par Fail2ban ?

Votre client SSH, votre application mail ou un script peut générer trop d’échecs. Ajoutez votre IP fixe dans ignoreip, puis vérifiez les logs de la jail concernée.

Sources

Demandez à l'IA son opinion
Gravatar for Matt Biscay

Je suis Matt Biscay, développeur WordPress & WooCommerce certifié chez Codeable, administrateur système et enseignant.

J’aide les entreprises à créer, optimiser et fiabiliser leurs sites WordPress avec une approche technique propre : performance, sécurité, maintenance, développement sur mesure et résolution de problèmes complexes.

Sur Skyminds, je partage des tutoriels WordPress, WooCommerce, Linux et administration système, avec des solutions testées sur des cas réels et pensées pour durer.

Découvrez mes services WordPress et WooCommerce.

10 pensées sur “Sécuriser un serveur dédié avec firewall et Fail2ban”

  1. Salut matt,

    Merci pour ces super tutoriaux!

    J’ai rencontrer un problème suite a l’utilisation du tuto fail2ban…

    Sur kimsufi, fraichement installée debian. j’utilise le script virtual min pour administrer tout ca.

    avant de faire un peu de securisation, les acces au ftp créers lors de la creation avec virtualmin d’un nouveau serveur virtuel, fonctionné par faitement.

    Depuis je ne peux plus accedder a mes espac ftp qui sont reservé a chaque serveur virtuel…

    Tu pourrais me donner quelque indice pour reparer tout ca

    Reply
    • Salut Majeri,

      Ce n’est pas au niveau de fail2ban que ça bloque mais au niveau des règles iptables : sur mon serveur, je n’ai pas installé de serveur FTP, je n’utilise qu’SSH qui est sécurisé donc je n’ai pas ouvert les ports FTP.

      Rajoute ceci dans les règles iptables :

      # FTP (BACKUP)
      iptables -t filter -A INPUT -p tcp --dport 21 -j ACCEPT
      iptables -t filter -A OUTPUT -p tcp --dport 21 -j ACCEPT

      J’ai édité l’article pour refléter les changements.

      Reply
  2. Merci, j’avais finalement noté qu’il n’y avait pas de règles pour le ftp sur iptable :) D’autant que j’avais rajouter ces règles de ftp sur mon précédent serveur quand j’avais suvi ton tuto :)

    tiens au passage un articles qui pourrait être rajouter a ta séries de tuto: L’optimisation de la config de mysql avec des script comme MySQL Tuner ou encore Tuning Primer…

    ++

    Reply
    • Ah oui tiens, c’est une bonne idée (surtout que je me suis servi des 2 scripts pour tuner MySQL dès le départ). J’ajoute ça à ma todo-list !

      Reply
  3. Bonjour Matt et merci pour ce tuto

    Une simple remarque, pour que les configurations soient prises au démarrage de la machine il faut ajouter dans l’en tête du fichier d’iptables :

    #!/bin/sh
    ### BEGIN INIT INFO
    # Provides: firewall
    # Required-Start: $remote_fs $syslog
    # Required-Stop: $remote_fs $syslog
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Short-Description: Démarre les règles iptables
    # Description: Charge la configuration du pare-feu iptables
    ### END INIT INFO

    Ensuite -> uptate-rc.d fichier defaults

    Le tour est joué :)

    (Debian Wheezy)

    Reply
  4. Sur ma config, le #!/bin/sh n’étant pas en premier le fichier iptable crash chaque ligne :

    ‘ptables v1.4.21: Invalid target name `ACCEPT
    Try `iptables -h’ or ‘iptables –help’ for more information.
    /etc/init.d/firewall: line 63: $’r’: command not found

    Alors que si le fichier commence par #!/bin/sh, aucun problème, mais je ne sais pas si ca passe pour le lancement automatique au démarrage.

    Avec les commandes suivantes :
    iptables -t filter -F
    iptables -t filter -P INPUT DROP
    iptables -t filter -P FORWARD DROP
    iptables -t filter -P OUTPUT DROP

    Je suis bon pour une journée de galère nan ? En l’espèce j’ai fait une réinstallation dans la mesure ou j’étais en test, mais en prod en me pose la question !!

    Reply
    • Bonjour,

      Sous Debian 6, 7 et 8 le fichier tel quel (avec les entêtes) fonctionne sans problème.

      Vérifie la ligne 63, c’est celle qui semble poser problème au niveau de la syntaxe.

      Reply
  5. Salut,
    J’ai un petit problème avec le firewall il fait planter la console SSH, j’aimerait comment résoudre ce “petit” problème .

    Merci pour ce magnifique tuto,
    GGLinnk.

    Reply

Opinions