SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-09-04

Configurer firewalld sur un VPS Rocky ou AlmaLinux

Ouvrez SSH et un port web, fermez-en un autre et conservez les règles après redémarrage. Comprenez les zones et le piège de l’option --permanent.

Ce qu’est firewalld et pourquoi Rocky et AlmaLinux l’incluent

firewalld est le gestionnaire de pare-feu installé par défaut sur Rocky Linux, AlmaLinux et les autres reconstructions de Red Hat Enterprise Linux (RHEL). Les deux distributions ont repris cette configuration par défaut au lieu de la choisir, ce qui devient plus clair lorsque vous savez comment Rocky et AlmaLinux ont repris le travail de Red Hat après le changement d’orientation de CentOS. firewalld n’inspecte pas lui-même les paquets. Il conserve une configuration enregistrée et la transforme en règles nftables. La commande firewall-cmd permet de la modifier sans interrompre le serveur. Rien dans ce guide ne change entre les deux distributions, car ce qui distingue réellement Rocky d’AlmaLinux concerne la promesse de compatibilité et la gamme de processeurs encore pris en charge, pas le pare-feu.

Si vous savez déjà comment fonctionne ufw sur un VPS Ubuntu, vous connaissez le principe. firewalld ajoute deux notions absentes d’ufw. La première est celle des zones : une stratégie nommée dans laquelle les paquets sont classés. La seconde est la séparation entre les règles actives et les règles enregistrées. Elle repose sur l’option --permanent et constitue la principale source de confusion avec cet outil.

Tout ce qui suit correspond à une commande à exécuter sur votre propre serveur. Testez chaque modification depuis une deuxième machine, car une règle qui semble correcte sur le serveur peut malgré tout être incorrecte depuis Internet.

Ouvrez SSH avant toute autre opération

La plupart des installations Rocky et AlmaLinux ont déjà firewalld installé et actif, et la configuration fournie autorise SSH. Certaines images cloud minimales le suppriment. Vérifiez plutôt que de partir du principe qu’il est présent.

sudo dnf install -y firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --state

firewall-cmd --state affiche running. Si le service est arrêté, tous les autres appels à firewall-cmd renvoient FirewallD is not running et se terminent avec un code différent de zéro. C’est la première chose à vérifier lorsqu’une commande semble ne rien faire.

Affichez maintenant ce qui est actuellement autorisé.

sudo firewall-cmd --list-all

La sortie réelle contient quelques lignes supplémentaires. Voici celles qui comptent :

public (active)
  target: default
  interfaces: eth0
  sources:
  services: cockpit dhcpv6-client ssh
  ports:
  rich rules:

ssh dans la ligne services: explique pourquoi votre session fonctionne encore. S’il est absent, ajoutez-le avant toute autre modification, car démarrer un firewall sans règle SSH ferme la session et vous empêche de vous reconnecter.

sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload

target: default signifie qu’un paquet ne correspondant à aucune règle est rejeté avec une réponse ICMP (Internet Control Message Protocol) host-prohibited. Un client qui tente d’atteindre un port fermé voit donc immédiatement No route to host. Définir la cible sur DROP rend au contraire le serveur silencieux : les scanners attendent alors l’expiration du délai.

sudo firewall-cmd --permanent --zone=public --set-target=DROP
sudo firewall-cmd --reload

Prenez en compte cette conséquence avant d’exécuter la commande : DROP empêche également le serveur de répondre à ping. Votre propre monitoring devient donc lui aussi silencieux.

Pourquoi ma règle a-t-elle disparu ? Le flag --permanent

firewalld conserve deux configurations à la fois. La configuration runtime correspond à ce que le kernel applique à cet instant. La configuration permanente est enregistrée dans /etc/firewalld/zones/public.xml et réapparaît après un reload ou un reboot.

Une commande sans --permanent ne modifie que la configuration runtime. Elle prend effet immédiatement et disparaît au prochain reload ou boot. Une commande avec --permanent écrit dans le fichier sans modifier ce qui est en cours d’exécution. Le port reste donc fermé jusqu’au reload. Aucun de ces comportements n’est un bug. Ils surprennent pourtant souvent, car la commande affiche success dans les deux cas.

Écrivez toujours les deux commandes.

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

Vous pouvez lire les deux configurations. C’est le moyen le plus rapide de déterminer laquelle des deux erreurs vous avez commise.

sudo firewall-cmd --list-services
sudo firewall-cmd --permanent --list-services

