Saltar al contenido

Acerca de HTTPS

Es fácil asumir que HTTPS es algo que simplemente está "activado" o no.

Pero es mucho más complejo que eso.

Consejo

Si tienes prisa o no te importa, continúa con las siguientes secciones para instrucciones paso a paso sobre cómo configurar todo con diferentes técnicas.

Para aprender los conceptos básicos de HTTPS, desde la perspectiva de un consumidor, revisa https://howhttps.works/.

Ahora, desde la perspectiva de un desarrollador, aquí hay varias cosas a tener en cuenta al pensar en HTTPS:

  • For HTTPS, the server needs to have "certificates" generated by a third party.
    • Esos certificados en realidad se adquieren de un tercero, no se "generan".
  • Certificates have a lifetime.
    • Expiran.
    • Y luego necesitan ser renovados, adquiridos nuevamente del tercero.
  • The encryption of the connection happens at the TCP level.
    • Eso es una capa por debajo de HTTP.
    • Por lo tanto, el manejo del certificado y la encriptación se hace antes de HTTP.
  • TCP doesn't know about "domains". Only about IP addresses.
    • La información sobre el dominio específico solicitado va en los datos HTTP.
  • Los certificados HTTPS "certifican" un dominio en particular, pero el protocolo y la encriptación ocurren a nivel TCP, antes de saber con qué dominio se está tratando.
  • By default, that would mean that you can only have one HTTPS certificate per IP address.
    • No importa cuán grande sea tu servidor o cuán pequeña sea cada aplicación que tengas en él.
    • Hay una solución para esto, sin embargo.
  • There's an extension to the TLS protocol (the one handling the encryption at the TCP level, before HTTP) called SNI.
    • Esta extensión SNI permite que un solo servidor (con una única dirección IP) tenga varios certificados HTTPS y sirva múltiples dominios/aplicaciones HTTPS.
    • Para que esto funcione, un único componente (programa) ejecutándose en el servidor, escuchando en la dirección IP pública, debe tener todos los certificados HTTPS en el servidor.
  • After obtaining a secure connection, the communication protocol is still HTTP.
    • Los contenidos están encriptados, aunque se estén enviando con el protocolo HTTP.

Es una práctica común tener un programa/servidor HTTP ejecutándose en el servidor (la máquina, host, etc.) y manejando todas las partes de HTTPS: recibir las peticiones HTTPS encriptadas, enviar las peticiones HTTP desencriptadas a la aplicación HTTP real ejecutándose en el mismo servidor (la aplicación FastAPI, en este caso), tomar la respuesta HTTP de la aplicación, encriptarla usando el certificado HTTPS apropiado y enviarla de vuelta al cliente usando HTTPS. A este servidor se le suele llamar TLS Termination Proxy.

Algunas de las opciones que podrías usar como TLS Termination Proxy son:

  • Traefik (que también puede manejar renovaciones de certificados)
  • Caddy (que también puede manejar renovaciones de certificados)
  • Nginx
  • HAProxy

Let's Encrypt

Antes de Let's Encrypt, estos certificados HTTPS eran vendidos por terceros de confianza.

El proceso para adquirir uno de estos certificados solía ser engorroso, requerir bastante papeleo y los certificados eran bastante caros.

Pero entonces se creó Let's Encrypt.

Es un proyecto de la Linux Foundation. Proporciona certificados HTTPS de forma gratuita, de manera automatizada. Estos certificados usan toda la seguridad criptográfica estándar, y son de corta duración (unos 3 meses), por lo que la seguridad es realmente mejor debido a su vida útil reducida.

Los dominios son verificados de forma segura y los certificados se generan automáticamente. Esto también permite automatizar la renovación de estos certificados.

La idea es automatizar la adquisición y renovación de estos certificados para que puedas tener HTTPS seguro, gratis, para siempre.

HTTPS para Desarrolladores

Aquí hay un ejemplo de cómo podría verse una API HTTPS, paso a paso, prestando atención principalmente a las ideas importantes para los desarrolladores.

Nombre de Dominio

Probablemente todo empezaría por ti adquiriendo algún nombre de dominio. Luego, lo configurarías en un servidor DNS (posiblemente tu mismo proveedor de nube).

Probablemente obtendrías un servidor en la nube (una máquina virtual) o algo similar, y tendría una dirección IP pública fija.

