Chapitre 820 minIntermédiaire
HTTP et HTTPS : requêtes, codes d'état et certificats
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- lire une requête et une réponse HTTP et interpréter un code d'état ;
- expliquer ce que TLS apporte et lire les champs d'un certificat ;
- choisir entre un certificat public et un certificat interne ;
- publier un site en HTTPS avec Nginx et le tester avec openssl.
4 exercices corrigés
HTTP (HyperText Transfer Protocol) est le protocole du web : un client (le navigateur, curl, une application) envoie une requête à un serveur, qui renvoie une réponse avec un code d'état. HTTPS, c'est HTTP transporté dans une connexion TLS chiffrée et authentifiée par un certificat : le port passe de 80 à 443. Ce chapitre décortique une requête et une réponse, les méthodes, les codes et les versions du protocole, puis les certificats (publics ou internes) et la publication d'un intranet en HTTPS avec Nginx sous Debian 13.
Une requête, une réponse
Chloé Lambert teste l'intranet de Sorbier, servi par srv-intranet (192.168.21.10), avec curl en mode bavard. Les lignes qui commencent par > sont envoyées, celles qui commencent par < sont reçues.
$ curl -v https://intranet.sorbier.example/annuaire
* Connected to intranet.sorbier.example (192.168.21.10) port 443
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=intranet.sorbier.example
* issuer: CN=Sorbier-AC
> GET /annuaire HTTP/2
> Host: intranet.sorbier.example
> User-Agent: curl/8.14.1
> Accept: */*
>
< HTTP/2 200
< server: nginx
< content-type: text/html; charset=utf-8
< strict-transport-security: max-age=31536000
<
<!DOCTYPE html> ...
Une requête contient : une méthode (GET), un chemin (/annuaire), la version, puis des en-têtes (Host, User-Agent…), une ligne vide et, pour certaines méthodes, un corps (les données d'un formulaire, du JSON). Une réponse contient : la version, un code d'état (200), des en-têtes et le corps (la page).
HTTP est sans état : chaque requête est indépendante, le serveur ne se souvient de rien entre deux requêtes. C'est le cookie, envoyé par le serveur (Set-Cookie) puis renvoyé par le navigateur à chaque requête (Cookie), qui permet de rester connecté d'une page à l'autre (cours Authentification).
Les méthodes
| Méthode | Usage | Modifie quelque chose sur le serveur ? |
|---|---|---|
GET | Lire une ressource (une page, une image, des données) | Non |
HEAD | Comme GET, mais sans le corps : seulement les en-têtes | Non |
POST | Envoyer des données : formulaire, création d'une ressource | Oui |
PUT | Remplacer une ressource | Oui |
PATCH | Modifier une partie d'une ressource | Oui |
DELETE | Supprimer une ressource | Oui |
OPTIONS | Demander quelles méthodes le serveur accepte | Non |
Les API REST utilisent toutes ces méthodes (cours API REST) ; un site web classique se contente surtout de GET et POST.
Les codes d'état
Le premier chiffre donne la famille. En dépannage, il dit tout de suite qui est en cause : un code 4xx désigne une erreur côté client (la requête), un code 5xx une erreur côté serveur.
| Code | Sens | Exemple de situation |
|---|---|---|
| 200 OK | Succès | La page s'affiche |
| 201 Created | Ressource créée | Une API a enregistré un nouveau ticket |
| 204 No Content | Succès, sans corps | Une suppression réussie dans une API |
| 301 Moved Permanently | Redirection définitive | http:// redirigé vers https:// |
| 302 Found / 307 Temporary Redirect | Redirection temporaire | Renvoi vers la page de connexion |
| 304 Not Modified | La copie en cache est encore bonne | Le navigateur réutilise l'image qu'il a déjà |
| 400 Bad Request | Requête mal formée | JSON invalide envoyé à une API |
| 401 Unauthorized | Authentification requise ou refusée | Pas de session, mot de passe faux |
| 403 Forbidden | Authentifié, mais pas autorisé | Un utilisateur sans droit sur la page d'administration, ou des droits de fichiers trop restrictifs sur le serveur |
| 404 Not Found | La ressource n'existe pas | Lien cassé, mauvais chemin |
| 405 Method Not Allowed | Méthode refusée pour cette ressource | Un DELETE sur une page statique |
| 429 Too Many Requests | Trop de requêtes | Limitation de débit d'une API |
| 500 Internal Server Error | Erreur dans l'application | Une exception PHP non gérée |
| 502 Bad Gateway | Le serveur intermédiaire a reçu une réponse invalide du serveur suivant | Le reverse proxy ne joint pas l'application, ou l'application a planté (chapitre 9) |
| 503 Service Unavailable | Service indisponible | Maintenance, surcharge, aucun serveur disponible derrière le répartiteur |
| 504 Gateway Timeout | Le serveur intermédiaire a attendu trop longtemps | L'application met trop de temps à répondre |
Les en-têtes à connaître
| En-tête | Sens | Utilité |
|---|---|---|
Host | Le nom du site demandé | Un même serveur héberge plusieurs sites (hôtes virtuels) et choisit d'après ce nom |
User-Agent | Le logiciel client | Statistiques, journaux, détection de robots |
Content-Type | Le format du corps | text/html, application/json |
Location | L'adresse de redirection | Avec les codes 301, 302, 307, 308 |
Cookie / Set-Cookie | Le cookie de session | Rester connecté |
Cache-Control | Les règles de cache | no-store pour les pages sensibles |
Strict-Transport-Security | HSTS : « ne viens plus qu'en HTTPS » | Empêche le retour au HTTP en clair |
X-Forwarded-For | L'adresse du vrai client, ajoutée par un reverse proxy | Le serveur final connaît le client malgré l'intermédiaire |
HTTP/1.1, HTTP/2, HTTP/3
| Version | Transport | Ce qui change |
|---|---|---|
| HTTP/1.1 (1997, aujourd'hui RFC 9112) | TCP, en texte | Une requête à la fois par connexion ; le navigateur ouvre plusieurs connexions en parallèle |
| HTTP/2 (2015, RFC 9113) | TCP, binaire, en pratique toujours dans TLS | Plusieurs requêtes en parallèle sur une seule connexion, en-têtes compressés |
| HTTP/3 (2022, RFC 9114) | QUIC, sur UDP 443 | Connexion plus rapide à établir, pas de blocage de toutes les requêtes quand un paquet se perd |
HTTPS : ce que TLS apporte
HTTPS ajoute, sous HTTP, une couche TLS (Transport Layer Security) qui apporte trois garanties :
- la confidentialité : les échanges sont chiffrés, personne sur le trajet ne lit les mots de passe ni les pages ;
- l'intégrité : un échange modifié en route est détecté ;
- l'authentification du serveur : le certificat prouve que tu parles bien à
intranet.sorbier.example, et pas à un imposteur.
La version actuelle est TLS 1.3 ; TLS 1.2 reste acceptable, les versions antérieures (TLS 1.0, 1.1, SSL) sont interdites. Le déroulé de la poignée de main TLS 1.3 et les algorithmes employés sont expliqués dans le chapitre TLS 1.3 et HTTPS du cours Cryptographie. Ici, on s'occupe de ce que l'administrateur manipule : le certificat.
Un point technique compte en exploitation : l'extension SNI (Server Name Indication). Le client envoie le nom du site dès le début de la poignée de main, avant tout chiffrement : un serveur qui héberge plusieurs sites sur la même adresse IP choisit ainsi le bon certificat. C'est ce qui permet à un reverse proxy de publier dix sites sur une seule adresse publique.
Le certificat, champ par champ
Un certificat X.509 associe une clé publique à une identité, et il est signé par une autorité de certification (AC) qui se porte garante de cette association (certificat et PKI).
| Champ | Exemple | À vérifier |
|---|---|---|
| Sujet (Subject) | CN=intranet.sorbier.example | Informatif ; les navigateurs ne regardent plus le CN |
| Noms alternatifs (SAN) | DNS:intranet.sorbier.example, DNS:srv-intranet.ad.sorbier.example | Le nom tapé dans le navigateur doit y figurer, sinon erreur |
| Émetteur (Issuer) | CN=Sorbier-AC | L'AC qui a signé |
| Validité | du 3 novembre 2026 au 3 novembre 2027 | Un certificat expiré, ou pas encore valide, est refusé |
| Usage étendu de la clé | Authentification du serveur | Un certificat de client ne sert pas pour un serveur web |
| Clé publique | RSA 3072 bits, ou ECDSA P-256 | La clé privée correspondante reste sur le serveur, et seulement là |
Le navigateur fait confiance au certificat s'il peut remonter une chaîne de confiance : le certificat du serveur est signé par une AC intermédiaire, elle-même signée par une AC racine présente dans le magasin de confiance du système. Le serveur doit envoyer son certificat et les intermédiaires : un serveur qui n'envoie que son propre certificat fonctionne sur certains navigateurs (qui ont déjà l'intermédiaire en cache) et échoue sur d'autres.
| Format de fichier | Contenu | Où on le croise |
|---|---|---|
.pem, .crt (texte en base64, entre -----BEGIN CERTIFICATE----- et -----END…) | Certificat ou clé | Linux, Nginx, Apache, HAProxy |
.cer, .der (binaire) | Certificat | Windows |
.pfx, .p12 | Certificat et clé privée, protégés par mot de passe | Import dans Windows, transfert d'un serveur à un autre |
.csr | Demande de certificat : la clé publique et le nom, à signer par l'AC | Envoyée à l'AC |
Certificat public ou certificat interne ?
| Certificat d'une AC publique | Certificat de l'AC interne (AD CS) | |
|---|---|---|
| Reconnu par | Tous les navigateurs et systèmes du monde | Les seules machines qui font confiance à l'AC interne : les membres du domaine, automatiquement |
| Pour | Les sites publiés sur Internet : suivi.sorbier.example, la messagerie | Les services internes : intranet, consoles d'administration, 802.1X, LDAPS |
| Noms possibles | Uniquement des noms publics dont tu prouves la propriété | Tous les noms, y compris internes |
| Obtention | Automatisée par le protocole ACME (Let's Encrypt, gratuit) | Modèles de certificats, inscription automatique par GPO (cours Windows Server) |
| Durée | De plus en plus courte (voir ci-dessous) | Fixée par le modèle (souvent 1 ou 2 ans) |
Le protocole ACME (RFC 8555) obtient et renouvelle un certificat sans intervention : le client prouve qu'il contrôle le nom, par un défi HTTP (déposer un fichier à une adresse précise du site, sur le port 80) ou un défi DNS (créer un enregistrement TXT _acme-challenge dans la zone). Le défi DNS permet d'obtenir un certificat pour un nom qui n'est pas joignable depuis Internet, comme intranet.sorbier.example. Sur pfSense, le paquet acme fait ce travail pour les certificats du reverse proxy (chapitre 9) ; sous Debian, certbot ou acme.sh.
Publier l'intranet en HTTPS avec Nginx
srv-intranet est un serveur Debian 13 avec Nginx 1.26. L'intranet est un site interne : son certificat vient de l'AC interne de Sorbier, Sorbier-AC, à laquelle tous les postes du domaine font déjà confiance.
1. Créer la clé et la demande de certificat sur srv-intranet :
sudo mkdir -p /etc/ssl/sorbier && cd /etc/ssl/sorbier
sudo openssl req -new -newkey rsa:3072 -noenc \
-keyout intranet.key -out intranet.csr \
-subj "/O=Sorbier Logistique/CN=intranet.sorbier.example" \
-addext "subjectAltName=DNS:intranet.sorbier.example,DNS:srv-intranet.ad.sorbier.example"
sudo chmod 600 intranet.key
-noenc laisse la clé privée sans mot de passe, pour que Nginx démarre sans intervention ; elle est protégée par ses droits (lisible par root seulement).
2. Faire signer la demande par l'AC interne, depuis un serveur Windows du domaine, avec le modèle de serveur web publié sur l'AC (son nom court, sans espaces) :
certreq -submit -attrib "CertificateTemplate:SorbierServeurWeb" intranet.csr intranet.cer
certreq demande quelle autorité utiliser, puis enregistre le certificat signé dans intranet.cer. Copie-le sur srv-intranet, avec le certificat de l'AC, dans un fichier intranet.crt qui contient d'abord le certificat du serveur, puis celui de l'AC (format PEM).
3. Déclarer le site dans /etc/nginx/sites-available/intranet :
server {
listen 80;
server_name intranet.sorbier.example;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
http2 on;
server_name intranet.sorbier.example;
ssl_certificate /etc/ssl/sorbier/intranet.crt;
ssl_certificate_key /etc/ssl/sorbier/intranet.key;
ssl_protocols TLSv1.2 TLSv1.3;
add_header Strict-Transport-Security "max-age=31536000" always;
root /var/www/intranet;
index index.html;
access_log /var/log/nginx/intranet.access.log;
error_log /var/log/nginx/intranet.error.log;
location / {
try_files $uri $uri/ =404;
}
}
4. Activer et vérifier :
sudo ln -s /etc/nginx/sites-available/intranet /etc/nginx/sites-enabled/
sudo nginx -t # syntax is ok / test is successful
sudo systemctl reload nginx
curl -I https://intranet.sorbier.example
Le premier bloc server redirige tout le HTTP vers HTTPS (code 301). La directive http2 on; active HTTP/2 (elle remplace l'ancien paramètre http2 de la ligne listen, depuis Nginx 1.25). ssl_protocols refuse tout ce qui est plus ancien que TLS 1.2.
Tester un certificat en ligne de commande
# La chaîne présentée par le serveur, la version de TLS négociée
openssl s_client -connect intranet.sorbier.example:443 -servername intranet.sorbier.example </dev/null
# Les dates et les noms du certificat
openssl s_client -connect intranet.sorbier.example:443 -servername intranet.sorbier.example </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
# Sous Windows : tester le port, puis lire le certificat d'un site
Test-NetConnection intranet.sorbier.example -Port 443
curl.exe -vI https://intranet.sorbier.example
-servername envoie le SNI : sans lui, un serveur qui héberge plusieurs sites peut présenter un autre certificat que celui que tu veux tester. Pour un site public, le test en ligne SSL Labs note la configuration de A+ à F.
Exercices
Exercice 1 sur 4 Interpréter les codes Réussi À revoir
Pour chaque situation, donne le code HTTP le plus probable et la piste à suivre.
- Julie ouvre
http://intranet.sorbier.exampleet se retrouve surhttps://intranet.sorbier.example. - Un utilisateur connecté ouvre la page d'administration de GLPI, réservée aux techniciens.
- Le site de suivi affiche une erreur juste après le redémarrage de
srv-web; HAProxy, sur le pare-feu, est en marche. - Le navigateur affiche « Page introuvable » après la migration du site vers un nouveau dossier.
- L'application PHP de l'intranet affiche une page blanche et le journal d'erreurs contient
PHP Fatal error.
Voir la réponseMasquer la réponse de l'exercice 1
- 301 : la redirection HTTP vers HTTPS configurée sur le serveur. C'est le comportement attendu.
- 403 : l'utilisateur est identifié mais n'a pas les droits. Vérifier son profil GLPI.
- 502 ou 503 : le reverse proxy ne joint pas encore l'application (502), ou ses contrôles de santé la considèrent hors service (503). Attendre la fin du démarrage, vérifier le service web de
srv-web, puis l'état du serveur dans les statistiques de HAProxy. - 404 : le chemin demandé n'existe plus. Vérifier
rootdans la configuration Nginx et prévoir des redirections 301 des anciennes adresses vers les nouvelles. - 500 : erreur dans l'application. Le journal d'erreurs dit laquelle ; le problème n'est ni réseau ni DNS.
Tu avais trouvé ?
Exercice 2 sur 4 Les erreurs de certificat Réussi À revoir
Pour chaque message du navigateur, donne la cause et la correction.
- « Le nom du certificat ne correspond pas » en ouvrant
https://srv-intranet. - « Le certificat a expiré » sur le site de suivi, un lundi matin.
- « Autorité de certification inconnue » sur l'intranet, mais seulement sur le smartphone personnel d'un salarié connecté au Wi-Fi invité.
- Le site s'affiche dans les navigateurs, mais
curlet l'application mobile de Sorbier renvoient une erreur de chaîne de certificats.
Voir la réponseMasquer la réponse de l'exercice 2
- Le nom court
srv-intranetne figure pas dans les SAN (qui contiennentintranet.sorbier.exampleetsrv-intranet.ad.sorbier.example). Utiliser un nom du certificat, ou refaire le certificat avec ce nom. - Le renouvellement automatique (ACME) a échoué, ou n'existait pas. Renouveler, puis réparer l'automatisation et superviser la date d'expiration (alerte 20 jours avant, par exemple).
- Le smartphone n'est pas membre du domaine : il ne fait pas confiance à
Sorbier-AC. C'est normal, l'intranet n'a pas à être joint depuis le Wi-Fi invité. Pour un service interne utilisé sur des appareils hors domaine, il faut soit installer le certificat de l'AC sur ces appareils (gestion des mobiles), soit un certificat public. - Le serveur n'envoie pas le certificat intermédiaire. Les navigateurs le retrouvent par d'autres moyens (cache, téléchargement par l'extension AIA du certificat, préchargement des intermédiaires des AC publiques), les autres clients non. Ajouter l'intermédiaire au fichier
ssl_certificate, après le certificat du serveur (le fullchain).
Tu avais trouvé ?
Exercice 3 sur 4 Lire une configuration Nginx Réussi À revoir
Un stagiaire propose cette configuration pour l'intranet. Trouve trois défauts.
server {
listen 80;
listen 443 ssl;
server_name intranet;
ssl_certificate /var/www/intranet/cert.pem;
ssl_certificate_key /var/www/intranet/cert.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
root /var/www/intranet;
}
Voir la réponseMasquer la réponse de l'exercice 3
- La clé privée est dans le dossier du site (
/var/www/intranet) : selon la configuration, elle pourrait être téléchargée par n'importe qui. Les clés vont hors de la racine web, par exemple dans/etc/ssl/sorbier/, avec des droits600. - TLS 1.0 et 1.1 sont autorisés : ce sont des versions obsolètes et vulnérables. Garder
TLSv1.2 TLSv1.3. - Le HTTP n'est pas redirigé vers HTTPS : le même site est servi en clair sur le port 80. Séparer un bloc
listen 80qui faitreturn 301 https://$host$request_uri;.
En bonus : server_name intranet ne correspond pas au nom complet intranet.sorbier.example, et il manque http2 on; et l'en-tête HSTS.
Tu avais trouvé ?
Exercice 4 sur 4 Préparer la demande de certificat Réussi À revoir
Sorbier publie sur srv-web un second site interne, docs.sorbier.example, qui doit aussi répondre au nom srv-web.dmz.sorbier.example.
- Écris la commande
opensslqui crée la clé RSA de 3 072 bits et la demande de certificat. - Le site sera consulté par des clients extérieurs. Quelle AC choisis-tu ? Le second nom pose-t-il un problème ?
- Avec la règle des 200 jours en vigueur en novembre 2026, combien de fois au moins faut-il renouveler un certificat public sur trois ans ? Que faut-il en conclure ?
Voir la réponseMasquer la réponse de l'exercice 4
-
La commande :
openssl req -new -newkey rsa:3072 -noenc -keyout docs.key -out docs.csr \ -subj "/O=Sorbier Logistique/CN=docs.sorbier.example" \ -addext "subjectAltName=DNS:docs.sorbier.example,DNS:srv-web.dmz.sorbier.example" -
Une AC publique, puisque les clients extérieurs ne font pas confiance à l'AC interne. Le second nom est un nom interne qui n'existe pas dans le DNS public : l'AC publique ne pourra pas vérifier sa propriété par un défi HTTP, et le nom apparaîtrait dans les journaux publics de certificats. Retire-le du certificat public.
-
Trois ans font 1 095 jours (1 096 avec une année bissextile) ; à 200 jours par certificat, il en faut au moins 6 (6 × 200 = 1 200 jours), soit le certificat initial et 5 renouvellements. Et la durée tombe à 100 jours en mars 2027 : il en faudra davantage. Conclusion : le renouvellement doit être automatique (ACME), et l'expiration supervisée.
Tu avais trouvé ?