La première commande affiche l’ensemble actif. La seconde affiche l’ensemble enregistré. Si l’ensemble actif contient un service que l’ensemble enregistré ne contient pas, cette règle disparaît au prochain reload. Si l’ensemble enregistré contient une règle absente de l’ensemble actif, vous avez oublié le reload. sudo firewall-cmd --runtime-to-permanent copie tout le contenu actif dans le fichier enregistré. Cette commande est utile après une session de tests.

--reload conserve l’état du suivi des connexions. Votre session SSH reste donc active. --complete-reload recharge également les modules du kernel et perd cet état. Cela interrompt généralement toutes les connexions ouvertes, y compris la vôtre. Utilisez le reload standard.

Un mécanisme de sécurité est intégré. Une règle runtime peut expirer automatiquement.

sudo firewall-cmd --add-service=http --timeout=5m

Cette règle se supprime après cinq minutes. Elle ne peut pas être combinée avec --permanent. C’est précisément son objectif : tester une modification dont vous n’êtes pas sûr. L’ancien mécanisme de sécurité reste préférable. Gardez une deuxième session SSH ouverte pendant la modification des règles. Ne la fermez pas tant qu’une nouvelle connexion ne confirme pas que les nouvelles règles fonctionnent.

Zones et raison pour laquelle seule la zone par défaut compte sur un VPS

Une zone est un ensemble nommé d’autorisations auquel est associé un niveau de confiance. firewalld place chaque paquet entrant dans une seule zone. Il compare d’abord l’adresse source du paquet à la liste sources: de chaque zone. Si aucune correspondance n’est trouvée, il utilise la zone à laquelle l’interface réseau entrante est associée. Si l’interface n’est associée à aucune zone, le paquet est placé dans la zone par défaut.

sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zones

Sur un VPS doté d’une seule interface réseau, la première réponse est presque toujours public. C’est la seule zone que vous utiliserez. firewall-cmd sans argument --zone= agit sur la zone par défaut. C’est pourquoi toutes les commandes courtes de ce guide fonctionnent sans préciser de zone.

Voici le problème qui peut vous faire perdre une après-midi. Si l’interface est associée à une autre zone, vos règles sont ajoutées à public alors que le trafic est traité ailleurs. Rien de ce que vous ajoutez n’a donc d’effet, et aucun avertissement ne vous en informe. --get-active-zones affiche cette association :

public
  interfaces: eth0

Si l’interface apparaît sous un autre nom de zone, écrivez vos règles dans cette zone avec --zone= ou déplacez l’interface.

sudo firewall-cmd --permanent --zone=public --change-interface=eth0
sudo firewall-cmd --reload

NetworkManager gère les interfaces sur Rocky et AlmaLinux. Il rétablit la zone lorsque la connexion est activée. Configurez-la également à cet endroit afin qu’un redémarrage n’annule pas vos modifications. Reprenez le nom de la connexion dans la première commande, car il est rarement identique au nom du périphérique.

sudo nmcli connection show
sudo nmcli connection modify "System eth0" connection.zone public

La correspondance sur l’adresse source est prioritaire sur la correspondance sur l’interface. C’est ce qui permet d’appliquer une politique différente à une adresse donnée. La zone intégrée trusted autorise tout.

sudo firewall-cmd --permanent --zone=trusted --add-source=203.0.113.10/32
sudo firewall-cmd --reload

Soyez prudent avec cette zone. Elle ouvre tous les ports du serveur à cette adresse, y compris celui de la base de données que vous pensiez privée. Utilisez une rich rule lorsque vous voulez autoriser un seul port plutôt qu’un hôte entier.

Qu’est-ce qu’un service firewalld ?

Un service est un ensemble nommé de ports, fourni sous forme de fichier XML. --add-service=https ouvre 443/tcp, car /usr/lib/firewalld/services/https.xml définit ce que https signifie.

sudo firewall-cmd --get-services
sudo firewall-cmd --info-service=https

--info-service affiche les ports correspondant à ce nom :

https
  ports: 443/tcp

Utilisez le nom lorsqu’il existe. La configuration reste claire dans --list-all six mois plus tard, et des paquets comme Cockpit installent leur propre fichier de service. Utilisez --add-port pour tout ce qui n’a pas de définition.

Le point à surveiller : le service ssh signifie 22/tcp, et rien d’autre. Si vous avez déplacé SSH vers un autre port en renforçant l’accès SSH au serveur, alors --add-service=ssh n’ouvre pas le port que vous utilisez réellement.

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload

Sur une réinstallation de RHEL, un second verrou intervient. SELinux (security-enhanced Linux) associe des labels aux numéros de port, et sshd n’est pas autorisé à s’attacher à un port qui ne correspond pas à ses labels. Il refuse alors de démarrer, et le journal indique error: Bind to port 2222 on 0.0.0.0 failed: Permission denied. Attribuez d’abord le label au port.

sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222

Comment voir ce qui est ouvert actuellement ?

sudo firewall-cmd --list-all
sudo firewall-cmd --list-rich-rules
sudo nft list table inet firewalld | head -n 40

Les deux premières commandes indiquent ce que firewalld considère comme ouvert. La troisième lit les règles réellement présentes dans le noyau, dans la table gérée par firewalld. Les résultats doivent correspondre.

Cela ne constitue pas une preuve. Effectuez le test depuis une autre machine :

nc -zv 203.0.113.20 443

N’exécutez pas le test sur le serveur lui-même. firewalld accepte tout ce qui arrive sur l’interface loopback, donc curl http://localhost:8080 réussit quelles que soient vos règles. Ce test indique que le service est actif. Il ne vous apprend rien sur le firewall.

Autoriser un port web

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services

La dernière commande doit maintenant afficher http https en plus des éléments déjà présents. Si le site ne répond toujours pas, le pare-feu n’est peut-être pas en cause. Une règle autorise un paquet. Un processus doit malgré tout être à l’écoute pour le recevoir.

sudo ss -tlnp

Un socket affiché comme 0.0.0.0:443 ou *:443 accepte les connexions depuis n’importe quelle adresse. Un socket affiché comme 127.0.0.1:443 répond uniquement sur la loopback. Aucune règle de pare-feu ne le rendra accessible depuis l’extérieur. Ports et sockets à l’écoute sous Linux explique cette différence plus en détail.

Comment fermer un port ?

sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload

La règle --permanent s’applique également ici, et les conséquences sont plus sévères dans ce sens. Supprimez un service uniquement de l’exécution courante : le port semble fermé, puis le prochain rechargement ou redémarrage le rouvre à partir du fichier enregistré. C’est une faille que vous ne remarquerez pas, car le contrôle que vous avez lancé a réussi.

La suppression d’un élément qui n’existait pas affiche Warning: NOT_ENABLED: http et se termine tout de même avec le code 0. L’ajout du même élément deux fois affiche Warning: ALREADY_ENABLED: http. Ces deux cas sont sans danger. Un nom mal orthographié est différent : Error: INVALID_SERVICE signifie que firewalld ne possède aucune définition portant ce nom et qu’aucune modification n’a été effectuée.

Si --list-all affiche cockpit et que vous n’utilisez pas la console web Cockpit sur le port 9090, supprimez-le. Chaque port ouvert correspond à un service que vous devez maintenir à jour. Pour ceux que vous décidez de conserver, dnf-automatic peut installer les mises à jour de sécurité selon une planification afin que cette tâche ne dépende pas de votre mémoire. Installer un correctif ne revient toutefois pas à redémarrer le service, et needs-restarting indique quels services utilisent encore les anciennes bibliothèques une fois ces mises à jour installées.

Restreindre un port à une seule adresse source

Les rich rules sont la forme longue, à utiliser lorsqu’un simple nom de service ne permet pas d’exprimer ce que vous voulez. Restreindre SSH à une seule adresse du bureau nécessite deux commandes. La seconde est souvent oubliée.

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" service name="ssh" accept'
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload

Une zone est un ensemble d’autorisations, et non une liste numérotée qui s’arrête à la première correspondance. La rich rule ajoute une autorisation pour une adresse donnée. Elle ne refuse l’accès à personne. Tant que ssh se trouve encore dans la ligne services:, tout Internet peut toujours atteindre le port 22 et la rich rule ne change rien de mesurable. Supprimez l’entrée générale. Sinon, la règle restrictive ne sert qu’à décorer la configuration.

Pour un port qui ne possède pas de nom de service, indiquez directement le port.

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port port="5432" protocol="tcp" accept'

Pour bloquer un réseau bruyant tout en conservant une trace, placez l’élément de journalisation avant l’action. C’est l’ordre attendu par le langage des rich rules.

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" log prefix="fw-drop " level="info" limit value="3/m" drop'
sudo firewall-cmd --reload
sudo journalctl -k -g fw-drop

