Aller au contenu

Pare-feu avec FirewallD sur un serveur Debian 13

Firewall

FirewallD est un système de pare-feu principalement utilisé sur les systèmes Fedora et Red Hat Enterprise Linux et toutes les distributions dérivées de cette dernière comme Rocky Linux, AlmaLinux et Oracle Linux. On le trouve également sur d'autres distributions comme OpenSUSE et Debian.

FirewallD est un frontal à nftables relativement simple à manipuler. Il est bien documenté dans la littérature imprimée et un peu partout sur le web. Je ne vais donc pas réinventer la roue et vous concocter un cours magistral sur FirewallD. Au lieu de cela, je vais reprendre les trois cas pratiques présentés dans mon précédent article sur la configuration du réseau et procéder à la configuration de base du pare-feu pour chacun d'entre eux.

Différents chemins mènent à Saint-Bauzille-de-Putois

La distribution Debian vous laisse le choix pour configurer un pare-feu. La solution la plus populaire consiste à utiliser ufw (Uncomplicated Firewall). Les gourous de l'administration système éditent directement leur propre litanie de règles nftables. Pour ma part, j'ai choisi FirewallD pour la simple raison que j'ai longtemps travaillé avec les systèmes de la famille Red Hat et que je suis passablement familiarisé avec cette solution.

Installation

FirewallD est fourni par les dépôts de paquets officiels de Debian :

$ sudo apt update
$ sudo apt install -y --no-install-recommends firewalld

La mise en service se fait automatiquement sur un système Debian :

$ systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
     Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; 
             preset: enabled)
     Active: active (running) since Fri 2026-01-30 08:43:36 CET; 44s ago
 Invocation: 47a0c3b66bf24fab8f986eacad28cb0d
       Docs: man:firewalld(1)
    Process: 17734 ExecStartPost=/usr/bin/firewall-cmd --state (code=exited, 
             status=0/SUCC>
   Main PID: 17708 (firewalld)
      Tasks: 2 (limit: 4634)
     Memory: 34.7M (peak: 57.9M)
        CPU: 2.435s
     CGroup: /system.slice/firewalld.service
             └─17708 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid

Configuration de base

Dans cet article, nous allons nous concentrer uniquement sur la configuration de base de FirewallD. Qu'est-ce que j'entends par là ?

  • Associer les interfaces réseau aux zones appropriées. Une zone est une collection de règles de pare-feu associées à un certain contexte. FirewallD fournit toute une série de zones prédéfinies.

  • Supprimer quelques services prédéfinis comme dhcpv6-client, mdns ou samba-client.

  • Autoriser le seul service ssh comme point de départ.

Ouvrir et/ou rediriger les ports

L'ouverture et/ou la redirection des ports sera traitée au fur et à mesure dans les articles sur les services correspondants.

Dans les trois exemples pratiques ci-dessous, je vais aller du plus simple au plus complexe.

FirewallD sur un serveur dédié

La configuration de base de FirewallD sur un serveur dédié avec une ouverture frontale sur Internet est relativement simple. C'est pour cette raison que je vous la présente en premier.

Dans la configuration par défaut, c'est la zone public qui est active sans pour autant être associée à une quelconque interface réseau :

$ sudo firewall-cmd --list-all
public (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces:
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Voici la configuration réseau de ma machine :

$ ip -o -br addr
lo               UNKNOWN        127.0.0.1/8
enp1s0           UP             195.154.114.174/24

J'associe l'interface enp1s0 à la zone public :

$ sudo firewall-cmd --permanent --zone=public --change-interface=enp1s0
success

Je prends en compte les modifications :

$ sudo firewall-cmd --reload
success

Et voilà le résultat :

$ sudo firewall-cmd --list-all
public (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp1s0
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Je supprime le service dhcpv6-client :

$ sudo firewall-cmd --permanent --remove-service=dhcpv6-client
success
$ sudo firewall-cmd --reload
success

À présent il ne me reste plus que le seul service ssh :

$ sudo firewall-cmd --list-all
public (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp1s0
  sources:
  services: ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Je vérifie depuis une machine externe :

$ sudo nmap sd-150204.dedibox.fr
Starting Nmap 7.95 ( https://nmap.org ) at 2026-01-30 09:08 CET
Nmap scan report for sd-150204.dedibox.fr (195.154.114.174)
Host is up (0.016s latency).
rDNS record for 195.154.114.174: 195-154-114-174.rev.poneytelecom.eu
Not shown: 980 filtered tcp ports, 19 filtered tcp ports 
PORT   STATE SERVICE
22/tcp open  ssh

Nmap done: 1 IP address (1 host up) scanned in 14.61 seconds

FirewallD sur un serveur local

La distinction entre un serveur dédié avec une adresse IP publique et une machine locale derrière un routeur est purement pragmatique. En théorie, nous pourrions très bien appliquer la même configuration que dans l'exemple ci-dessus. En pratique, j'aime bien faire la distinction et utiliser la zone internal pour ce genre de configuration.

La pertinence de cette distinction apparaîtra plus clairement dans le dernier exemple de cet article.

FirewallD est installé, et le service correspondant est lancé. Je jette un œil sur la configuration par défaut de la zone internal :

$ sudo firewall-cmd --list-all --zone=internal
internal
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces:
  sources:
  services: dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Voici la configuration réseau de la machine :

$ ip -o -br addr
lo               UNKNOWN        127.0.0.1/8
enp3s0           UP             192.168.2.3/24

Je définis la zone internal par défaut en lui associant l'interface réseau enp3s0 :

$ sudo firewall-cmd --set-default-zone=internal
success
$ sudo firewall-cmd --permanent --zone=internal --change-interface=enp3s0
success
$ sudo firewall-cmd --reload
success

Je vérifie le résultat de l'opération :

$ sudo firewall-cmd --list-all
internal (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp3s0
  sources:
  services: dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Je supprime une poignée de services prédéfinis pour cette zone :

$ sudo firewall-cmd --permanent --remove-service=dhcpv6-client
success
$ sudo firewall-cmd --permanent --remove-service=mdns
success
$ sudo firewall-cmd --permanent --remove-service=samba-client
success
$ sudo firewall-cmd --reload
success

Là encore, je n'ai gardé que le seul service ssh :

$ sudo firewall-cmd --list-all
internal (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp3s0
  sources:
  services: ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Je vérifie depuis une autre machine du réseau :

$ sudo nmap sandbox.microlinux.lan
Starting Nmap 7.95 ( https://nmap.org ) at 2026-01-30 10:04 CET
Nmap scan report for sandbox.microlinux.lan (192.168.2.3)
Host is up (0.00036s latency).
Not shown: 989 filtered tcp ports, 10 filtered tcp ports
PORT   STATE SERVICE
22/tcp open  ssh
MAC Address: B0:83:FE:90:4D:64 (Dell)

Nmap done: 1 IP address (1 host up) scanned in 5.24 seconds

FirewallD sur un routeur

Sur mon routeur local, les choses se compliquent un tout petit peu. Là aussi, FirewallD est installé, et le service correspondant est activé. Voici la configuration réseau de la machine :

$ ip -o -br addr
lo               UNKNOWN        127.0.0.1/8
enp1s0           UP             192.168.2.251/24
enp2s0           UP             192.168.3.1/24

J'affiche la configuration par défaut de la zone external :

$ sudo firewall-cmd --list-all --zone=external
external
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces:
  sources:
  services: ssh
  ports:
  protocols:
  forward: yes
  masquerade: yes
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Dans un premier temps, j'associe l'interface enp1s0 à la zone external :

$ sudo firewall-cmd --permanent --zone=external --change-interface=enp1s0
success
$ sudo firewall-cmd --reload
success

Je vérifie :

$ sudo firewall-cmd --list-all --zone=external
external (active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp1s0
  sources:
  services: ssh
  ports:
  protocols:
  forward: yes
  masquerade: yes
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

L'interface enp2s0 sera associée à la zone internal. Cette zone sera définie comme la zone par défaut :

$ sudo firewall-cmd --permanent --zone=internal --change-interface=enp2s0
success
$ sudo firewall-cmd --set-default-zone=internal
success
$ sudo firewall-cmd --reload
success

Voilà ce que ça donne :

$ sudo firewall-cmd --list-all
internal (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp2s0
  sources:
  services: dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Au passage, je désactive les services que je n'utilise pas :

$ sudo firewall-cmd --permanent --remove-service=dhcpv6-client
success
$ sudo firewall-cmd --permanent --remove-service=mdns
success
$ sudo firewall-cmd --permanent --remove-service=samba-client
success
$ sudo firewall-cmd --reload
success

Je vérifie :

$ sudo firewall-cmd --list-all
internal (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp2s0
  sources:
  services: ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Configurer le relais des paquets

Maintenant que j'ai mis en place la configuration de mes deux zones, il me faut activer le relais des paquets (IP Masquerading). Concrètement, cela veut dire que les paquets IP du réseau 192.168.3.0/24 doivent pouvoir transiter vers le réseau 192.168.2.0/24.

Le relais des paquets n'est pas activé par défaut sur un système Debian. Je vais donc éditer un fichier /etc/sysctl.d/ip-forwarding.conf à cet effet :

/etc/sysctl.d/ip-forwarding.conf
net.ipv4.ip_forward = 1

J'active ce nouveau paramètre :

$ sudo sysctl --system

Dans la configuration par défaut, la zone external permet déjà le relais des paquets :

$ sudo firewall-cmd --list-all --zone=external
external (active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: enp1s0
  sources:
  services: ssh
  ports:
  protocols:
  forward: yes
  masquerade: yes
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Il nous reste à définir une politique pour autoriser le trafic entre les zones internal et external. Voici à quoi ça ressemble :

$ sudo firewall-cmd --permanent --new-policy=router
success
$ sudo firewall-cmd --permanent --policy=router --add-ingress-zone=internal
success
$ sudo firewall-cmd --permanent --policy=router --add-egress-zone=external
success
$ sudo firewall-cmd --permanent --policy=router --set-target=ACCEPT
success
$ sudo firewall-cmd --reload
success

Autoriser le trafic entre les zones

FirewallD requiert ce genre d'autorisation explicite du trafic entre les zones depuis la version 1.0. Dans les versions antérieures, ce trafic était autorisé par défaut. Étant donné qu'avant de migrer mes machines vers Debian, j'utilisais FirewallD 0.9 sur des systèmes Red Hat, j'ai passé une bonne journée à m'arracher les cheveux en me demandant ce qui pouvait bien bloquer mes paquets entre les deux réseaux. J'ai fini par trouver la réponse dans la documentation de Arch Linux. Ce genre de surprise fait partie de notre métier.

J'affiche les détails de cette nouvelle politique :

$ sudo firewall-cmd --info-policy=router
router (active)
  priority: -1
  target: ACCEPT
  ingress-zones: internal
  egress-zones: external
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Pour tester le relais des paquets, je me connecte à un client dans le réseau 192.168.3.0/24 :

$ ip -o -br addr
lo               UNKNOWN        127.0.0.1/8
enp3s0           UP             192.168.3.10/24

Tester le relais des paquets

Pour l'instant je n'ai pas encore installé Dnsmasq sur le routeur. Pour tester le relais des paquets, je me sers provisoirement d'un poste client avec une configuration réseau statique.

Pour finir, j'essaie d'envoyer successivement un ping sur les deux réseaux :

$ ping -c 1 -q 192.168.3.1
PING 192.168.3.1 (192.168.3.1) 56(84) bytes of data.

--- 192.168.3.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.352/0.352/0.352/0.000 ms
$ ping -c 1 -q 192.168.2.1
PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.

--- 192.168.2.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.986/0.986/0.986/0.000 ms

Documentation


La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.