WIKI Retour au Portfolio

Dernière mise à jour : 23 juin 2026

7 - Management des services réseaux

Fiche de révision RHCSA (RHEL 9 / EX200) : SSH, HTTP, SELinux, firewalld, NTP/chrony, NFS client & autofs, conteneurs Podman.

⚠️ Cadrage examen : sur l'EX200, on configure un client (NFS, SSH), on gère le firewall (firewalld), SELinux, NTP (chrony) et la mise en réseau de base. Monter un serveur NFS/HTTP n'est pas un objectif officiel, mais les notes les couvrent pour la compréhension. Le réseau se configure avec NetworkManager / nmcli (les ifconfig et network-scripts sont dépréciés sur RHEL 9).


A. Mise en réseau avec NetworkManager (nmcli)

⚠️ Non couvert par les notes brutes mais objectif central EX200 (« manage basic networking »). Ajout synthétique.

Sur RHEL 9, le réseau est géré par le service NetworkManager. On manipule des connexions (profils) qui s'appliquent à des devices (interfaces).

nmcli device status              # état des interfaces (device)
nmcli connection show            # lister les profils de connexion
nmcli con show "System ens160"   # détail d'un profil

# IP statique
nmcli con add type ethernet con-name static-ens160 ifname ens160 \
  ipv4.addresses 192.168.10.50/24 ipv4.gateway 192.168.10.1 \
  ipv4.dns 8.8.8.8 ipv4.method manual
nmcli con mod static-ens160 +ipv4.dns 1.1.1.1   # ajouter un DNS secondaire
nmcli con up static-ens160                       # APPLIQUER la connexion

🚨 Piège : après un nmcli con mod, les changements ne sont PAS actifs tant qu'on n'a pas fait nmcli con up <con> (ou nmcli con reload + up).

💡 nmtui est l'interface texte équivalente (utile à l'exam si on hésite sur la syntaxe nmcli).

nmtui            # menu : Edit/Activate connection, Set hostname

Hostname & /etc/hosts

hostnamectl                          # afficher le hostname courant
hostnamectl set-hostname server.example.com
  • Résolution DNS : /etc/resolv.conf (géré par NetworkManager), /etc/hosts pour les résolutions locales statiques.
# /etc/hosts  -> résolution locale (prioritaire)
192.168.0.216  server.example.com  server
192.168.0.215  monpc

💡 La note brute mettait l'exemple server.example dans /etc/resolv.conf — c'est une erreur : ce type d'entrée IP→nom va dans /etc/hosts, pas dans resolv.conf (qui ne contient que nameserver/search).


B. Manager SSH

Connexion par clé SSH

Le client détient la clé privée, le serveur la clé publique. Le client signe un message avec sa clé privée, le serveur vérifie avec la clé publique pour authentifier l'utilisateur.

Schéma SSH : le client (clé privée ~priv) prouve son identité au serveur sshd qui détient la clé publique ~pub

ssh-keygen                       # génère une paire clé pub/privée pour l'user courant (passphrase optionnel)
ssh-copy-id server.example       # copie la clé publique vers la cible
ssh server.example               # après copie, connexion sans mot de passe

Passphrase & ssh-agent

  • Après ssh-copy-id, ssh server ne demande plus le mot de passe du compte.
  • Si la clé a une passphrase, elle est demandée à chaque connexion → peu pratique.
  • ssh-agent met la clé déverrouillée en cache pour la durée de la session :
ssh-agent /bin/bash      # lance un shell avec un agent (cache la clé privée)
ssh-add                  # ajoute la clé au cache (saisie de la passphrase une fois)

Options du client SSH

  • Fichiers : /etc/ssh/ssh_config (global) ou ~/.ssh/config (par utilisateur).
ssh -X server.example        # X forwarding (applis graphiques distantes)
ssh -X server.example gedit  # lance gedit du serveur sur ton écran
ssh -Y server.example        # X forwarding "trusted"

Options du serveur SSH (hardening)

  • Fichier : /etc/ssh/sshd_config (le d = daemon).
