Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

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.

text
$ 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éthodeUsageModifie quelque chose sur le serveur ?
GETLire une ressource (une page, une image, des données)Non
HEADComme GET, mais sans le corps : seulement les en-têtesNon
POSTEnvoyer des données : formulaire, création d'une ressourceOui
PUTRemplacer une ressourceOui
PATCHModifier une partie d'une ressourceOui
DELETESupprimer une ressourceOui
OPTIONSDemander quelles méthodes le serveur accepteNon

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.

CodeSensExemple de situation
200 OKSuccèsLa page s'affiche
201 CreatedRessource crééeUne API a enregistré un nouveau ticket
204 No ContentSuccès, sans corpsUne suppression réussie dans une API
301 Moved PermanentlyRedirection définitivehttp:// redirigé vers https://
302 Found / 307 Temporary RedirectRedirection temporaireRenvoi vers la page de connexion
304 Not ModifiedLa copie en cache est encore bonneLe navigateur réutilise l'image qu'il a déjà
400 Bad RequestRequête mal forméeJSON invalide envoyé à une API
401 UnauthorizedAuthentification requise ou refuséePas de session, mot de passe faux
403 ForbiddenAuthentifié, mais pas autoriséUn utilisateur sans droit sur la page d'administration, ou des droits de fichiers trop restrictifs sur le serveur
404 Not FoundLa ressource n'existe pasLien cassé, mauvais chemin
405 Method Not AllowedMéthode refusée pour cette ressourceUn DELETE sur une page statique
429 Too Many RequestsTrop de requêtesLimitation de débit d'une API
500 Internal Server ErrorErreur dans l'applicationUne exception PHP non gérée
502 Bad GatewayLe serveur intermédiaire a reçu une réponse invalide du serveur suivantLe reverse proxy ne joint pas l'application, ou l'application a planté (chapitre 9)
503 Service UnavailableService indisponibleMaintenance, surcharge, aucun serveur disponible derrière le répartiteur
504 Gateway TimeoutLe serveur intermédiaire a attendu trop longtempsL'application met trop de temps à répondre

Les en-têtes à connaître

En-têteSensUtilité
HostLe nom du site demandéUn même serveur héberge plusieurs sites (hôtes virtuels) et choisit d'après ce nom
User-AgentLe logiciel clientStatistiques, journaux, détection de robots
Content-TypeLe format du corpstext/html, application/json
LocationL'adresse de redirectionAvec les codes 301, 302, 307, 308
Cookie / Set-CookieLe cookie de sessionRester connecté
Cache-ControlLes règles de cacheno-store pour les pages sensibles
Strict-Transport-SecurityHSTS : « ne viens plus qu'en HTTPS »Empêche le retour au HTTP en clair
X-Forwarded-ForL'adresse du vrai client, ajoutée par un reverse proxyLe serveur final connaît le client malgré l'intermédiaire

HTTP/1.1, HTTP/2, HTTP/3

VersionTransportCe qui change
HTTP/1.1 (1997, aujourd'hui RFC 9112)TCP, en texteUne 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 TLSPlusieurs requêtes en parallèle sur une seule connexion, en-têtes compressés
HTTP/3 (2022, RFC 9114)QUIC, sur UDP 443Connexion 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).

ChampExempleÀ vérifier
Sujet (Subject)CN=intranet.sorbier.exampleInformatif ; les navigateurs ne regardent plus le CN
Noms alternatifs (SAN)DNS:intranet.sorbier.example, DNS:srv-intranet.ad.sorbier.exampleLe nom tapé dans le navigateur doit y figurer, sinon erreur
Émetteur (Issuer)CN=Sorbier-ACL'AC qui a signé
Validitédu 3 novembre 2026 au 3 novembre 2027Un certificat expiré, ou pas encore valide, est refusé
Usage étendu de la cléAuthentification du serveurUn certificat de client ne sert pas pour un serveur web
Clé publiqueRSA 3072 bits, ou ECDSA P-256La 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 fichierContenuOù on le croise
.pem, .crt (texte en base64, entre -----BEGIN CERTIFICATE----- et -----END…)Certificat ou cléLinux, Nginx, Apache, HAProxy
.cer, .der (binaire)CertificatWindows
.pfx, .p12Certificat et clé privée, protégés par mot de passeImport dans Windows, transfert d'un serveur à un autre
.csrDemande de certificat : la clé publique et le nom, à signer par l'ACEnvoyée à l'AC

Certificat public ou certificat interne ?

Certificat d'une AC publiqueCertificat de l'AC interne (AD CS)
Reconnu parTous les navigateurs et systèmes du mondeLes seules machines qui font confiance à l'AC interne : les membres du domaine, automatiquement
PourLes sites publiés sur Internet : suivi.sorbier.example, la messagerieLes services internes : intranet, consoles d'administration, 802.1X, LDAPS
Noms possiblesUniquement des noms publics dont tu prouves la propriétéTous les noms, y compris internes
ObtentionAutomatisée par le protocole ACME (Let's Encrypt, gratuit)Modèles de certificats, inscription automatique par GPO (cours Windows Server)
DuréeDe 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 :

bash
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) :

powershell
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 :

nginx
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 :

bash
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

bash
# 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
powershell
# 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.

  1. Julie ouvre http://intranet.sorbier.example et se retrouve sur https://intranet.sorbier.example.
  2. Un utilisateur connecté ouvre la page d'administration de GLPI, réservée aux techniciens.
  3. Le site de suivi affiche une erreur juste après le redémarrage de srv-web ; HAProxy, sur le pare-feu, est en marche.
  4. Le navigateur affiche « Page introuvable » après la migration du site vers un nouveau dossier.
  5. 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
  1. 301 : la redirection HTTP vers HTTPS configurée sur le serveur. C'est le comportement attendu.
  2. 403 : l'utilisateur est identifié mais n'a pas les droits. Vérifier son profil GLPI.
  3. 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.
  4. 404 : le chemin demandé n'existe plus. Vérifier root dans la configuration Nginx et prévoir des redirections 301 des anciennes adresses vers les nouvelles.
  5. 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.

  1. « Le nom du certificat ne correspond pas » en ouvrant https://srv-intranet.
  2. « Le certificat a expiré » sur le site de suivi, un lundi matin.
  3. « Autorité de certification inconnue » sur l'intranet, mais seulement sur le smartphone personnel d'un salarié connecté au Wi-Fi invité.
  4. Le site s'affiche dans les navigateurs, mais curl et l'application mobile de Sorbier renvoient une erreur de chaîne de certificats.
Voir la réponseMasquer la réponse de l'exercice 2
  1. Le nom court srv-intranet ne figure pas dans les SAN (qui contiennent intranet.sorbier.example et srv-intranet.ad.sorbier.example). Utiliser un nom du certificat, ou refaire le certificat avec ce nom.
  2. 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).
  3. 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.
  4. 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.

nginx
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
  1. 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 droits 600.
  2. TLS 1.0 et 1.1 sont autorisés : ce sont des versions obsolètes et vulnérables. Garder TLSv1.2 TLSv1.3.
  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 80 qui fait return 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.

  1. Écris la commande openssl qui crée la clé RSA de 3 072 bits et la demande de certificat.
  2. Le site sera consulté par des clients extérieurs. Quelle AC choisis-tu ? Le second nom pose-t-il un problème ?
  3. 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
  1. La commande :

    bash
    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"
    
  2. 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.

  3. 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é ?

Chapitre terminé !

Fais les 4 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Reverse proxy et répartition de charge : HAProxy sur pfSenseRevoir le sommaire du cours