La valeur limit empêche un flot de paquets de remplir le journal. Avant de limiter SSH à une seule adresse, vérifiez que cette adresse est stable. Une connexion domestique dont l’adresse IP change vous empêchera de vous connecter le jour où elle changera. Testez donc au préalable l’accès à la console de votre fournisseur et vérifiez qu’il fonctionne.

commandes ufw et leurs équivalents avec firewall-cmd

Même tâche, outil différent. Chaque ligne --permanent nécessite une ligne sudo firewall-cmd --reload après elle, ce qu’une liste de ce type ne peut pas montrer.

  • sudo ufw enable devient sudo systemctl enable --now firewalld
  • sudo ufw disable devient sudo systemctl disable --now firewalld
  • sudo ufw status verbose devient sudo firewall-cmd --list-all
  • sudo ufw allow OpenSSH devient sudo firewall-cmd --permanent --add-service=ssh
  • sudo ufw allow 443/tcp devient sudo firewall-cmd --permanent --add-port=443/tcp
  • sudo ufw delete allow 443/tcp devient sudo firewall-cmd --permanent --remove-port=443/tcp
  • sudo ufw allow from 203.0.113.10 to any port 22 devient la rich rule indiquée ci-dessus
  • sudo ufw reload devient sudo firewall-cmd --reload
  • sudo ufw default deny incoming correspond déjà au fonctionnement de la zone public, et --set-target=DROP en est la version silencieuse
  • sudo ufw logging on devient sudo firewall-cmd --set-log-denied=all

Une différence doit être clairement indiquée. ufw conserve une liste numérotée, et vous pouvez insérer une règle à la position 1. firewalld n’utilise pas de numéros de règle. Ici, « placer cette règle en premier » ne signifie donc rien. Lorsque deux entrées firewalld semblent se contredire, l’acceptation générale l’emporte, car aucun élément de l’ensemble ne refuse le trafic. Vous devez supprimer vous-même l’entrée générale.

Pourquoi mon conteneur Docker est-il accessible alors que le pare-feu semble fermé ?

Parce qu’un port publié par un conteneur ne passe jamais par la partie du pare-feu contrôlée par votre zone. docker run -d -p 8080:80 nginx demande à Docker d’ajouter ses propres règles de NAT (network address translation) et de forwarding. Un paquet arrivant sur le port 8080 est réécrit, puis routé vers le conteneur. Il est donc transféré au lieu d’être remis à l’hôte. Les lignes services: et ports: de votre zone contrôlent les paquets remis à l’hôte. Les règles de Docker contrôlent le chemin de forwarding et les acceptent.

Vous obtenez ainsi un serveur sur lequel sudo firewall-cmd --list-all n’affiche aucun port 8080, alors que nc -zv 203.0.113.20 8080, exécuté depuis une autre machine, établit quand même la connexion. Examinez les règles installées par Docker :

sudo iptables -t nat -L DOCKER -n

La correction se trouve dans le flag de publication. Liez le port à loopback et placez un reverse proxy devant le conteneur.

docker run -d -p 127.0.0.1:8080:80 nginx

Le conteneur répond maintenant à curl http://127.0.0.1:8080 sur le serveur, mais à aucune connexion externe. Les utilisateurs d’Ubuntu rencontrent le même problème, décrit dans pourquoi les conteneurs Docker publient directement leurs ports au-delà d’ufw. Podman rootful, que Rocky et AlmaLinux fournissent dans leurs dépôts de base, publie les ports avec la même approche NAT. Effectuez donc le test depuis une autre machine au lieu de vous fier à la liste de la zone. Ce chevauchement explique également pourquoi installer Docker Engine sur ces distributions nécessite quelques étapes absentes d’un guide Ubuntu, à commencer par le fait que Podman possède déjà la commande docker.

Faire survivre la configuration à un redémarrage et comprendre les erreurs courantes

sudo systemctl is-enabled firewalld
sudo systemctl status firewalld

enabled et active (running) sont les commandes attendues. Un firewall actif mais non activé vous protège jusqu’au premier redémarrage. Cette vérification doit figurer dans la liste des contrôles à effectuer pendant les dix premières minutes sur un nouveau VPS, avec les clés SSH et les mises à jour.

