SSL Labs (de Qualys) es el test público más usado para evaluar la configuración TLS de un servidor web. Asigna una nota de A+ a F según los protocolos, cifrados, certificado y cabeceras que ofrece tu sitio. En esta guía configurarás Nginx o Apache en Ubuntu 24.04 con un certificado de Let's Encrypt, TLS 1.2 y 1.3 con cifrados modernos y la cabecera HSTS, que es lo que separa una A de una A+, y comprobarás el resultado en SSL Labs.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con un usuario no root con privilegios
sudo. - Nginx o Apache instalado y sirviendo tu sitio por HTTP.
- Un dominio (
your_domainen los ejemplos) con registros A (y AAAA si usas IPv6) apuntando al servidor. Si tieneswww, también debe apuntar al servidor. - Puertos 80 y 443 abiertos. Con UFW:
sudo ufw allow 'Nginx Full'
Si usas Apache, el perfil es 'Apache Full'.
Qué necesita una A+
SSL Labs parte de una puntuación numérica y después aplica límites que bajan la nota ante problemas concretos. Para llegar a A+ necesitas:
| Requisito | Qué pasa si falta |
|---|---|
| Certificado válido, cadena completa y nombre correcto | Nota T o F |
| Sin SSL 3, TLS 1.0 ni TLS 1.1 | Limitado a B (C o F si hay SSL 3) |
| Secreto hacia adelante (ECDHE) en todas las suites | Limitado a B |
| Sin cifrados inseguros (RC4, 3DES, NULL, EXPORT) | Limitado a B, C o F |
| Soporte de TLS 1.3 | Recomendado; los servidores modernos lo tienen por defecto |
Cabecera HSTS con max-age de al menos 6 meses | Se queda en A |
El OCSP stapling, las cabeceras como CSP o X-Frame-Options y el preload de HSTS no forman parte de la nota. Son buenas prácticas, pero no hace falta nada de eso para la A+.
Paso 1: Obtener un certificado ECDSA con Certbot
Instala Certbot con el plugin de tu servidor web:
sudo apt update
sudo apt install certbot python3-certbot-nginx
Para Apache, instala python3-certbot-apache en lugar de python3-certbot-nginx.
Desde la versión 2.0, Certbot genera por defecto claves ECDSA P-256, más pequeñas y rápidas que RSA 2048 con una seguridad equivalente o mayor. Ubuntu 24.04 trae Certbot 2.9, así que no necesitas opciones extra. Solicita el certificado solo (certonly) para que Certbot no modifique la configuración TLS del sitio; la escribirás tú en el paso 2:
sudo certbot certonly --nginx -d your_domain -d www.your_domain
Con Apache, usa --apache en lugar de --nginx.
Comprueba el tipo de clave:
sudo openssl x509 -in /etc/letsencrypt/live/your_domain/cert.pem -noout -text | grep 'Public Key Algorithm'
Public Key Algorithm: id-ecPublicKey
El paquete de Certbot instala un temporizador de systemd que renueva los certificados automáticamente. Verifica que está activo:
systemctl list-timers certbot.timer
Paso 2: Configurar TLS y HSTS en Nginx
En Ubuntu, /etc/nginx/nginx.conf ya activa TLS 1.0 y 1.1 en su sección SSL Settings, y eso limitaría la nota a B. Edítalo:
sudo nano /etc/nginx/nginx.conf
Deja la sección SSL Settings del bloque http así:
##
# SSL Settings
##
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_ecdh_curve X25519:prime256v1:secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
Estos cifrados solo usan ECDHE (secreto hacia adelante) con AES-GCM o ChaCha20, y ninguno aparece como débil en SSL Labs. ssl_ciphers no afecta a TLS 1.3, que usa las suites seguras de OpenSSL por defecto.
Ahora crea o sustituye la configuración del sitio:
sudo nano /etc/nginx/sites-available/your_domain
server {
listen 80;
listen [::]:80;
server_name your_domain www.your_domain;
return 301 https://your_domain$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your_domain www.your_domain;
ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/your_domain;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Puntos importantes:
fullchain.pemincluye el certificado intermedio. Si usascert.pem, la cadena queda incompleta y SSL Labs lo penaliza.max-age=31536000es un año, por encima de los 6 meses que exige la A+.alwayshace que la cabecera se envíe también en respuestas de error.includeSubDomainsobliga a usar HTTPS en todos los subdominios. Quítalo si alguno sigue sirviendo solo HTTP.- En Nginx, un
add_headerdentro de un bloquelocationanula todos losadd_headerdel bloqueserver. Si añades cabeceras en unlocation, repite ahí la de HSTS.
Activa el sitio si es nuevo, comprueba la sintaxis y recarga:
sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Paso 3 (alternativa): Configurar TLS y HSTS en Apache
Si usas Apache, activa los módulos necesarios:
sudo a2enmod ssl headers
Crea un archivo global con la política TLS. Se carga después de mods-available/ssl.conf y sustituye sus valores:
sudo nano /etc/apache2/conf-available/tls-modern.conf
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLHonorCipherOrder off
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
SSLOpenSSLConfCmd Curves X25519:prime256v1:secp384r1
SSLSessionTickets off
sudo a2enconf tls-modern
Crea el sitio con la redirección y el VirtualHost HTTPS:
sudo nano /etc/apache2/sites-available/your_domain.conf
<VirtualHost *:80>
ServerName your_domain
ServerAlias www.your_domain
Redirect permanent / https://your_domain/
</VirtualHost>
<VirtualHost *:443>
ServerName your_domain
ServerAlias www.your_domain
DocumentRoot /var/www/your_domain
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/your_domain/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/your_domain/privkey.pem
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
ErrorLog ${APACHE_LOG_DIR}/your_domain_error.log
CustomLog ${APACHE_LOG_DIR}/your_domain_access.log combined
</VirtualHost>
Actívalo, comprueba y recarga:
sudo a2ensite your_domain
sudo apache2ctl configtest
sudo systemctl reload apache2
Syntax OK
Paso 4: Comprobar la configuración antes del test
SSL Labs tarda un par de minutos, así que conviene verificar lo básico antes desde el servidor.
La redirección de HTTP a HTTPS:
curl -sI http://your_domain | grep -iE '^(HTTP|location)'
HTTP/1.1 301 Moved Permanently
Location: https://your_domain/
La cabecera HSTS en HTTPS:
curl -sI https://your_domain | grep -i strict-transport-security
strict-transport-security: max-age=31536000; includeSubDomains
El protocolo y la cadena de certificados:
openssl s_client -connect your_domain:443 -servername your_domain < /dev/null 2>/dev/null | grep -E 'Verify return code|^New'
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Verify return code: 0 (ok)
Un código distinto de 0 (ok) indica un problema de cadena o de nombre que SSL Labs también detectará.
Paso 5: Ejecutar el test de SSL Labs
Abre https://www.ssllabs.com/ssltest/, escribe tu dominio y marca Do not show the results on the boards si no quieres que aparezca en el listado público. El análisis tarda entre uno y tres minutos y prueba cada dirección IP del dominio por separado (IPv4 e IPv6), así que ambas deben tener la misma configuración.
El resumen debe mostrar Overall Rating: A+. En la sección de detalles verás:
- Protocols: TLS 1.3 y TLS 1.2 en
Yes; TLS 1.1, TLS 1.0, SSL 3 y SSL 2 enNo. - Cipher Suites: ninguna marcada como
WEAK. - HTTP Strict Transport Security (HSTS):
Yescon elmax-ageque configuraste.
Si repites el test tras un cambio, pulsa Clear cache en la página de resultados; si no, SSL Labs muestra el análisis anterior.
Sobre el preload de HSTS
El preload de HSTS (añadir preload a la cabecera y registrar el dominio en hstspreload.org) hace que los navegadores usen HTTPS desde la primera visita. No sube la nota y es difícil de deshacer: salir de la lista tarda meses y, mientras tanto, cualquier subdominio sin HTTPS deja de ser accesible. Actívalo solo cuando estés seguro de que todo el dominio, incluidos los subdominios, funciona por HTTPS y exige max-age de al menos un año.
Solución de problemas
Nota B con el aviso "This server supports TLS 1.0 and TLS 1.1". Otra configuración vuelve a activar esos protocolos. En Nginx suele ser include /etc/letsencrypt/options-ssl-nginx.conf; en el bloque server o un sitio default que escucha en el mismo puerto. Búscalos:
sudo grep -rnE 'ssl_protocols|SSLProtocol|options-ssl' /etc/nginx /etc/apache2
Se queda en A y SSL Labs no detecta HSTS. Comprueba con curl -sI https://your_domain que la cabecera sale en la respuesta de la raíz. En Nginx, revisa si algún location tiene su propio add_header. En Apache, confirma que el módulo headers está activo con apache2ctl -M | grep headers.
"Chain issues: Incomplete". El servidor no envía el intermedio. Usa fullchain.pem en ssl_certificate o en SSLCertificateFile.
Nota distinta en IPv4 e IPv6. El registro AAAA apunta a otra máquina o Nginx no tiene listen [::]:443. Corrige el DNS o la directiva listen.
Conclusión
Has configurado un certificado ECDSA de Let's Encrypt con renovación automática, limitado el servidor a TLS 1.2 y 1.3 con cifrados que ofrecen secreto hacia adelante, forzado HTTPS y añadido la cabecera HSTS, que es el último requisito para la A+. Como siguientes pasos, puedes añadir cabeceras de seguridad (Content-Security-Policy, X-Content-Type-Options) y revisarlas en securityheaders.com, y repetir el test de SSL Labs tras cada cambio de configuración o de certificado.