En el/los servidor(es) DNS configurarías un registro (un "registro A") para apuntar tu dominio a la dirección IP pública de tu servidor.

Probablemente harías esto solo una vez, la primera vez, al configurar todo.

Consejo

Esta parte del Nombre de Dominio está mucho antes que HTTPS, pero como todo depende del dominio y de la dirección IP, vale la pena mencionarlo aquí.

DNS

Ahora concentrémonos en todas las partes reales de HTTPS.

Primero, el navegador consultaría con los servidores DNS cuál es la IP del dominio, en este caso, someapp.example.com.

Los servidores DNS le dirían al navegador que use alguna dirección IP específica. Esa sería la dirección IP pública usada por tu servidor, que configuraste en los servidores DNS.

Inicio del Handshake TLS

El navegador entonces se comunicaría con esa dirección IP en el puerto 443 (el puerto HTTPS).

La primera parte de la comunicación es simplemente establecer la conexión entre el cliente y el servidor y decidir las claves criptográficas que usarán, etc.

Esta interacción entre el cliente y el servidor para establecer la conexión TLS se llama el handshake TLS.

TLS con la Extensión SNI

Solo un proceso en el servidor puede estar escuchando en un puerto específico en una dirección IP específica. Puede haber otros procesos escuchando en otros puertos en la misma dirección IP, pero solo uno por cada combinación de dirección IP y puerto.

TLS (HTTPS) usa el puerto específico 443 por defecto. Así que ese es el puerto que necesitaríamos.

Como solo un proceso puede estar escuchando en este puerto, el proceso que lo haría sería el TLS Termination Proxy.

El TLS Termination Proxy tendría acceso a uno o más certificados TLS (certificados HTTPS).

Usando la extensión SNI discutida arriba, el TLS Termination Proxy verificaría cuál de los certificados TLS (HTTPS) disponibles debería usar para esta conexión, usando el que coincida con el dominio esperado por el cliente.

En este caso, usaría el certificado para someapp.example.com.