Option Rôle
Port 22 port d'écoute
PermitRootLogin no interdire le login root direct (hardening)
PasswordAuthentication no forcer l'auth par clé
PubkeyAuthentication yes autoriser l'auth par clé
X11Forwarding yes autoriser le forwarding X
AllowUsers user1 user2 restreindre qui peut se connecter
systemctl restart sshd       # OBLIGATOIRE pour appliquer les changements

🚨 Piège : ne pas confondre ssh_config (client) et sshd_config (serveur). Et un changement dans sshd_config n'est pris en compte qu'après systemctl restart sshd.

Copie & synchronisation sécurisées

scp file1 file2 student@remoteserver:/home/student   # copie sécurisée via SSH
scp -r root@remoteserver:/tmp/files .                 # copie récursive
sftp student@remoteserver                             # client FTP interactif sur SSH
#   put file   -> upload | get file -> download | exit -> quitter

rsync : ne synchronise que les différences (efficace pour les MAJ).

rsync -a *  root@server:/home/student   # mode archive (préserve perms, liens, dates...)
Option rsync Effet
-r récursif
-l conserve les liens symboliques
-p préserve les permissions
-n dry-run (test sans copier)
-a mode archive (= rlptgoD)
-A archive + ACL
-X synchronise aussi le contexte SELinux

C. Service HTTP (Apache / httpd)

💡 Mettre en place un serveur web n'est pas un objectif EX200, mais sert de support pour SELinux/firewalld.

  • Apache (httpd) est le serveur web le plus répandu sous Linux (alternative : Nginx).
  • Fichiers de configuration :
    • /etc/httpd/conf/httpd.conf — config principale
    • /etc/httpd/conf.d/ — fichiers drop-in
    • /var/www/html/DocumentRoot par défaut (Apache cherche index.html)
dnf install httpd
systemctl enable --now httpd     # port 80 par défaut
curl http://localhost            # vérifier la page servie
# Logs en cas d'erreur
cd /var/log/httpd                # access_log et error_log

D. Sécurisation avec SELinux

La sécurité UNIX classique (DAC) ne couvre qu'une partie de l'OS. SELinux (MAC) apporte une protection plus complète.

Principe : ce qui n'est pas explicitement autorisé est refusé. Un service inconnu nécessitera donc toujours une configuration pour être autorisé sous SELinux.

Modes SELinux

  • SELinux est activé ou désactivé : passer de l'un à l'autre exige un reboot.
  • S'il est activé, deux modes :
    • Permissive : ne bloque rien, journalise seulement (utile pour le test).
    • Enforcing : applique réellement la politique (bloque).
