Cómo funcionan realmente HTTPS y TLS: Guía práctica
Por qué HTTPS es importante y qué hace realmente
Probablemente hayas visto el icono del candado en tu navegador y asumido que tu conexión es segura. Pero, ¿qué garantiza realmente ese candado? HTTPS (Hypertext Transfer Protocol Secure) es HTTP sobre TLS (Transport Layer Security). Proporciona tres garantías fundamentales: confidencialidad (los espías no pueden leer los datos), integridad (los datos no pueden modificarse en tránsito sin ser detectados) y autenticación (estás hablando con el servidor real, no con un impostor).
Sin HTTPS, cualquiera en la ruta de red—Wi-Fi de una cafetería, tu ISP o un router malicioso—puede leer o alterar tu tráfico. Con HTTPS, eso se vuelve impráctico. Pero TLS no es magia; es un protocolo cuidadosamente diseñado con pasos específicos. Comprender esos pasos te ayuda a depurar problemas de conexión, configurar servidores correctamente y evitar errores comunes.
El handshake TLS: paso a paso
Cuando tu navegador se conecta a un sitio HTTPS, realiza un handshake TLS antes de que se intercambie cualquier dato HTTP. Esto es lo que sucede en un handshake TLS 1.3 típico (el estándar moderno):
- ClientHello: El cliente envía un mensaje con las versiones de TLS compatibles, los conjuntos de cifrado y un valor aleatorio (client random). También incluye un key share para el intercambio de claves (por ejemplo, usando ECDHE).
- ServerHello: El servidor responde con la versión de TLS elegida, el conjunto de cifrado, un valor aleatorio (server random) y su propio key share. También envía su cadena de certificados.
- Verificación del certificado: El cliente valida el certificado del servidor contra las CA raíz de confianza, comprueba el nombre de host y asegura que no haya expirado ni haya sido revocado.
- Derivación de claves: Ambos lados calculan el mismo secreto compartido usando sus claves privadas y los key shares intercambiados. A partir de esto, derivan claves de sesión simétricas.
- Finished: Ambos lados envían un mensaje Finished cifrado con las claves de sesión para verificar la integridad del handshake.
Después del handshake, todos los datos de la aplicación (solicitudes y respuestas HTTP) se cifran con las claves de sesión simétricas. TLS 1.3 reduce el handshake a un solo viaje de ida y vuelta (1-RTT) y admite la reanudación 0-RTT para conexiones repetidas, mejorando la latencia.
Certificados y cadenas de confianza
Un certificado es un documento digital que vincula una clave pública a una identidad (como un nombre de dominio). Está firmado por una Autoridad de Certificación (CA). Tu navegador y sistema operativo incluyen un almacén de CA raíz de confianza. Cuando un servidor presenta su certificado, el cliente construye una cadena desde el certificado del servidor hasta una raíz de confianza. Si falta algún eslabón o no es válido, la conexión falla.
Los problemas comunes de certificados incluyen:
- Certificado expirado: El período de validez ha pasado.
- Nombre de host no coincide: El certificado es para un dominio diferente (por ejemplo,
example.comvswww.example.com). - Cadena incompleta: El servidor no envió los certificados intermedios, por lo que el cliente no puede construir una ruta hasta una raíz de confianza.
- Emisor no confiable: El certificado es autofirmado o de una CA que no está en el almacén de confianza.
Herramientas como OpenSSL pueden ayudarte a inspeccionar certificados. Por ejemplo, para ver la cadena de certificados que envía un servidor:
openssl s_client -connect example.com:443 -showcerts
Este comando imprime los certificados y el resultado de la verificación. Busca Verify return code: 0 (ok) para confirmar que la cadena es válida.
Depuración de conexiones TLS
Cuando HTTPS falla, el mensaje de error a menudo apunta a la fase que se rompió. Aquí tienes una tabla rápida de solución de problemas:
| Síntoma | Causa probable | Acción |
|---|---|---|
| El navegador muestra "certificado expirado" | Certificado pasado de su fecha de expiración | Renueva el certificado y recarga el servidor |
| "NET::ERR_CERT_COMMON_NAME_INVALID" | Nombre de host no coincide | Asegúrate de que el certificado cubra el dominio exacto (incluyendo www si es necesario) |
| "unable to get local issuer certificate" | Faltan certificados intermedios | Configura el servidor para enviar la cadena completa |
| El handshake falla con error de protocolo | El cliente y el servidor no tienen una versión de TLS o cifrado en común | Actualiza la configuración del servidor para admitir TLS moderno (1.2+) |
Para una inspección más profunda, usa openssl s_client con flags como -tls1_3 para probar versiones específicas, o curl -v https://example.com para ver los detalles del handshake. Las herramientas de desarrollo del navegador (pestaña Seguridad) también muestran información del certificado y detalles de la conexión.
Mejores prácticas para la configuración del servidor
Una configuración TLS adecuada es crucial para la seguridad y el rendimiento. Sigue estas pautas:
- Usa solo TLS 1.3 y 1.2: Deshabilita versiones anteriores (TLS 1.0, 1.1) que tienen vulnerabilidades conocidas.
- Habilita HTTP/2 o HTTP/3: Estos protocolos requieren TLS y ofrecen beneficios de rendimiento.
- Usa conjuntos de cifrado fuertes: Prefiere cifrados AEAD como AES-GCM o ChaCha20-Poly1305.
- Habilita OCSP stapling: Reduce la latencia y mejora la privacidad en las comprobaciones de revocación.
- Implementa HSTS: El encabezado
Strict-Transport-Securityindica a los navegadores que siempre usen HTTPS para tu dominio. - Automatiza la renovación de certificados: Usa Let's Encrypt con Certbot o similar para evitar la expiración.
Aquí tienes un fragmento de configuración de Nginx para TLS moderno:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
}
Después de aplicar los cambios, prueba tu configuración con herramientas como SSL Labs' SSL Test (en línea) o openssl s_client para verificar el handshake y la cadena de certificados.
Preguntas frecuentes
¿Cuál es la diferencia entre TLS y SSL?
SSL (Secure Sockets Layer) es el predecesor de TLS. Las versiones SSL 2.0 y 3.0 están obsoletas debido a fallos de seguridad. TLS 1.2 y 1.3 son los protocolos modernos y seguros. La gente suele decir "SSL" coloquialmente, pero se refieren a TLS.
¿Cómo protege HTTPS contra ataques de intermediario (man-in-the-middle)?
HTTPS utiliza certificados firmados por CA de confianza para autenticar el servidor. Durante el handshake, el cliente verifica el certificado del servidor y comprueba que la clave pública del certificado coincida con la utilizada en el intercambio de claves. Esto evita que un atacante se haga pasar por el servidor sin un certificado válido.
¿Puedo usar HTTPS sin certificado?
No. Se requiere un certificado para que el servidor demuestre su identidad y para que el cliente establezca un canal cifrado. Puedes usar un certificado autofirmado para pruebas, pero los navegadores mostrarán una advertencia porque no es de confianza para las CA públicas. Para producción, usa un certificado de una CA de confianza como Let's Encrypt.
Cuando trabajes con configuraciones TLS, es posible que necesites inspeccionar registros del servidor o probar endpoints. Para un análisis rápido de los registros de acceso de Nginx y detectar errores TLS o patrones inusuales, prueba el Analizador de Registros de Nginx para parsear y visualizar datos de registro sin esfuerzo.