Les commandes nftables brutes et firewalld ne sont pas compatibles. firewalld gère une table appelée inet firewalld. sudo nft flush ruleset la supprime, puis le serveur devient ouvert à tout le trafic. Pourtant, firewall-cmd --list-all continue d’afficher la configuration attendue, car firewalld indique ce qu’il croit être chargé et non ce que contient réellement le kernel. sudo firewall-cmd --reload réinstalle les règles. Écrivez les règles avec firewall-cmd afin qu’elles soient restaurées après un reload.

Deux gestionnaires de firewall sur un même serveur. Installer ufw ou iptables-services en plus de firewalld fait intervenir deux programmes qui écrivent des règles sans se coordonner. Le résultat dépend alors du service démarré en dernier. Choisissez-en un seul. Sur Rocky et AlmaLinux, firewalld est celui pris en charge par la distribution.

Le firewall du fournisseur devant le serveur. De nombreux panneaux VPS disposent d’un firewall réseau distinct. Si --list-all indique qu’un port est ouvert mais qu’une connexion externe échoue toujours, vérifiez le panneau avant de modifier le serveur. L’inverse est également possible : une règle ouverte dans le panneau ne sert à rien si firewalld rejette le paquet.

Exécuter firewall-cmd sans sudo. Chaque modification nécessite root. Sans cette autorisation, la requête est refusée et rien n’est modifié. À première vue, on peut croire que la commande a été ignorée.

Six commandes couvrent la plupart des opérations courantes : --list-all pour consulter l’état, --permanent --add-service ou --add-port pour ouvrir un accès, --permanent --remove-service pour le fermer, --reload pour appliquer le fichier enregistré et --runtime-to-permanent après une série de tests. La zone est public, le flag est --permanent et la seule vérification fiable vient d’une autre machine.

FAQ

Pourquoi ma règle firewalld a-t-elle disparu après un redémarrage ?

La règle a été ajoutée uniquement à la configuration d’exécution. sudo firewall-cmd --add-service=http s’applique immédiatement et est supprimée au prochain rechargement ou démarrage, car la configuration enregistrée dans /etc/firewalld/zones/public.xml n’a jamais été modifiée. Ajoutez --permanent, puis exécutez sudo firewall-cmd --reload. Pour conserver les règles que vous avez déjà ajoutées manuellement, exécutez sudo firewall-cmd --runtime-to-permanent. Cette commande copie l’ensemble actif dans le fichier enregistré.

Pourquoi rien ne change-t-il après l’ajout d’une règle avec --permanent ?

Parce que --permanent écrit le fichier sans modifier le pare-feu en cours d’exécution. Le port reste fermé tant que sudo firewall-cmd --reload n’a pas chargé la configuration enregistrée dans le noyau. Comparez sudo firewall-cmd --list-services et sudo firewall-cmd --permanent --list-services : si la liste enregistrée contient une entrée absente de la liste active, il vous manque le rechargement.

Dois-je utiliser --add-service ou --add-port ?

Utilisez --add-service lorsqu’un nom existe pour le service que vous exécutez. Cela indique l’intention, et sudo firewall-cmd --info-service=https montre précisément quels ports ce nom couvre. Utilisez --add-port lorsqu’aucun nom ne définit votre service ou lorsqu’il écoute sur un port non standard. Le service ssh correspond uniquement à 22/tcp. Si SSH utilise le port 2222, vous devez donc utiliser --add-port=2222/tcp et ajouter un label SELinux pour ce port.

Pourquoi mon conteneur Docker est-il accessible alors que firewall-cmd indique que le port est fermé ?

Un port publié est réécrit par les propres règles NAT de Docker, puis redirigé vers le conteneur. Le paquet n’est donc jamais remis à l’hôte. Les listes de services et de ports d’une zone ne couvrent que les paquets remis à l’hôte. Le conteneur répond depuis Internet alors que --list-all n’affiche rien. Publiez plutôt le port sur l’interface loopback avec docker run -d -p 127.0.0.1:8080:80 nginx, puis placez un reverse proxy devant le conteneur.

Puis-je installer ufw sur Rocky Linux à la place de firewalld ?

Deux gestionnaires de pare-feu installés sur le même serveur écrivent des règles sans connaître les règles de l’autre. L’ensemble qui subsiste dépend du service démarré en dernier. firewalld est l’outil pris en charge sur Rocky Linux et AlmaLinux. Il est déjà installé et utilise le même backend nftables que celui qu’utiliserait ufw. Apprenez la zone par défaut et le flag --permanent une fois, et vous disposerez de l’essentiel de l’outil.