El patrón que sigo viendo en auditorías internas y post-incidentes es simple: el tráfico de salida se deja “abierto por defecto” y luego se intenta compensar con detección. En cloud, ese orden suele salir caro. Si una VM/EC2 cae, el egress libre (por ejemplo, un Security Group de salida a 0.0.0.0/0) se convierte en la vía rápida para Command & Control y exfiltración: HTTP/HTTPS hacia cualquier destino, DNS a resolvers externos, y túneles que se camuflan como tráfico legítimo.
Este artículo se centra en cómo implementar Network Egress Control real para VPCs: no como un “checkbox”, sino como un conjunto de guardrails operables que resisten incidentes, cambios y presión por “no romper” dependencias.
Qué salió mal cuando el egress es “permitir todo”
El problema no es que exista salida a internet; el problema es que la salida no está gobernada. En muchas VPCs, las instancias privadas salen por un NAT Gateway sin restricciones, y los Security Groups permiten egress a cualquier destino. En el día a día parece práctico: actualizaciones, llamadas a APIs, telemetría… todo “funciona”. Pero esa misma comodidad elimina fricción al atacante.
En empresa, el impacto real aparece en dos momentos: cuando hay un compromiso y cuando hay que responder rápido. Con egress abierto, un malware puede rotar dominios/IPs de C2 sin impedimentos y exfiltrar por HTTPS a un bucket externo, un pastebin, un servidor en un ASN barato o incluso a un CDN. Lo peor es que, desde red, el tráfico “parece normal”: TLS al puerto 443.
Un efecto colateral habitual es operativo: cuando por fin se decide cerrar, nadie tiene inventario de dependencias de salida. El equipo de producto siente el cambio como “seguridad rompiendo cosas”, y el resultado suele ser volver a abrir 0.0.0.0/0 “temporalmente”. Esa temporalidad tiende a durar meses.
Decisiones de arquitectura: NAT con restricciones vs. endpoints privados
El primer trade-off real es separar el tráfico “necesario para operar” del tráfico “comodín”. Para servicios gestionados del propio cloud, la mejor palanca es evitar internet directamente. En AWS, esto se materializa con VPC Endpoints (Gateway Endpoints para S3/DynamoDB y Interface Endpoints/PrivateLink para servicios como KMS, Secrets Manager, STS, ECR, etc.). Cuando lo haces bien, reduces superficie: ese tráfico ya no depende del NAT ni de rutas a un Internet Gateway.
En escenarios corporativos, el cambio se nota en incident response: si una instancia comprometida intenta exfiltrar a S3, pero tu acceso permitido a S3 está acotado a endpoints privados y a buckets concretos, ya no es “S3 a cualquier sitio”. Además, al mover dependencias internas a PrivateLink, eliminas necesidad de abrir egress a rangos públicos que cambian.
- Gateway Endpoints (S3/DynamoDB): reducen coste y simplifican rutas, pero requieren disciplina con políticas de endpoint y bucket policies. Sin esa disciplina, sigues permitiendo accesos amplios, solo que “por dentro”.
En la práctica, esto implica revisar que el acceso a S3/DynamoDB desde subnets privadas no pueda ir “por internet” como bypass. Si tienes ruta al NAT y además endpoint, una app comprometida puede seguir saliendo por NAT hacia destinos externos; el endpoint solo cubre los servicios asociados.
- NAT Gateways con restricciones: útiles para dependencias externas inevitables (APIs de terceros, repositorios, validadores de licencias), pero requieren un punto de control adicional (firewall/proxy) porque el NAT por sí solo no filtra por FQDN ni hace inspección.
El error típico es asumir que “tener NAT” es equivalente a “tener control”. Si no hay inspección ni allowlist, el NAT es solo una puerta de salida altamente disponible.
Cómo hacerlo en la práctica: cortar el egress en Security Groups sin paralizar equipos
El quick win con mejor relación impacto/esfuerzo es dejar de tratar el egress como un “permit all” y pasar a un modelo de allowlist por dependencias conocidas. En AWS, esto empieza por endurecer los Security Groups de workloads: permitir salida solo a puertos y destinos necesarios (por ejemplo, 443 hacia un proxy interno, 5432 hacia una base de datos, o 443 hacia un endpoint privado).
En entornos con varias squads, funciona mejor si lo conviertes en un estándar de plataforma: plantillas de SG por tipo de workload, y una vía controlada para solicitar excepciones. Si lo haces “a mano” en cada instancia, se rompe con el primer autoscaling o con el primer redeploy.
- Patrón operativo: forzar que el único egress permitido desde subnets privadas sea hacia un proxy/firewall (puerto 3128/443 según diseño) y hacia servicios internos necesarios (DBs, caches). Esto reduce drásticamente C2 directo desde la instancia.
Este patrón crea una consecuencia buena y una incómoda. La buena: el atacante ya no puede “hablar al mundo” desde la máquina. La incómoda: si una app necesita hablar con un tercero nuevo, se notará. Por eso la clave está en el proceso de alta de dependencias y en la observabilidad (ver qué se bloquea y por qué).
- Validación rápida en AWS: revisa que los SG no tengan egress amplio a
0.0.0.0/0en 443 “por si acaso”. En VPC Flow Logs, valida que los flujos salientes a internet desde subnets privadas se reduzcan a “solo proxy/firewall” y que no existan rutas alternativas (por ejemplo, instancias con IP pública por error).
Si al hacer el cambio aparecen errores “intermitentes” en producción, suele ser porque había dependencias no documentadas (telemetría, OCSP/CRL, endpoints de autenticación, repositorios). No es un argumento para abrir todo: es señal de que el egress control te está obligando a descubrir deuda técnica real.
Inspección y bloqueo: proxy de salida y firewalls con políticas mantenibles
Cuando necesitas control fino (dominios, categorías, TLS inspection en casos justificados), el egress debe pasar por un punto inspectable. En AWS, un patrón común es desplegar un proxy de salida (por ejemplo, Squid) en una subnet de gestión o egress, y forzar rutas desde workloads hacia ese proxy. En organizaciones con requisitos más estrictos, se prefiere un control centralizado con AWS Network Firewall; en Azure, la contraparte típica es Azure Firewall.
La diferencia práctica entre “bloquear por IP/puerto” y “bloquear por dominio” se ve el día que un tercero migra de IP o usa CDN. Si tu allowlist es solo IP, romperás integraciones con frecuencia. Si dependes solo de FQDN sin buen gobierno, abrirás demasiado (“*.amazonaws.com” y similares). La política mantenible suele ser: endpoints privados para servicios cloud propios; y para terceros, reglas por FQDN/categoría con un proceso de alta y expiración.
- Qué bloquear primero: resolvers DNS externos directos (para evitar bypass), egress directo a 443 desde workloads (para forzar proxy/firewall), y destinos “commodity” de exfil (almacenamiento genérico, paste sites) según política corporativa.
Esto no es teoría: en incidentes reales, si permites DNS directo a internet, un atacante puede usar DoH/DoT o tunelizar en subdominios para evadir controles basados en IP. Forzar DNS controlado y egress controlado reduce el espacio de maniobra.
- Señales operativas de que el control funciona: caen los intentos de conexión a IPs desconocidas desde workloads; suben eventos de denegación bien clasificados (y accionables) en el firewall/proxy; y las excepciones se gestionan como cambios trazables, no como “abre y ya”.
Un anti-patrón frecuente es desplegar un firewall pero dejar rutas alternativas: una subnet con ruta al NAT “para emergencias”, una instancia con IP pública “temporal”, o SGs con egress abierto “solo para debugging”. En red, una excepción así invalida toda la inversión.
Recomendaciones para entornos corporativos
Si quieres Network Egress Control real para VPCs, el foco debe estar en cerrar la puerta fácil (egress amplio desde el workload) y crear un camino de salida gobernado (endpoints privados + punto inspectable). El objetivo no es eliminar internet, sino evitar que una máquina comprometida pueda improvisar C2/exfil sin fricción.
En la práctica, lo más efectivo suele ser combinar: VPC Endpoints/PrivateLink para servicios gestionados, Security Groups con allowlist mínima, y un proxy/firewall como único camino de salida para dependencias externas. Lo que hace que esto funcione en empresa es la operativa: plantillas, proceso de excepciones, y validación continua con Flow Logs y revisión de SG/rutas para evitar bypass.
Si hoy existe egress a 0.0.0.0/0 “por defecto”, el primer paso no es discutir sobre herramientas, sino decidir dónde estará el control (proxy/firewall/endpoints) y mover el tráfico hacia ahí, de forma visible y reversible. A partir de ese punto, el egress deja de ser una puerta trasera y pasa a ser un componente gestionado.
¿Te interesa la seguridad en Cloud?
Comparto análisis técnicos, laboratorios prácticos y experiencias reales sobre Cloud Security.