El cliente ya confía en la entidad que generó ese certificado TLS (en este caso Let's Encrypt, pero veremos eso más adelante), por lo que puede verificar que el certificado es válido.

Luego, usando el certificado, el cliente y el TLS Termination Proxy deciden cómo encriptar el resto de la comunicación TCP. Esto completa la parte del Handshake TLS.

Después de esto, el cliente y el servidor tienen una conexión TCP encriptada, esto es lo que proporciona TLS. Y luego pueden usar esa conexión para iniciar la comunicación HTTP real.

Y eso es lo que es HTTPS, es simplemente HTTP plano dentro de una conexión TLS segura en lugar de una conexión TCP pura (sin encriptar).

Consejo

Ten en cuenta que la encriptación de la comunicación ocurre a nivel TCP, no a nivel HTTP.

Petición HTTPS

Ahora que el cliente y el servidor (específicamente el navegador y el TLS Termination Proxy) tienen una conexión TCP encriptada, pueden iniciar la comunicación HTTP.

Así que, el cliente envía una petición HTTPS. Esto es simplemente una petición HTTP a través de una conexión TLS encriptada.

Desencriptar la Petición

El TLS Termination Proxy usaría la encriptación acordada para desencriptar la petición, y transmitiría la petición HTTP plana (desencriptada) al proceso que ejecuta la aplicación (por ejemplo, un proceso con Uvicorn ejecutando la aplicación FastAPI).

Respuesta HTTP

La aplicación procesaría la petición y enviaría una respuesta HTTP plana (sin encriptar) al TLS Termination Proxy.

Respuesta HTTPS

El TLS Termination Proxy entonces encriptaría la respuesta usando la criptografía acordada previamente (que comenzó con el certificado para someapp.example.com), y la enviaría de vuelta al navegador.

Luego, el navegador verificaría que la respuesta es válida y está encriptada con la clave criptográfica correcta, etc. Entonces desencriptaría la respuesta y la procesaría.

El cliente (navegador) sabrá que la respuesta viene del servidor correcto porque está usando la criptografía que acordaron usando el certificado HTTPS previamente.

Múltiples Aplicaciones

En el mismo servidor (o servidores), podría haber múltiples aplicaciones, por ejemplo, otros programas de API o una base de datos.

Solo un proceso puede estar manejando el IP y puerto específicos (el TLS Termination Proxy en nuestro ejemplo) pero las otras aplicaciones/procesos pueden estar ejecutándose en el/los servidor(es) también, siempre y cuando no intenten usar la misma combinación de IP pública y puerto.

De esa manera, el TLS Termination Proxy podría manejar HTTPS y certificados para múltiples dominios, para múltiples aplicaciones, y luego transmitir las peticiones a la aplicación correcta en cada caso.

Renovación de Certificados

En algún punto en el futuro, cada certificado expiraría (unos 3 meses después de adquirirlo).

Y luego, habría otro programa (en algunos casos es otro programa, en algunos casos podría ser el mismo TLS Termination Proxy) que hablaría con Let's Encrypt, y renovaría el/los certificado(s).

Los certificados TLS están asociados con un nombre de dominio, no con una dirección IP.

Así que, para renovar los certificados, el programa de renovación necesita probar a la autoridad (Let's Encrypt) que efectivamente "posee" y controla ese dominio.

Para hacer eso, y para acomodar las diferentes necesidades de las aplicaciones, hay varias formas en las que puede hacerlo. Algunas formas populares son:

  • Modify some DNS records.
    • Para esto, el programa de renovación necesita soportar las APIs del proveedor de DNS, por lo que, dependiendo del proveedor de DNS que estés usando, esto podría ser o no una opción.
  • Run as a server (at least during the certificate acquisition process) on the public IP address associated with the domain.
    • Como dijimos arriba, solo un proceso puede estar escuchando en un IP y puerto específicos.
    • Esta es una de las razones por las que es muy útil cuando el mismo TLS Termination Proxy también se encarga del proceso de renovación de certificados.
    • De lo contrario, podrías tener que detener el TLS Termination Proxy momentáneamente, iniciar el programa de renovación para adquirir los certificados, luego configurarlos con el TLS Termination Proxy, y luego reiniciar el TLS Termination Proxy. Esto no es ideal, ya que tu(s) aplicación(es) no estarán disponibles durante el tiempo que el TLS Termination Proxy esté apagado.

Todo este proceso de renovación, mientras se sigue sirviendo la aplicación, es una de las principales razones por las que querrías tener un sistema separado para manejar HTTPS con un TLS Termination Proxy en lugar de simplemente usar los certificados TLS con el servidor de aplicaciones directamente (ej. Uvicorn).

Headers de Proxy Reenviados

Cuando usas un proxy para manejar HTTPS, tu servidor de aplicaciones (por ejemplo Uvicorn vía FastAPI CLI) no sabe nada sobre el proceso HTTPS, se comunica con HTTP plano con el TLS Termination Proxy.

Este proxy normalmente establecería algunos encabezados HTTP al vuelo antes de transmitir la petición al servidor de aplicaciones, para hacerle saber al servidor de aplicaciones que la petición está siendo reenviada por el proxy.

Detalles Técnicos

Los headers del proxy son:

Sin embargo, como el servidor de aplicaciones no sabe que está detrás de un proxy de confianza, por defecto no confiaría en esos encabezados.

Pero puedes configurar el servidor de aplicaciones para que confíe en los encabezados reenviados enviados por el proxy. Si estás usando FastAPI CLI, puedes usar la Opción del CLI --forwarded-allow-ips para indicarle desde qué IPs debería confiar en esos encabezados reenviados.

Por ejemplo, si el servidor de aplicaciones solo está recibiendo comunicación del proxy de confianza, puedes configurarlo con --forwarded-allow-ips="*" para que confíe en todas las IPs entrantes, ya que solo recibirá peticiones de cualquiera que sea la IP usada por el proxy.

De esta manera la aplicación podría saber cuál es su propia URL pública, si está usando HTTPS, el dominio, etc.

Esto sería útil por ejemplo para manejar correctamente las redirecciones.

Consejo

Puedes aprender más sobre esto en la documentación de Detrás de un Proxy - Habilitar Encabezados Reenviados del Proxy

Resumen

Tener HTTPS es muy importante, y bastante crítico en la mayoría de los casos. La mayor parte del esfuerzo que como desarrollador tienes que poner alrededor de HTTPS se trata simplemente de entender estos conceptos y cómo funcionan.

Pero una vez que conoces la información básica sobre HTTPS para desarrolladores puedes combinar y configurar fácilmente diferentes herramientas para ayudarte a gestionar todo de una manera sencilla.

En algunos de los próximos capítulos, te mostraré varios ejemplos concretos de cómo configurar HTTPS para aplicaciones FastAPI. 🔒