Salta el contingut

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:

  1. El servidor genera la parella de claus (privada + pública).
  2. 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.
  3. Es passa la CSR a la CA.
  4. 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.

    -----BEGIN CERTIFICATE-----
    MIIDXTCCAkWgAwIBAgIJAKL...
    -----END CERTIFICATE-----
    

    Una clau privada en PEM comença per -----BEGIN PRIVATE KEY----- (o RSA PRIVATE KEY en 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:

sudo certbot certonly --webroot -w /var/www/exemple -d exemple.cat -d www.exemple.cat

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
#!/bin/bash
# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
systemctl reload nginx

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.