getenforce               # état courant (Enforcing / Permissive / Disabled)
setenforce 0             # passer en Permissive (temporaire)
setenforce 1             # passer en Enforcing
  • État par défaut : /etc/selinux/config (RHEL 9 ; l'ancien /etc/sysconfig/selinux y pointe en symlink).
  • Options de boot dans le menu GRUB :
    • enforcing=0 → permissive (1 → enforcing)
    • selinux=1 → activé (0 → désactivé)

Composantes SELinux : contextes (labels)

SELinux applique des labels de contexte définissant les permissions, posés sur les objets source et target, et reliés par des règles de la policy.

  • Source : users, processus
  • Target : fichiers, répertoires, ports

Schéma SELinux : un contexte source (myapp_t, process) accède à un contexte target (myapp_files_t, file/port) selon les rules de la policy ; tout repose sur les LABELS

Structure d'un label : user:role:type — le type est le champ déterminant (« type enforcement »).

ls -Z /var/www/html              # voir les contextes des fichiers
semanage fcontext -l             # lister les règles de contexte fichier
semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"   # AJOUTER une règle
semanage fcontext -m ...         # MODIFIER une règle existante
restorecon -Rv /var/www/html     # APPLIQUER la policy sur le filesystem
semanage fcontext -l -C          # voir les règles changées vs la policy par défaut

💡 semanage fcontext écrit la règle dans la policy (pas sur l'inode). C'est restorecon qui applique réellement le label aux fichiers. Le fichier /.autorelabel (créé à la racine) déclenche un relabel complet au prochain boot.

Exemple : déplacer un fichier change son contexte

Quand on déplace (mv) un fichier, il conserve son ancien contexte (au lieu d'hériter de celui du dossier) → l'accès peut casser.

Démonstration shell : après mv vers /var/www/html, le fichier hosts garde son contexte admin_home_t au lieu de httpd_sys_content_t, d'où le besoin de restorecon

Trouver le bon contexte

dnf install selinux-policy-doc        # docs de policy détaillées
man -k _selinux | grep httpd          # pages de man par service
man httpd_selinux                     # contextes attendus pour httpd

💡 Si on applique une config non standard, on copie le contexte de l'équivalent par défaut.

Ports SELinux

Les ports réseau ont aussi un label SELinux. SELinux autorise les ports par défaut ; pour un port non standard, il faut le déclarer :

semanage port -l                      # lister les labels de ports
man semanage-port                     # bon label à appliquer
# Exemple : faire écouter sshd sur 2022
semanage port -a -t ssh_port_t -p tcp 2022

💡 Astuce de diagnostic : setenforce 0 puis retest. Si ça marche en permissive mais pas en enforcing → le problème vient bien de SELinux.

Booleans SELinux

Un boolean est un interrupteur activant/désactivant des parties de la policy.

getsebool -a                          # lister tous les booleans (= semanage boolean -l)
getsebool -a | grep ftp               # filtrer (ex. FTP)
setsebool -P ftpd_anon_write on       # -P = PERSISTANT (survit au reboot)
semanage boolean -l -C                # voir les booleans modifiés (≠ défaut)

Sortie shell : getsebool -a | grep ftp liste les booleans FTP (tous off), puis setsebool -P ftpd_anon_write on et semanage boolean -l -C confirme le boolean passé à on

🚨 Piège : setsebool sans -P est perdu au reboot. Toujours -P pour rendre le boolean persistant.

Logs & troubleshooting SELinux

  • SELinux journalise via auditd dans /var/log/audit/audit.log (entrées AVC).
  • sealert interprète ces messages et écrit dans /var/log/messages, avec des pistes de résolution.
grep AVC /var/log/audit/audit.log     # voir les refus (source/target context)
journalctl | grep sealert             # alertes sealert + solutions proposées
sealert -l <UUID>                      # détail d'une alerte donnée

Démarche de troubleshoot :

  1. setenforce 0 → le problème disparaît ? → c'est SELinux.
  2. grep AVC /var/log/audit/audit.log → identifier source/target context, puis corriger (semanage fcontext + restorecon, ou un boolean).
  3. journalctl | grep sealert → lire les alertes et solutions.

Récupération si un autorelabel bloque le boot (édition GRUB) :

systemd.unit=emergency.target        # ajouter à la ligne kernel dans GRUB
mount -o remount,rw /
rm -f /.autorelabel
restorecon -Rv /                     # relabel manuel (remplace l'autorelabel supprimé)

E. Sécurité réseau : firewalld

Surveiller les sockets (ss)

Un socket réseau = un endpoint (IP + port).

ss            # toutes les infos socket (verbeux)
ss -tu        # sockets TCP & UDP
ss -tua       # + sockets en écoute (listening)
ss -tln       # TCP en écoute uniquement, sans résolution de nom
ss -tulpn     # TCP+UDP en écoute, avec process/PID

Le firewall

  • Le kernel fournit netfilter (packet filtering, NAT, port forwarding).
  • nftables est le framework qui applique le firewalling.
  • firewalld est le service (frontend) qui pilote nftables.

⚠️ Déprécié : iptables est remplacé par nftables / firewalld sur RHEL 9. Utiliser firewall-cmd.

Composantes : zones, services, ports, rich rules.

firewall-cmd --list-all          # config de la zone par défaut
firewall-cmd --get-services      # services prédéfinis
firewall-cmd --get-zones         # zones disponibles

Configurer avec firewall-cmd

Flag Effet
(aucun) s'applique au runtime uniquement (perdu au reload/reboot)
--permanent écrit dans la config (persistant), mais pas actif au runtime
--reload recharge la config permanente dans le runtime
systemctl status firewalld
firewall-cmd --add-service=http                # autorise HTTP (runtime seulement)
firewall-cmd --add-service=http --permanent    # persiste (mais pas encore actif)
firewall-cmd --reload                          # active la config permanente
firewall-cmd --list-all                        # vérifier

🚨 Piège majeur d'exam : ouvrir un port/service avec firewall-cmd sans --permanent → perdu au reboot. Et avec --permanent sans --reload → pas actif tout de suite. Méthode sûre : ajouter en --permanent puis --reload.

# Méthode robuste type exam
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
firewall-cmd --list-all

💡 Zones firewalld (rappel utile) :

Zone Usage typique
public zone par défaut, réseaux non fiables
trusted tout le trafic accepté
internal / home / work réseaux internes, partiellement fiables
dmz serveurs exposés, accès entrant limité
block / drop rejette / ignore tout le trafic entrant

💡 Rich rule (règle fine, ex. autoriser une source précise) :

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" service name="ssh" accept'
firewall-cmd --reload

F. Service de temps (NTP / chrony)

Heure sous Linux

  • Au boot, Linux lit l'horloge matérielle (hardware clock).
  • Le system time en est dérivé, puis (option) synchronisé par NTP via Internet.
hwclock              # afficher/régler l'horloge matérielle
hwclock --systohc    # copie le system time -> hardware clock
hwclock --hctosys    # copie le hardware clock -> system time
date                 # afficher/régler l'heure
timedatectl          # gérer heure ET fuseau horaire

timedatectl

timedatectl status                       # propriétés de l'heure
timedatectl set-time "2026-06-23 10:00:00"
timedatectl list-timezones               # lister les fuseaux
timedatectl set-timezone Europe/Paris    # changer de fuseau
timedatectl set-ntp true                 # activer/désactiver la synchro NTP

💡 systemd-timesyncd.service est un autre service NTP, non utilisé par défaut sur RHEL (qui utilise chrony).

Serveur de temps chrony

  • chronyd est le service NTP par défaut de RHEL 9.
  • Configuration : /etc/chrony.conf.
# /etc/chrony.conf
pool 2.rhel.pool.ntp.org iburst    # pool de serveurs NTP (iburst = synchro rapide)
server myserver iburst             # une source unique
systemctl restart chronyd          # prendre en compte la config
chronyc sources                    # voir les sources et l'état de synchro
chronyc tracking                   # détail de la synchronisation courante

G. Systèmes de fichiers distants : NFS client & autofs

⚠️ Cadrage EX200 : seul le montage côté client (NFS, autofs) est attendu. La config serveur ci-dessous est donnée pour la compréhension.

(Référence) Serveur NFS

dnf install nfs-utils
mkdir -p /nfsdata /home/ldap/ldapuser{1..9}
echo "/nfsdata *(rw,no_root_squash)"   >> /etc/exports
echo "/home/ldap *(rw,no_root_squash)" >> /etc/exports
systemctl enable --now nfs-server
for i in nfs mountd rpc-bind; do firewall-cmd --add-service=$i --permanent; done
firewall-cmd --reload

Côté client (objectif exam)

nfs-utils doit être installé au préalable.

dnf install nfs-utils
showmount -e nfsserver           # voir les exports du serveur
mount nfsserver:/share /mnt      # montage manuel temporaire

💡 Pour un montage persistant, ajouter une ligne dans /etc/fstab :

nfsserver:/share  /mnt  nfs  defaults,_netdev  0 0

Automount (autofs)

autofs monte un partage à la demande (à l'accès) et démonte après inactivité.

dnf install autofs
systemctl enable --now autofs
# /etc/auto.master  -> point de montage parent + map secondaire
/data   /etc/auto.nfsdata

# /etc/auto.nfsdata -> sous-répertoire et source
files   -rw   nfsserver:/nfsdata
#   => /data/files montera nfsserver:/nfsdata à l'accès

💡 /etc/auto.misc fournit des exemples de syntaxe.

Automount des home directories (wildcard)

Scénario entreprise : le serveur NFS fournit les home, montés automatiquement à la connexion de l'utilisateur. On utilise un wildcard (*) et la substitution (&).

# /etc/auto.home  (map indirecte)
*   -rw   nfsserver:/home/ldap/&
#   * = nom de l'utilisateur demandé ; & = même nom côté serveur
#   ex. accès /home/ldap/bob  ->  monte nfsserver:/home/ldap/bob

H. Installation automatique (Kickstart) — aperçu

💡 Hors cœur EX200 mais présent dans les notes ; à connaître pour la culture RHEL.

ksvalidator /root/anaconda-ks.cfg   # valider la syntaxe du fichier kickstart

Le fichier anaconda-ks.cfg (dans /root) est généré après l'install. Options courantes :

url --url="http://myserver/..."                 # média d'installation
repo --name="myrepo" --baseurl=...              # dépôt supplémentaire
text                                            # installation en mode texte
clearpart --all --drive=sda,sdb                 # effacer les partitions
part /home --fstype=ext4 --label=home --size=2048 --maxsize=4096 --grow
autopart                                        # root + swap + boot auto
network --device=ens33 --bootproto=dhcp --hostname=server.example
firewall --enabled --service=ssh,http
timesource --ntp-server pool.ntp.org
rootpw --plaintext secret
selinux --enforcing

Source du fichier au boot du client :

inst.ks=http://somewhere/ks.cfg            # via HTTP
inst.ks=hd:LABEL=MYLABEL:/directory/file   # depuis un device (USB, par LABEL ou UUID)

I. Manager les conteneurs (Podman)

Concepts

  • Un conteneur = un package contenant l'application et toutes ses dépendances.
  • Démarre à partir d'une image fournie par un registry (dépôt d'images).
  • Repose sur des fonctions du kernel Linux : cgroups (limites de ressources), namespaces (isolation des données/config), SELinux (sécurité).

Rootless containers :

  • Un conteneur a besoin d'un UID pour démarrer.
  • Root container : démarré par root. Rootless : démarré par un user non-root.
  • Limites du rootless : pas d'accès complet au filesystem, pas de bind sur des ports privilégiés (< 1024).

Architecture microservices : une app complexe = plusieurs conteneurs ; en principe 1 conteneur = 1 service. Orchestration via Kubernetes ou Red Hat OpenShift.

Outils

Outil Rôle
podman gérer conteneurs et images (équivalent de docker)
buildah outil avancé pour construire des images
skopeo inspecter, copier, supprimer, signer des images

Images & registries

  • Images au format OCI (Open Container Initiative) → compatibilité entre podman/docker.
  • Registries publics (hub.docker.com), privés, ou Red Hat : quay.io, registry.redhat.io, catalog.redhat.com.
podman login registry.redhat.io
podman login registry.redhat.io --get-login   # vérifier le compte connecté

Configuration des registries : /etc/containers/registries.conf

  • registres par défaut : section [registries.search]
  • registres sans SSL : [registries.insecure]
  • par utilisateur : ~/.config/containers/registries.conf

Containerfile (ex-Dockerfile)

Fichier texte d'instructions pour construire une image à partir d'une image de base (souvent UBI = Universal Base Image de Red Hat).

dnf install container-tools
git clone https://github.com/sandervanvugt/rhcsa
cd rhcsa                                    # contient un Containerfile d'exemple
podman info                                 # infos registres/images
podman login registry.access.redhat.com
podman build -t mymap .                     # build depuis le Containerfile du dossier courant (-t = tag)
podman images                               # vérifier l'image créée

Commandes Podman essentielles

Commande Rôle
podman search chercher des images dans les registries
podman run lancer un conteneur (pull l'image si absente)
podman stop arrêter un conteneur en cours
podman ps / ps -a conteneurs actifs / + arrêtés
podman build construire une image depuis un Containerfile
podman images lister les images
podman inspect détails d'un conteneur ou d'une image
podman pull tirer une image du registry
podman exec exécuter une commande dans un conteneur actif
podman rm supprimer un conteneur
podman logs voir les logs d'un conteneur

Récapitulatif des sous-commandes Podman essentielles : search, run, stop, ps, build, images, inspect, pull, exec, rm

podman search ubi
podman run --name sleepy docker.io/redhat/ubi9 sleep 3600   # premier plan
podman ps
podman stop sleepy                  # ou l'ID (2 premiers caractères suffisent)
podman run -d --name sleepy2 docker.io/redhat/ubi9 sleep 3600   # -d = arrière-plan
podman rm sleepy                    # supprimer un conteneur arrêté
podman ps -a

Troubleshooting

podman inspect <container>          # quelle commande démarre le conteneur
podman run -it <image> /bin/bash    # terminal interactif
podman logs <ID>                    # logs du conteneur

Conteneur nécessitant des variables d'environnement

Passer -e KEY=VALUE avant le nom de l'image (sinon interprété par l'app du conteneur).

podman run --name mydb quay.io/centos7/mariadb-103-centos7   # échoue (manque le mot de passe)
podman logs mydb                                              # voir l'erreur
skopeo inspect docker://quay.io/centos7/mariadb-103-centos7  # voir les variables attendues
podman rm mydb
podman run --name mydb -e MYSQL_ROOT_PASSWORD=password quay.io/centos7/mariadb-103-centos7

Accès applicatif : port mapping

  • L'accès se fait par port mapping : un port de l'hôte est mappé vers un port du conteneur.
  • Le mapping se définit au démarrage du conteneur (pas après).
  • Rootless → mapping uniquement sur des ports non privilégiés (> 1024).
podman login registry.access.redhat.com
podman run -d -p 80:80 registry.access.redhat.com/ubi9/nginx-120     # échoue en rootless (port < 1024)
podman run -d -p 8080:80 registry.access.redhat.com/ubi9/nginx-120   # OK
podman port -a
sudo firewall-cmd --add-port=8080/tcp --permanent                    # rendre le port joignable
sudo firewall-cmd --reload

Stockage persistant (bind-mount)

On fournit du stockage en bind-montant un répertoire de l'hôte dans le conteneur. Attention à l'ownership :

  • Conteneur root : UID/GID hôte et conteneur correspondent → pas de souci.
  • Conteneur rootless : l'UID de l'app dans le conteneur (vu via les namespaces) doit posséder le répertoire bind-monté.
podman inspect <image>                       # quel user lance l'app
podman exec <container> grep mysql /etc/passwd   # trouver l'UID applicatif

Namespaces & mapping UID : un conteneur rootless tourne dans un user namespace ; l'UID « root » interne mappe vers un UID ordinaire sur l'hôte.

podman unshare cat /proc/self/uid_map        # voir le mapping UID
podman unshare chown 27:27 ~/mydb            # poser l'ownership dans le namespace (répertoire dans le home)
ls -ld ~/mydb                                # vérifier côté hôte

SELinux pour le bind-mount : il faut le contexte container_file_t sur le répertoire. L'option :Z le pose automatiquement :

podman run -d --name mydb -e MYSQL_ROOT_PASSWORD=password \
  -v /home/student/mydb:/var/lib/mysql:Z \
  quay.io/centos7/mariadb-103-centos7
ls -Z /home/student                          # vérifier le contexte appliqué

Conteneur en service systemd (rootless)

Un conteneur est un service comme un autre pour systemd. On crée une user unit systemd pour gérer un conteneur rootless avec systemctl --user.

Linger : un service user normal s'arrête à la fermeture de session. loginctl enable-linger le maintient actif même session fermée.

loginctl enable-linger linda     # garder les services user de linda actifs (en root)
loginctl show-user linda
loginctl disable-linger linda

Principe de la procédure : se connecter en tant que l'utilisateur (jamais su -, définir un mot de passe), créer ~/.config/systemd/user, générer l'unit avec podman generate --new, puis vérifier WantedBy=default.target et non multi-user.target

Procédure systemd rootless pas à pas : useradd/passwd linda, enable-linger, ssh linda@localhost, mkdir ~/.config/systemd/user, podman run -p 8081:80 nginx, podman generate systemd --new, édition de container-mynginx.service (WantedBy=default.target), puis systemctl --user daemon-reload/enable/status

🚨 À retenir pour l'exam :

  • Se connecter en tant que l'utilisateur (définir un mot de passe), ne pas utiliser su -.
  • Pour un conteneur root, générer l'unit dans /etc/systemd/system à la place.
  • Vérifier que l'unit a bien WantedBy=default.target (et non multi-user.target) pour démarrer en session user.
ps fax                            # voir le process conteneur après reboot (chercher son user)
man podman-generate-systemd

⚠️ Évolution RHEL 9 : podman generate systemd est marqué déprécié au profit des fichiers Quadlet (~/.config/containers/systemd/*.container). À la date des notes, podman generate systemd reste fonctionnel et c'est la méthode présentée ; connaître l'existence de Quadlet pour les versions récentes.