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
ifconfigetnetwork-scriptssont 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/hostspour 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.exampledans/etc/resolv.conf— c'est une erreur : ce type d'entrée IP→nom va dans/etc/hosts, pas dansresolv.conf(qui ne contient quenameserver/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.

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 serverne 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(led= 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 chercheindex.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/selinuxy 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

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'estrestoreconqui 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.

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 0puis 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)

🚨 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). sealertinterprè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 :
setenforce 0→ le problème disparaît ? → c'est SELinux.grep AVC /var/log/audit/audit.log→ identifier source/target context, puis corriger (semanage fcontext+restorecon, ou un boolean).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é :
iptablesest remplacé par nftables / firewalld sur RHEL 9. Utiliserfirewall-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 |

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


🚨 À 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 nonmulti-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 systemdest marqué déprécié au profit des fichiers Quadlet (~/.config/containers/systemd/*.container). À la date des notes,podman generate systemdreste fonctionnel et c'est la méthode présentée ; connaître l'existence de Quadlet pour les versions récentes.