Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Permitir tráfico saliente por dominio

By Joshua FoxAug 28, 20237 min read

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

Cuando construyes una aplicación segura, lo habitual es bloquearle el permiso para conectarse fuera de su Virtual Private Cloud (VPC). Pero a veces necesitas abrir un poco la puerta, por ejemplo, si tu aplicación tiene que llegar a una API de terceros.

Gateway to Domain, al estilo Lovecraft. Crédito: StableDiffusion

Lo habitual es permitir el egress únicamente hacia las direcciones IP relevantes, ya sea con el Firewall de Google Cloud Platform o con Network ACLs en AWS. Sin embargo, las direcciones IP pueden cambiar con el tiempo, mientras que el Fully Qualified Domain Name (FQDN), por ejemplo api.example.com, ofrece un endpoint estable y conocido públicamente. Por eso, la mayoría de las aplicaciones se configuran para acceder a un FQDN y no a una dirección IP.

En este artículo voy a repasar las distintas formas de permitir el egress únicamente hacia un FQDN específico, con las ventajas y desventajas de cada enfoque.

Buscaremos opciones económicas, fáciles de mantener, robustas y simples.

También revisaremos opciones con la ventaja adicional de Kubernetes-awareness: si tu aplicación corre en Kubernetes, por ejemplo, quizá quieras permitir el egress desde un namespace de Kubernetes en concreto y no desde otros.

También puede interesarte la granularidad a nivel de dominio, ya que una misma dirección IP puede dar la cara por varios dominios, como ocurre con el virtual hosting basado en nombre. La mayoría de las soluciones que veremos aquí no contemplan ese caso: si permites el acceso a un dominio asociado a una IP determinada, también se habilita el egress hacia todos los dominios que están detrás de esa misma dirección. Presentaremos algunas soluciones que sí lo soportan.

Las opciones que reviso aquí son:

  • Squid, como ejemplo de proxy autoadministrado
  • AWS Network Firewall, con deep packet inspection, que permite el control a nivel de dominio, incluso con virtual hosting.
  • Una nueva funcionalidad de Google Firewall, que ofrece control de FQDN con la comodidad de un servicio serverless.
  • El nuevo Google Secure Web Gateway, que añade control granular hasta el nivel del dominio e incluso de la URL.
  • Soluciones con Kubernetes-awareness: Cilium e Istio.

(Una nota sobre las capas OSI: como los nombres de dominio y el DNS están en la "capa de aplicación" del modelo de red OSI, capa 7, al control de egress por FQDN a veces se le llama "control de egress de capa 7". En cambio, la capa 3 es donde se definen las direcciones IP y se controla mediante los firewalls clásicos o las Network ACLs).

Implementarlo por tu cuenta

Primero, veamos cómo podríamos implementarlo nosotros mismos. No es algo que recomiende, pero ayuda a entender qué hacen estas soluciones por debajo.

Aunque la aplicación esté configurada con el FQDN de la API de terceros, los nombres de dominio solo son relevantes antes de intentar la conexión, cuando el cliente busca la dirección IP a partir del nombre de dominio. A partir de ahí, el tráfico de red usa direcciones IP, que es lo que tu solución necesita bloquear.

Ten en cuenta también que un mismo FQDN puede corresponder a varias direcciones IP. Esto no es problema, ya que una consulta DNS normal las devuelve todas, y así puedes permitir el acceso a una lista de direcciones IP.

Tienes un Firewall o una Network ACL que bloquea todo el tráfico salvo el dirigido a las direcciones IP relevantes.

Escribes y despliegas una aplicación que consulta el DNS periódicamente para obtener la dirección IP actual del FQDN de la API, api.example.com. (Una buena opción para correr esto a bajo costo es GCP Cloud Functions o AWS Lambda con un trigger periódico). En los pocos casos en los que la dirección IP haya cambiado, tu aplicación actualiza el Firewall o la Network ACL.

Reverse web proxies autoadministrados

Una solución "clásica" para el control de egress por FQDN es un reverse web proxy, donde Squid es la opción open source más conocida. Usas el servicio de routing de tu nube para dirigir todo el tráfico saliente a través de una VM que ejecuta el proxy Squid; este verifica que la dirección IP coincida con el nombre de dominio —según se haya configurado en una whitelist ACL— y lo retransmite si hay coincidencia.

Squid está disponible en AWS Marketplace; revisa esta discusión de arquitectura. También está disponible en GCP Marketplace; revisa esta configuración de red. Te recomiendo también esta discusión sobre el control de egress por FQDN en Squid y otros proxies, como DiscrimiNAT y Aviatrix.

Los proxies como Squid corriendo en una VM implican una carga de mantenimiento: hay que actualizar los sistemas operativos de las VMs y lidiar con las caídas, por ejemplo. Como todo el flujo de tráfico de red pasa por una sola VM (a menos que te tomes el trabajo extra de configurar un despliegue con balanceo de carga), la carga puede ser pesada, lo que pone en riesgo la robustez y puede obligarte a pagar una VM más grande corriendo 24x7, incluso cuando no se aprovecha al máximo.

