Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Permitir tráfico saliente por dominio: control de egress FQDN

By Joshua FoxFeb 7, 20237 min read

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

FQDN Egress Control

Cuando construyes una aplicación segura, lo habitual es no dejar que se conecte fuera de su Virtual Private Cloud (VPC). Pero a veces necesitas abrir un poco la puerta, por ejemplo, cuando tu aplicación tiene que llegar a una API de terceros.

FQDN Egress Control

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

Lo habitual es permitir egress solo a las direcciones IP que correspondan, configurándolo con el Firewall en Google Cloud Platform o con Network ACLs en AWS. Pero 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. La mayoría de las aplicaciones se configuran para acceder a un FQDN y no a una dirección IP.

allow egres

En este artículo voy a repasar las distintas formas de permitir 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 integrarse con Kubernetes: por ejemplo, si tu aplicación corre en Kubernetes, tal vez quieras permitir egress desde un namespace específico y no desde otros.

Otro punto que conviene tener en cuenta es la granularidad de control a nivel de dominio, ya que una misma dirección IP puede alojar varios dominios. La mayoría de las soluciones aquí no contemplan esto: si permites el acceso a un dominio con una IP determinada, también se permitirá egress a todos los dominios que estén detrás de esa dirección. Esto no suele ser un problema de seguridad, ya que normalmente todos los dominios alojados en una misma IP están bajo el control de una sola entidad. Pero el virtual hosting basado en nombre sí permite este escenario, así que también presentaremos algunas soluciones que lo soportan.

Las opciones que reviso aquí son:

  • Squid, como ejemplo de proxy autogestionado
  • AWS Network Gateway, con deep packet inspection, que permite 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 integradas con Kubernetes: 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, la 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 firewalls típicos o Network ACLs.)

Cómo implementarlo por tu cuenta

Primero, veamos cómo se podría implementar esto por cuenta propia. No es que lo 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, tu solución tiene que bloquear paquetes a nivel de dirección IP, ya que todo el tráfico de red las usa. Los nombres de dominio solo son relevantes antes de que se intente la conexión, cuando el cliente busca la dirección IP a partir del nombre de dominio.

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, así que 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 IP relevantes.

Escribes y despliegas una aplicación que consulta el DNS de forma periódica 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 que la dirección IP haya cambiado, tu aplicación actualiza el Firewall o la Network ACL.

Reverse web proxies autogestionados

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 enviar todo el tráfico saliente a través de una VM que corre el proxy Squid; este coteja la dirección IP contra el nombre de dominio —según se haya configurado en una whitelist de ACL— y, si hay coincidencia, lo deja pasar.

Squid está disponible en el AWS Marketplace; revisa esta discusión sobre arquitectura. También está disponible en el GCP Marketplace; mira esta configuración de red. Mira 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, por ejemplo al actualizar los sistemas operativos de las VMs y atender caídas. Como todo el tráfico de red pasa por una sola VM (a menos que hagas el esfuerzo adicional de configurar un despliegue con balanceo de carga), la carga puede ser alta, lo que pone en riesgo la robustez y puede obligarte a tener una VM más grande corriendo 24x7, incluso cuando no se necesita al máximo.

AWS Network Firewall

AWS Network Firewall hace deep packet inspection y, por eso, gana más capacidad de filtrado. Esto significa que no es estrictamente comparable con Google Firewall, que se parece más a las Network ACLs de AWS.

AWS Network Firewall soporta el control de egress por FQDN mediante stateful domain list rule groups. Usando el 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 se puede integrar con Route 53 DNS Firewall, que bloquea los intentos de resolución DNS, de modo que, por ejemplo, una consulta DNS para api.example.com desde una aplicación dentro de la VPC no se resuelva a una dirección IP. Pero el DNS Firewall en realidad no impide el acceso a esa IP; de eso se encarga Network Firewall.

Network Firewall es una buena opción, aunque puede salir caro: está pensado para entornos empresariales complejos con múltiples redes. ( Mira 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 gestionada por el proveedor de la nube que administrar la VM por tu cuenta. Y justo ahora Google está lanzando algunas soluciones que hacen esto posible. En un próximo post entraré en detalle sobre cómo usarlas, pero aquí van los puntos clave por ahora.

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

Otro servicio en Preview limitado, Secure Web Gateway, también permite control a nivel de dominio. Para lograrlo, le das acceso a tus certificados SSL en el GCP Certificate Manager, así puede 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, hasta te permite control a nivel de URL.

Cilium

Las soluciones anteriores trabajan a nivel de la VPC. Pero si tu aplicación corre en Kubernetes, tal vez prefieras que el control de egress funcione con conceptos de Kubernetes. Para esto puedes usar CiliumNetworkPolicy. Es una Custom Resource Definition (CRD) que ejecuta la lógica de resolver nombres de dominio a direcciones IP y luego bloquea o permite tráfico en la capa de red de Cilium basada en eBPF. (Mira dos posts en el blog de DoiT.) La CRD se integra con Kubernetes, así que puedes distinguir pods por namespace: algunos con acceso permitido a la API externa y otros no. Otra CRD, CiliumClusterwideNetworkPolicy, hace lo mismo, pero su configuración se aplica entre namespaces, a todo el cluster.

Esta solución añade algo de complejidad a tu cluster por la necesidad de sumar la capa de red adicional de Cilium. En un futuro cercano, como se indica en la documentación de Cilium, "toda la funcionalidad se integrará en el formato de recursos estándar y esta CRD ya no será necesaria". Aunque todavía no hay una especificación estándar disponible, el Kubernetes Networking Special Interest Group ya está trabajando en ello.

Istio

La solución más completa es la que ofrece el service mesh Istio. Istio controla totalmente el tráfico y te permite bloquear todo el egress, salvo lo que definas en un ServiceEntry. Cuando especificas resolution: DNS, le pides a Istio que no se base en la dirección IP a la que se está conectando el cliente (un pod), sino que resuelva el nombre de dominio mediante DNS de forma periódica. El servicio de Istio se puede exponer solo a los namespaces que elijas. Istio te da el mayor nivel de control, pero añade más complejidad que Cilium, con toda la potencia y funcionalidad de una capa de service mesh.

¿Qué hacer?

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

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