Aide-mémoire SSL/TLS, OpenSSL et Certbot
| Concepts Clés |
| Terme | Description |
| SSL / TLS | TLS (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. |
| CSR | Certificate Signing Request — demande de signature de certificat envoyée à une CA. |
| CA | Certificate Authority — autorité de certification (Let's Encrypt, DigiCert, GlobalSign…). |
| SAN | Subject Alternative Names — liste de domaines couverts par un seul certificat (ex: exemple.com + www.exemple.com). |
| Formats | PEM :: 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 |
| Objectif | Commande |
| 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 |