Certificats SSL/TLS i Certbot
Aquesta pàgina explica què és realment un certificat digital, quins fitxers hi intervenen (.pem, .crt, .cer, .key, .csr, .pfx...) i com obtenir-los i gestionar-los de forma automatitzada amb Certbot. És la base que després s'aplica a Apache, IIS i Nginx.
Xifratge asimètric: la base de tot
TLS es basa en criptografia asimètrica: una parella de claus matemàticament relacionades.
- Clau privada (
private key): es queda sempre al servidor, mai es comparteix. Serveix per desxifrar i per signar. - Clau pública (
public key): es distribueix lliurement (va dins del certificat). Serveix per xifrar i per verificar signatures.
El que es xifra amb la pública només es pot desxifrar amb la privada corresponent, i viceversa. Un certificat digital no és més que la clau pública del servidor empaquetada junt amb metadades (a quin domini pertany, qui l'ha emès, quan caduca...) i signada digitalment per una Autoritat de Certificació (CA) perquè els navegadors puguin confiar-hi.
graph LR
A[Clau privada] -- es guarda al servidor --> B[Servidor Web]
C[Clau pública] -- s'inclou al --> D[Certificat]
D -- signat per --> E[Autoritat de Certificació]
D -- s'envia al --> F[Client/Navegador]
F -- xifra dades amb --> C
B -- desxifra amb --> A
La clau privada mai es comparteix
Si algú obté la clau privada del teu servidor, pot suplantar-lo (desxifrar trànsit interceptat o generar un servidor fals que el navegador consideri legítim). Els permisos del fitxer .key han de ser restrictius (chmod 600, propietari root o l'usuari del servei) i mai s'ha de pujar a un repositori Git.
Cadena de confiança (chain of trust)
Els navegadors no confien "a cegues" en qualsevol certificat: confien en un conjunt reduït de CA arrel (root CA) que porten preinstal·lades. Per motius de seguretat, les CA arrel gairebé mai signen certificats de servidor directament: signen CA intermèdies, i són aquestes les que signen el certificat final del teu domini.
graph TD
Root["CA Arrel (Root CA)<br/>preinstal·lada al navegador/SO"] -->|signa| Inter["CA Intermèdia<br/>(p. ex. Let's Encrypt R3)"]
Inter -->|signa| Leaf["Certificat del domini<br/>(end-entity / leaf)<br/>www.exemple.cat"]
Perquè el navegador pugui reconstruir aquesta cadena fins arribar a una arrel de confiança, el servidor no ha d'enviar només el seu certificat: ha d'enviar també els certificats intermedis. Quan falta algun esglaó, el navegador mostra errors com "certificat no confiable" tot i que el certificat en si sigui vàlid — és l'error més habitual en desplegaments manuals.
Sol·licitud de certificat: la CSR
Per obtenir un certificat d'una CA, no s'envia la clau privada. El procediment és:
- El servidor genera la parella de claus (privada + pública).
- Es genera una CSR (Certificate Signing Request): un fitxer que conté la clau pública i les dades del domini/organització, tot signat amb la clau privada per demostrar que en tens el control.
- Es passa la CSR a la CA.
- La CA valida el domini (per HTTP, DNS o correu, segons el tipus de certificat) i emet el certificat: la clau pública de la CSR, signada per la CA.
# 1. Generar clau privada (RSA 2048 bits)
openssl genrsa -out exemple.cat.key 2048
# 2. Generar la CSR a partir de la clau privada
openssl req -new -key exemple.cat.key -out exemple.cat.csr \
-subj "/C=ES/ST=Girona/L=Blanes/O=Exemple SL/CN=www.exemple.cat"
# 3. Inspeccionar el contingut de la CSR abans d'enviar-la
openssl req -text -noout -in exemple.cat.csr
Amb Let's Encrypt i Certbot aquests tres passos són automàtics: Certbot genera la clau, la CSR, prova que controles el domini, i desa el certificat emès, tot en una sola comanda.
Tipus de validació de certificats
| Tipus | Validació | Ús habitual |
|---|---|---|
| DV (Domain Validation) | Només es comprova que controles el domini (HTTP o DNS) | La majoria de llocs web; és el que emet Let's Encrypt |
| OV (Organization Validation) | Es verifiquen també dades de l'organització | Empreses que volen mostrar-hi el seu nom |
| EV (Extended Validation) | Verificació legal exhaustiva de l'organització | Banca i finances (cada cop menys diferenciat visualment als navegadors) |
Formats i extensions de fitxer: la part que confon
El contingut (clau, certificat...) es pot codificar amb diferents formats, i l'extensió del fitxer no sempre indica el format real amb precisió — és una font habitual d'errors.
Formats de codificació
-
PEM (
Privacy Enhanced Mail): text en Base64, delimitat per capçaleres llegibles. És el format més utilitzat a Linux/Apache/Nginx.Una clau privada en PEM comença per
-----BEGIN PRIVATE KEY-----(oRSA PRIVATE KEYen formats més antics). -
DER: la mateixa informació que PEM però en binari, sense codificar en Base64. Habitual a Java/Windows.
Extensions més comunes
| Extensió | Què sol contenir | Format típic |
|---|---|---|
.key |
Clau privada | PEM |
.csr |
Petició de signatura (Certificate Signing Request) | PEM |
.crt / .cer |
Certificat (clau pública signada) | PEM o DER — cal comprovar-ho |
.pem |
Qualsevol dels anteriors, o diversos concatenats | PEM |
.p7b / .p7c |
Certificat(s) sense la clau privada, format PKCS#7 | DER o PEM |
.pfx / .p12 |
Clau privada + certificat(s), tot junt i xifrat amb contrasenya, format PKCS#12 | Binari |
.crt i .cer no garanteixen el format
A diferència de .pem, les extensions .crt i .cer no indiquen si el contingut és PEM (text) o DER (binari) — cal obrir el fitxer o provar-lo amb openssl per saber-ho amb certesa. IIS/Windows sol treballar amb DER i amb el contenidor .pfx; Apache/Nginx treballen amb PEM.
Els fitxers que genera Let's Encrypt
Quan Certbot emet un certificat, deixa quatre fitxers a /etc/letsencrypt/live/<domini>/:
| Fitxer | Contingut |
|---|---|
privkey.pem |
La clau privada. Mai es comparteix. |
cert.pem |
Només el certificat del domini (leaf), sense la cadena |
chain.pem |
Només els certificats intermedis (la cadena, sense el del domini) |
fullchain.pem |
cert.pem + chain.pem concatenats — és el que s'ha de configurar al servidor com a SSLCertificateFile/ssl_certificate |
# fullchain.pem és literalment la concatenació d'aquests dos:
cat cert.pem chain.pem > fullchain.pem
La majoria de servidors web (Apache amb mod_ssl, Nginx) necessiten dos fitxers per activar TLS: el fullchain.pem (certificat + cadena) i el privkey.pem (clau privada) per separat.
Certbot en detall
Certbot és el client oficial de Let's Encrypt. Automatitza els tres passos de sol·licitud (clau, CSR, validació) i, opcionalment, la configuració del servidor web.
Instal·lació
sudo apt update
sudo apt install certbot
# Plugin específic segons el servidor
sudo apt install python3-certbot-apache # per Apache
sudo apt install python3-certbot-nginx # per Nginx
Mètodes de validació (plugins)
Certbot ha de demostrar a Let's Encrypt que controles el domini abans d'emetre el certificat. Els mètodes més habituals:
Webroot — Certbot deixa un fitxer temporal dins el DocumentRoot que el servidor ja serveix, i Let's Encrypt el descarrega per HTTP:
Standalone — Certbot aixeca el seu propi mini-servidor al port 80 (cal que Apache/Nginx no estigui escoltant en aquell moment):
sudo systemctl stop nginx
sudo certbot certonly --standalone -d exemple.cat
sudo systemctl start nginx
Plugin integrat (Apache/Nginx) — Certbot detecta la configuració, obté el certificat i edita el VirtualHost/server automàticament perquè n'hi apunti:
sudo certbot --apache -d exemple.cat -d www.exemple.cat
sudo certbot --nginx -d exemple.cat -d www.exemple.cat
DNS-01 — Certbot demana que es creï un registre TXT concret al DNS del domini. És l'únic mètode possible per a certificats wildcard (*.exemple.cat), perquè no hi ha cap "servidor web" associat a un wildcard on servir un fitxer:
sudo apt install python3-certbot-dns-cloudflare
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d "*.exemple.cat" -d "exemple.cat"
AC0375/03/12 — Miniactivitat
RA3 · CA3f
Sobre un servidor Apache o Nginx amb un nom de domini vàlid i accessible des d'Internet (o simulat amb /etc/hosts i un domini de proves), obtén un certificat amb Certbot fent servir el plugin integrat (--apache o --nginx). Localitza els quatre fitxers a /etc/letsencrypt/live/<domini>/ i explica amb les teves paraules per a què serveix cadascun.
Renovació automàtica
Els certificats de Let's Encrypt caduquen als 90 dies (a propòsit, per forçar l'automatització). Certbot instal·la un temporitzador systemd que comprova dos cops al dia si cal renovar (renova quan queden menys de 30 dies):
# Comprovar que el temporitzador està actiu
sudo systemctl status certbot.timer
# Simular una renovació sense fer-la de veritat
sudo certbot renew --dry-run
# Forçar la renovació de tots els certificats
sudo certbot renew --force-renewal
Hooks de desplegament — executar una acció (com recarregar el servidor) automàticament després de cada renovació:
sudo certbot renew --deploy-hook "systemctl reload nginx"
# O bé deixar un script a:
# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
Gestió de certificats existents
# Llistar certificats gestionats per Certbot
sudo certbot certificates
# Revocar un certificat (per exemple, si la clau privada s'ha vist compromesa)
sudo certbot revoke --cert-path /etc/letsencrypt/live/exemple.cat/cert.pem
# Eliminar un certificat de la configuració de Certbot
sudo certbot delete --cert-name exemple.cat
Inspeccionar i convertir certificats amb OpenSSL
Inspeccionar
# Veure el contingut d'un certificat (domini, emissor, validesa...)
openssl x509 -in cert.pem -text -noout
# Veure només la data de caducitat
openssl x509 -in cert.pem -noout -enddate
# Comprovar que la clau privada i el certificat es corresponen
# (els dos hash han de coincidir)
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in privkey.pem | openssl md5
# Comprovar un certificat servit en viu per un domini
openssl s_client -connect exemple.cat:443 -servername exemple.cat </dev/null 2>/dev/null | openssl x509 -noout -dates -issuer
Convertir entre formats
# PEM -> DER
openssl x509 -in cert.pem -outform der -out cert.der
# DER -> PEM
openssl x509 -in cert.der -inform der -outform pem -out cert.pem
# PEM (cert + clau) -> PFX/P12 (necessari sovint per IIS o Java)
openssl pkcs12 -export -out certificat.pfx \
-inkey privkey.pem -in cert.pem -certfile chain.pem
# PFX/P12 -> PEM (extreure clau i certificat per fer-los servir a Apache/Nginx)
openssl pkcs12 -in certificat.pfx -nocerts -nodes -out privkey.pem
openssl pkcs12 -in certificat.pfx -clcerts -nokeys -out cert.pem
AC0375/03/13 — Miniactivitat
RA3 · CA3f
A partir del fullchain.pem i privkey.pem generats a l'activitat anterior, utilitza openssl per: (1) mostrar la data de caducitat del certificat, (2) comprovar que la clau privada es correspon amb el certificat comparant els hashos de mòdul, i (3) generar un fitxer .pfx protegit amb contrasenya a partir dels fitxers PEM.
Errors habituals
| Símptoma | Causa probable |
|---|---|
| "NET::ERR_CERT_AUTHORITY_INVALID" tot i tenir un certificat vàlid | Falta la cadena intermèdia: s'ha configurat cert.pem en lloc de fullchain.pem |
| El servidor no arrenca en aplicar TLS | La clau privada no es correspon amb el certificat, o els permisos del fitxer .key no permeten llegir-lo a l'usuari del servei |
| Certificat caducat sense avís previ | El temporitzador certbot.timer no està actiu, o el deploy-hook que recarrega el servidor falla silenciosament |
| Certificat wildcard rebutjat per Let's Encrypt amb el mètode webroot | Els wildcards només es poden validar amb el mètode DNS-01 |
Error important una clau .pfx a Apache/Nginx directament |
Apache/Nginx esperen PEM; cal convertir el .pfx amb openssl pkcs12 primer |
Referències
Documentació oficial de Let's Encrypt, Certbot i OpenSSL: consulta la secció Serveis Web a la pàgina d'Annexos · Recursos.