Aide-mémoire SSL/TLS, OpenSSL et Certbot
Concepts Clés
TermeDescription
SSL / TLSTLS (Transport Layer Security) est le successeur de SSL. On dit encore "SSL" par habitude mais TLS 1.2/1.3 est ce qui est utilisé aujourd'hui.
Certificat (CRT / PEM)Fichier contenant la clé publique + infos sur l'entité (domaine, organisation, dates de validité). Signé par une CA.
Clé privée (KEY)Fichier secret à ne jamais divulguer. Associé au certificat.
CSRCertificate Signing Request — demande de signature de certificat envoyée à une CA.
CACertificate Authority — autorité de certification (Let's Encrypt, DigiCert, GlobalSign…).
SANSubject Alternative Names — liste de domaines couverts par un seul certificat (ex: exemple.com + www.exemple.com).
FormatsPEM :: Base64 encodé (.crt .pem .key)
DER :: binaire (.der .cer)
PFX/P12 :: bundle clé + cert pour Windows/IIS (.pfx .p12)
CRT :: souvent PEM renommé
Bundle :: concat issuer chain + cert dans un PEM
OpenSSL — Inspecter des Certificats
ObjectifCommande
Afficher un certificat (fichier) openssl x509 -in cert.pem -text -noout
openssl x509 -in cert.pem -noout -subject -issuer -dates
openssl x509 -in cert.pem -noout -enddate  :: date d'expiration
Vérifier un certificat sur un serveur openssl s_client -connect exemple.com:443
openssl s_client -connect exemple.com:443 -servername exemple.com
echo | openssl s_client -connect exemple.com:443 2>/dev/null | openssl x509 -noout -dates
echo | openssl s_client -connect exemple.com:443 2>/dev/null | openssl x509 -noout -subject
Vérifier la date d'expiration :: expire dans N jours ? (0 = déjà expiré)
openssl x509 -in cert.pem -noout -checkend $((30*86400))

:: via réseau
echo | openssl s_client -connect exemple.com:443 2>/dev/null \
  | openssl x509 -noout -enddate
Afficher les SANs (Subject Alt Names) openssl x509 -in cert.pem -noout -ext subjectAltName
openssl s_client -connect exemple.com:443 </dev/null 2>/dev/null \
  | openssl x509 -noout -ext subjectAltName
Vérifier clé privée + certificat (doivent correspondre) openssl x509 -noout -modulus -in cert.pem | md5sum
openssl rsa -noout -modulus -in key.pem | md5sum
:: Les deux sommes doivent être identiques
Vérifier la chaîne de confiance openssl verify -CAfile ca-bundle.crt cert.pem
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt cert.pem
OpenSSL — Générer des Certificats
Certificat auto-signé (dev/test) :: Générer clé + certificat auto-signé en une commande
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
  -sha256 -days 365 -nodes \
  -subj "/C=FR/ST=IDF/L=Paris/O=MonOrg/CN=localhost"

:: Avec SAN pour localhost et IP
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
  -sha256 -days 365 -nodes \
  -subj "/CN=localhost" \
  -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
Générer une clé RSA openssl genrsa -out key.pem 4096
openssl genrsa -aes256 -out key_protected.pem 4096 :: avec passphrase
Générer une clé EC (ECDSA) openssl ecparam -name prime256v1 -genkey -noout -out ec_key.pem
Générer un CSR openssl req -new -key key.pem -out cert.csr
openssl req -noout -text -in cert.csr          :: vérifier le CSR
Enlever la passphrase d'une clé openssl rsa -in key_protected.pem -out key.pem
OpenSSL — Conversions de Formats
PEM → DER openssl x509 -in cert.pem -outform DER -out cert.der
DER → PEM openssl x509 -in cert.der -inform DER -out cert.pem
PEM → PFX/P12 (pour IIS/Windows) openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -certfile ca-chain.pem
PFX → PEM openssl pkcs12 -in cert.pfx -out cert.pem -nodes
openssl pkcs12 -in cert.pfx -nocerts -out key.pem -nodes :: clé seule
Créer un bundle (chaîne complète) cat cert.pem intermediate.pem > fullchain.pem
Certbot — Let's Encrypt
Installation :: Debian/Ubuntu
apt install certbot python3-certbot-apache
apt install certbot python3-certbot-nginx

:: snap (universel)
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
Émettre un certificat — Apache certbot --apache -d exemple.com -d www.exemple.com
certbot --apache -d exemple.com                    :: simple
certbot --apache --agree-tos --email admin@exemple.com -d exemple.com
Émettre un certificat — Nginx certbot --nginx -d exemple.com -d www.exemple.com
Mode standalone (sans serveur web) :: Arrêter le serveur web d'abord (libérer le port 80)
certbot certonly --standalone -d exemple.com
Mode webroot certbot certonly --webroot -w /var/www/html -d exemple.com
Emplacement des certificats /etc/letsencrypt/live/exemple.com/
├── cert.pem      :: certificat seul
├── chain.pem     :: chaîne intermédiaire
├── fullchain.pem :: cert + chaîne (à utiliser dans Apache)
└── privkey.pem   :: clé privée
Renouvellement certbot renew               :: renouveler tous les certs proches d'expiration
certbot renew --dry-run      :: simuler sans exécuter
certbot renew --force-renewal :: forcer le renouvellement

:: Vérifier le timer systemd automatique
systemctl status certbot.timer
systemctl list-timers | grep certbot
Cron de renouvellement (si pas de timer) :: Ajouter dans crontab -e :
0 3 * * * certbot renew --quiet --post-hook "systemctl reload apache2"
Lister les certificats certbot certificates
Révoquer / Supprimer certbot revoke --cert-path /etc/letsencrypt/live/exemple.com/cert.pem
certbot delete --cert-name exemple.com
Configuration Apache SSL
Activer le module SSL a2enmod ssl
a2enmod headers
systemctl restart apache2
VirtualHost HTTPS (443) <VirtualHost *:443>
  ServerName exemple.com
  DocumentRoot /var/www/html

  SSLEngine on
  SSLCertificateFile    /etc/letsencrypt/live/exemple.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/exemple.com/privkey.pem

  :: TLS moderne
  SSLProtocol -all +TLSv1.2 +TLSv1.3
  SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
  SSLHonorCipherOrder off
  SSLSessionTickets off

  :: HSTS (après avoir testé que HTTPS fonctionne)
  Header always set Strict-Transport-Security "max-age=63072000"
</VirtualHost>
Redirection HTTP → HTTPS <VirtualHost *:80>
  ServerName exemple.com
  RewriteEngine On
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
Tester la config Apache apache2ctl configtest
apachectl -t
apachectl -S   :: liste les VirtualHosts
Vérification et Dépannage
Outils en ligne https://www.ssllabs.com/ssltest/    :: audit complet SSL
https://www.whynopadlock.com/      :: contenu mixte HTTP/HTTPS
https://crt.sh/                   :: historique certificats CT log
https://decoder.link/sslchecker   :: vérifier chaîne
Script bash : contrôle expiration #!/bin/bash
DOMAINE="exemple.com"
JOURS=30
expire=$(echo | openssl s_client -connect $DOMAINE:443 -servername $DOMAINE 2>/dev/null \
          | openssl x509 -noout -enddate | cut -d= -f2)
expire_ts=$(date -d "$expire" +%s)
now_ts=$(date +%s)
diff_jours=$(( (expire_ts - now_ts) / 86400 ))
echo "Certificat $DOMAINE expire dans $diff_jours jours ($expire)"
[[ $diff_jours -lt $JOURS ]] && echo "ATTENTION : renouvellement proche !"
Erreurs courantes SSL_ERROR_RX_RECORD_TOO_LONG   :: HTTP servi sur port HTTPS
ERR_CERT_AUTHORITY_INVALID     :: CA inconnue (auto-signé)
ERR_CERT_DATE_INVALID          :: cert expiré
ERR_CERT_COMMON_NAME_INVALID   :: domaine ne correspond pas au cert
MIXED CONTENT                  :: ressources HTTP dans une page HTTPS