AWS Network Firewall

AWS Network Firewall hace deep packet inspection, lo que le da más capacidad de filtrado. Esto significa que no es del todo comparable con Google Firewall, que se parece más a las AWS Network ACLs.

AWS Network Firewall soporta el control de egress por FQDN mediante stateful domain list rule groups. Gracias al Server Name Indicator (SNI) que se envía al negociar una conexión TCP para tráfico HTTPS, puede distinguir entre dominios en escenarios de virtual hosting.

Network Firewall puede integrarse con Route 53 DNS Firewall, que bloquea los intentos de resolución DNS, de modo que, por ejemplo, una consulta DNS a api.example.com desde una aplicación dentro de la VPC no resuelve a una dirección IP. Pero el DNS Firewall en realidad no impide el acceso a esa dirección IP; eso lo hace Network Firewall.

Network Firewall es una buena opción, aunque puede salir caro: está pensado para entornos empresariales complejos con varias redes. (Revisa mi artículo en el DoiT Blog donde comparo los casos de uso de los muchos servicios tipo Firewall en AWS).

Google Firewall y Web Gateway

Es más fácil usar una solución totalmente administrada por el proveedor de la nube que gestionar la VM por tu cuenta. Y Google está sacando justo ahora algunas soluciones que lo hacen posible.

Google Firewall tiene una nueva funcionalidad de FQDN Objects, hoy en Preview limitada. Usa Cloud DNS cada 30 segundos para consultar la dirección IP actual del servicio externo.

Otro servicio en Preview limitada, Secure Web Gateway (renombrado como Secure Web Proxy), también permite control a nivel de dominio. Para lograrlo, le das acceso a tus certificados SSL en GCP Certificate Manager, de modo que pueda descifrar y cifrar tu tráfico HTTPS. Este acceso profundo le permite controlar el egress a nivel de dominio, incluso en escenarios de virtual hosting. Y como ve la solicitud HTTP completa, también te permite controlarlo a nivel de URL.

Cilium

Las soluciones anteriores trabajan a nivel de VPC. Pero si tu aplicación corre en Kubernetes, quizá quieras que el control de egress se entienda con los conceptos de Kubernetes. Para eso puedes introducir CiliumNetworkPolicy, una Custom Resource Definition (CRD) que ejecuta la lógica de resolver nombres de dominio a direcciones IP y luego bloquea o permite el tráfico en la capa de red de Cilium basada en eBPF. (Revisa dos posts en el DoiT blog). La CRD tiene Kubernetes-awareness, así que puedes distinguir pods por namespace: algunos con acceso permitido a la API externa, otros sin él. Otra CRD, CiliumClusterwideNetworkPolicy, hace lo mismo, pero su configuración aplica de forma transversal a todos los namespaces, es decir, a todo el cluster.

Esta solución agrega algo de complejidad al cluster por la capa de red adicional de Cilium. Pronto, según se indica en la documentación de Cilium, "toda la funcionalidad se fusionará en el formato de recurso estándar y esta CRD dejará de ser necesaria". Aunque todavía no hay una especificación estándar disponible, el Kubernetes Networking Special Interest Group ya está trabajando en ella.

Istio

La solución más completa la ofrece el service mesh de Istio. Istio controla el tráfico por completo y te permite bloquear todo el egress, salvo lo que se defina en un ServiceEntry. Cuando especificas resolution: DNS, le pides a Istio que no se base en la dirección IP a la que se conecta el cliente (un pod), sino que resuelva el nombre de dominio periódicamente vía DNS. El servicio de Istio puede exponerse solo a los namespaces que elijas. Istio te da el mayor nivel de control, aunque suma más complejidad que Cilium, con toda la potencia y funcionalidad de una capa de service mesh.

¿Qué hacer?

Tienes varias opciones: el probadísimo Squid (u otro reverse web proxy); los nuevos servicios administrados, Google Firewall FQDN Objects y AWS Network Firewall; el Secure Web Gateway que actúa como proxy HTTP; y, además, Cilium e Istio con Kubernetes-awareness.

Si quieres una solución estable y administrada, mi recomendación es ir con el nuevo Google Firewall (cuando madure) y AWS Network Firewall (si los precios entran en tu presupuesto). Si necesitas control a nivel de namespaces de Kubernetes, la solución más simple es una CRD de Cilium; cuando salga el estándar nativo de Kubernetes, ve por ese.

Apéndice

Agosto de 2023: mi colega

publicó recientemente artículos en profundidad sobre varios de estos temas, que reflejan los nuevos lanzamientos de Google de lo que era alpha cuando escribí este artículo, y dan más detalle técnico.