Esc
 Naviguer  Ouvrir Esc Fermer
Aller au contenu

2.3 — Sécurité du transport (TLS)

🎯 Objectif : comprendre ce qui se passe pendant le TLS handshake, ce qu’est un certificat, et comment configurer HTTPS proprement (HSTS, redirections, mixed content).

À l'issue de cet axe, tu sauras :

  • Expliquer ce qui se passe pendant un TLS handshake
  • Lire un certificat X.509 et identifier émetteur, sujet, validité
  • Mettre en place Let's Encrypt en 5 minutes avec Caddy ou Certbot
  • Configurer HSTS, redirection HTTP → HTTPS, mixed content
  • Comprendre les types de certificats (DV, OV, EV) et choisir

Débutant 10 min prérequis : axe 1 lu

HTTP en clair signifie que tout le monde sur le chemin (Wi-Fi public, FAI, gouvernement) peut :

  1. Lire ton trafic (mots de passe, cookies, données).
  2. Modifier les pages reçues (injecter des pubs, du malware).
  3. Usurper l’identité de sites populaires.

HTTPS = HTTP encapsulé dans TLS. Ça apporte :

  • Confidentialité (chiffrement) : personne ne peut lire.
  • Intégrité (HMAC) : personne ne peut modifier sans être détecté.
  • Authentification (certificat) : tu parles bien au vrai serveur.

Avant d’envoyer la moindre requête HTTP, le client et le serveur négocient une connexion sécurisée.

sequenceDiagram
    participant C as Client
    participant S as Serveur

    C->>S: ClientHello<br/>(versions TLS supportées,<br/>cipher suites,<br/>clé publique éphémère)
    S->>C: ServerHello + Certificat + Clé publique<br/>+ Finished
    C->>C: Vérifie le certificat<br/>(chaîne, validité, nom)
    C->>S: Finished<br/>(connexion établie)
    Note over C,S: Données HTTP chiffrées circulent
TLS 1.3 handshake — 1 RTT seulement

TLS 1.3 (2018) optimise tout :

  • 1 RTT seulement (TLS 1.2 en demandait 2)
  • Chiffres archaïques supprimés (RC4, 3DES, MD5…)
  • 0-RTT possible pour les reconnexions

Un certificat est un fichier signé par une autorité de certification (CA). Il dit :

« Moi, Let’s Encrypt, je certifie que la clé publique ci-jointe appartient à example.com, et c’est valable jusqu’au 15 janvier 2026. »

Subject: CN=example.com, O=Example Corp
Issuer: CN=R3, O=Let's Encrypt
Valid from: 2025-10-15
Valid until: 2026-01-15
Serial number: 04:5A:6B:...
Public Key: RSA 2048 bits
Signature: <signature de l'issuer>
SAN: example.com, www.example.com, api.example.com

SAN (Subject Alternative Names) liste tous les noms couverts par le certificat. C’est ainsi qu’un seul cert protège plusieurs sous-domaines.

Fenêtre de terminal
# Avec OpenSSL
openssl s_client -connect example.com:443 -servername example.com < /dev/null \
| openssl x509 -text -noout
# Plus simple
echo | openssl s_client -showcerts -connect example.com:443

Dans le navigateur : clic sur le cadenas → Certificat.

Un cert n’est pas signé directement par une racine de confiance. Il y a une chaîne :

flowchart TD
    Root[Root CA<br/>ex. ISRG Root X1<br/>installée dans l'OS/navigateur]
    Inter[Certificat intermédiaire<br/>ex. Let's Encrypt R3<br/>signé par la Root]
    Leaf[Certificat du serveur<br/>example.com<br/>signé par l'intermédiaire]
    Root --> Inter --> Leaf
Chaîne de certificats — 3 niveaux typiques

Le serveur doit envoyer la chaîne (sauf la racine, déjà connue du client). Une chaîne incomplète = warning navigateur.

TypeValidationCoûtCas
DV (Domain Validated)« Tu contrôles le domaine » (challenge HTTP/DNS)Gratuit (Let’s Encrypt)95 % des cas
OV (Organization Validated)DV + vérification de l’organisation~100 €/anSites pro qui veulent montrer le nom
EV (Extended Validation)OV + vérification approfondie~300 €/anBanques (mais l’effet visuel a quasi disparu en 2020+)

Pour 99 % des cas en 2026 : utilise Let’s Encrypt (DV, gratuit, automatisé).

Caddy obtient et renouvelle Let’s Encrypt automatiquement.

# Caddyfile
example.com {
reverse_proxy localhost:3000
}
Fenêtre de terminal
caddy run

C’est tout. HTTPS, redirection HTTP→HTTPS, renouvellement, HTTP/3 — gratuit.

Fenêtre de terminal
# Installer Certbot
sudo apt install certbot python3-certbot-nginx
# Obtenir un certificat
sudo certbot --nginx -d example.com -d www.example.com

Certbot modifie ta config Nginx automatiquement et installe un cron de renouvellement.

HTTPS automatique, rien à configurer. Tu pousses ton code, le service gère cert + renouvellement.

# Nginx
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}

Annonce au navigateur : « Pour ce domaine, n’utilise QUE HTTPS pendant N secondes, même si l’utilisateur tape http:// ».

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
DirectiveEffet
max-age=315360001 an
includeSubDomainsApplique aux sous-domaines
preloadHardcoded dans Chrome/Firefox/etc. (soumets sur hstspreload.org)

Une page HTTPS qui charge des ressources HTTP (images, scripts) :

<!-- ❌ MAUVAIS : mixed content -->
<img src="http://cdn.example.com/logo.png">
<!-- ✅ BON -->
<img src="https://cdn.example.com/logo.png">
<!-- ou URL relative au protocole (vieux) -->
<img src="//cdn.example.com/logo.png">

Le navigateur bloque les scripts/iframes mixed content (active mixed content), affiche un warning pour les images (passive mixed content).

Header pour tout migrer d’un coup :

Content-Security-Policy: upgrade-insecure-requests

Réécrit automatiquement les http: en https: dans la page.

  • Le nom du domaine (visible via SNI dans le ClientHello — voir ECH/Encrypted ClientHello en cours d’adoption).
  • Les métadonnées : taille des paquets, timing.
  • La machine compromise : un keylogger sur le client voit tout.

Le bouton « j’accepte le certificat invalide »

Section intitulée « Le bouton « j’accepte le certificat invalide » »

Toujours rouge. Même en dev. Si tu travailles en HTTPS local, utilise mkcert :

Fenêtre de terminal
brew install mkcert # ou choco install mkcert
mkcert -install
mkcert localhost 127.0.0.1
# génère localhost.pem + localhost-key.pem

Ton navigateur fait confiance, pas de warning.

Que protège TLS ?
Tu vois le message 'Mixed Content blocked' dans la console. Que se passe-t-il ?
Tu mets en place HSTS avec max-age=31536000. Tu réalises que ton renouvellement de certificat échoue. Qu'arrive-t-il aux visiteurs déjà venus ?

Suite : 2.4 — Anatomie d’un navigateur — comment le HTML reçu devient des pixels.