EC2 sin acceso a Internet en VPC personalizada: Internet Gateway y Route Table

Creaste una VPC personalizada, lanzaste una instancia EC2 en una subred pública y no puedes hacer ping a google.com — ni SSH funciona desde fuera. Este es uno de los problemas más frecuentes al trabajar con redes en AWS, y casi siempre se reduce a tres capas que deben estar alineadas: el Internet Gateway, la Route Table y la configuración de IP pública. Si falla cualquiera de las tres, el tráfico no sale.

TL;DR — Acceso a Internet en EC2 dentro de VPC personalizada

CapaQué debe estar configuradoError típico
Internet GatewayCreado y adjunto a la VPCIGW existe pero no está adjunto
Route TableRuta 0.0.0.0/0 apuntando al IGWRoute Table sin ruta de salida
Subred públicaAsociada a la Route Table correctaSubred usa la Route Table principal sin IGW
IP públicaAuto-assign habilitado o EIP asignadoInstancia sin IP pública
Security GroupRegla de salida 0.0.0.0/0 permitidaEgress bloqueado por SG restrictivo
Network ACLReglas de entrada y salida permisivasACL bloquea tráfico de retorno

Cómo funciona el acceso a Internet en una VPC personalizada

Cuando AWS crea la VPC por defecto, todo esto ya viene configurado. En una VPC personalizada, partes de esta cadena no existen hasta que las construyes explícitamente. El flujo de tráfico de salida desde una instancia EC2 hacia Internet atraviesa estas capas en orden:

graph LR EC2["Instancia EC2
IP privada: 10.0.1.5"] --> RT["Route Table
0.0.0.0/0 → igw-xxx"] RT --> IGW["Internet Gateway
NAT 1:1"] IGW --> INT["Internet
8.8.8.8"] SG["Security Group
Egress: ALLOW"] -.->|filtra| EC2 NACL["Network ACL
Stateless"] -.->|filtra subred| RT
  1. EC2 genera tráfico hacia una IP externa (ej. 8.8.8.8).
  2. El kernel de la instancia consulta la Route Table asociada a su subred.
  3. La ruta 0.0.0.0/0 debe apuntar al Internet Gateway (IGW) de la VPC.
  4. El IGW realiza NAT 1:1 entre la IP privada de la instancia y su IP pública o Elastic IP.
  5. El Security Group filtra el tráfico de salida (egress) antes de que salga.
  6. El Network ACL filtra a nivel de subred — tanto entrada como salida, y es stateless.

El detalle que más confunde: el IGW no es un router que simplemente reenvía paquetes. Realiza traducción de direcciones. Si la instancia no tiene IP pública asignada, el IGW no puede completar esa traducción y el paquete se descarta silenciosamente.

Piensa en el IGW como la puerta de salida de un edificio: puedes construir el pasillo (Route Table) y abrir la cerradura (Security Group), pero si la puerta no está instalada en el marco (IGW no adjunto a la VPC), nadie sale.

Diagnóstico: EC2 sin acceso a Internet en VPC personalizada

Antes de modificar cualquier configuración, verifica el estado actual de cada capa. Cambiar cosas sin diagnóstico previo es la razón por la que estos problemas tardan horas en resolverse.

Paso 1 — Verificar que el Internet Gateway existe y está adjunto a la VPC

Un IGW puede existir en tu cuenta pero estar en estado 'detached'. Eso no genera ningún error visible en la consola hasta que intentas enrutar tráfico a través de él. Confirma el estado antes de tocar la Route Table.

# Listar todos los Internet Gateways y su estado de adjunto
aws ec2 describe-internet-gateways \
  --query 'InternetGateways[*].{IGW_ID:InternetGatewayId,Estado:Attachments[0].State,VPC_ID:Attachments[0].VpcId}' \
  --output table

El campo Estado debe mostrar available y el VPC_ID debe coincidir con tu VPC. Si el IGW aparece sin adjuntos o con estado detached, continúa con el Paso 2. Si no existe ningún IGW para tu VPC, créalo primero.

Paso 2 — Crear y adjuntar el Internet Gateway (si no existe o está desconectado)

Si el diagnóstico del paso anterior confirmó que no hay IGW adjunto, este es el punto de partida real. Sin este componente, los pasos siguientes no tienen efecto.

# Crear un nuevo Internet Gateway
aws ec2 create-internet-gateway \
  --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=mi-igw}]'

# El comando anterior devuelve el InternetGatewayId. Úsalo en el siguiente comando.
# Reemplaza igw-XXXXXXXXXXXXXXXXX con el ID obtenido
# Reemplaza vpc-XXXXXXXXXXXXXXXXX con el ID de tu VPC personalizada
aws ec2 attach-internet-gateway \
  --internet-gateway-id igw-XXXXXXXXXXXXXXXXX \
  --vpc-id vpc-XXXXXXXXXXXXXXXXX

Paso 3 — Verificar la Route Table asociada a la subred pública

Este es el error más común después del IGW desconectado: la subred está usando la Route Table principal de la VPC, que no tiene ruta hacia el IGW. Las Route Tables principales rara vez se modifican, lo que significa que todas las subredes nuevas heredan una tabla sin salida a Internet por defecto.

# Obtener el ID de la subred donde está tu instancia EC2
# Reemplaza i-XXXXXXXXXXXXXXXXX con el ID de tu instancia
aws ec2 describe-instances \
  --instance-ids i-XXXXXXXXXXXXXXXXX \
  --query 'Reservations[0].Instances[0].{SubnetId:SubnetId,VpcId:VpcId,PublicIP:PublicIpAddress}' \
  --output table

# Verificar qué Route Table está asociada a esa subred
# Reemplaza subnet-XXXXXXXXXXXXXXXXX con el SubnetId obtenido arriba
aws ec2 describe-route-tables \
  --filters Name=association.subnet-id,Values=subnet-XXXXXXXXXXXXXXXXX \
  --query 'RouteTables[*].{RouteTableId:RouteTableId,Rutas:Routes[*].{Destino:DestinationCidrBlock,Target:GatewayId}}' \
  --output json

En la salida, busca una entrada con DestinationCidrBlock: 0.0.0.0/0. Si no existe, la subred no tiene ruta de salida. Si existe pero el GatewayId no empieza con igw-, el tráfico está siendo enviado al lugar equivocado.

Paso 4 — Agregar la ruta de salida a Internet en la Route Table

Con el IGW adjunto y la Route Table identificada, ahora puedes agregar la ruta que conecta ambos. Si la subred aún usa la Route Table principal, lo recomendable es crear una Route Table dedicada para subredes públicas en lugar de modificar la principal.

# Opción A: Agregar ruta 0.0.0.0/0 a una Route Table existente
# Reemplaza rtb-XXXXXXXXXXXXXXXXX con el RouteTableId identificado en el Paso 3
# Reemplaza igw-XXXXXXXXXXXXXXXXX con el ID de tu Internet Gateway
aws ec2 create-route \
  --route-table-id rtb-XXXXXXXXXXXXXXXXX \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id igw-XXXXXXXXXXXXXXXXX

# Opción B: Crear una Route Table nueva para subredes públicas
aws ec2 create-route-table \
  --vpc-id vpc-XXXXXXXXXXXXXXXXX \
  --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=rtb-publica}]'

# Agregar la ruta al IGW en la nueva Route Table
# Usa el RouteTableId devuelto por el comando anterior
aws ec2 create-route \
  --route-table-id rtb-XXXXXXXXXXXXXXXXX \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id igw-XXXXXXXXXXXXXXXXX

# Asociar la nueva Route Table a la subred pública
aws ec2 associate-route-table \
  --route-table-id rtb-XXXXXXXXXXXXXXXXX \
  --subnet-id subnet-XXXXXXXXXXXXXXXXX

Paso 5 — Confirmar que la instancia tiene IP pública asignada

El IGW necesita una IP pública para realizar la traducción de direcciones. Si la instancia fue lanzada en una subred donde 'Auto-assign public IPv4 address' estaba deshabilitado, no tiene IP pública y el tráfico no puede salir aunque el IGW y la Route Table estén correctamente configurados. Esto no genera ningún error explícito — el tráfico simplemente no llega.

# Verificar si la instancia tiene IP pública
aws ec2 describe-instances \
  --instance-ids i-XXXXXXXXXXXXXXXXX \
  --query 'Reservations[0].Instances[0].{PublicIP:PublicIpAddress,PublicDNS:PublicDnsName,Estado:State.Name}' \
  --output table

Si PublicIP aparece como None, tienes dos opciones: asignar una Elastic IP a la instancia, o habilitar auto-assign en la subred para instancias futuras.

# Asignar una Elastic IP a la instancia existente
# Primero, obtener un nuevo EIP
aws ec2 allocate-address --domain vpc

# Asociar el EIP a la instancia
# Reemplaza eipalloc-XXXXXXXXXXXXXXXXX con el AllocationId devuelto
aws ec2 associate-address \
  --instance-id i-XXXXXXXXXXXXXXXXX \
  --allocation-id eipalloc-XXXXXXXXXXXXXXXXX

# Habilitar auto-assign de IP pública en la subred para instancias futuras
aws ec2 modify-subnet-attribute \
  --subnet-id subnet-XXXXXXXXXXXXXXXXX \
  --map-public-ip-on-launch

Paso 6 — Revisar Security Group: reglas de egress

Los Security Groups de EC2 son stateful, pero las reglas de egress existen y pueden estar configuradas de forma restrictiva. Un SG sin regla de salida explícita bloquea todo el tráfico de egress. Verifica que haya una regla que permita salida hacia 0.0.0.0/0.

# Obtener el Security Group asociado a la instancia
aws ec2 describe-instances \
  --instance-ids i-XXXXXXXXXXXXXXXXX \
  --query 'Reservations[0].Instances[0].SecurityGroups' \
  --output table

# Revisar las reglas de egress del Security Group
# Reemplaza sg-XXXXXXXXXXXXXXXXX con el GroupId obtenido
aws ec2 describe-security-groups \
  --group-ids sg-XXXXXXXXXXXXXXXXX \
  --query 'SecurityGroups[0].IpPermissionsEgress' \
  --output json

Si el resultado está vacío o no incluye 0.0.0.0/0 con protocolo -1 (todo el tráfico), agrega la regla:

# Permitir todo el tráfico de salida desde el Security Group
aws ec2 authorize-security-group-egress \
  --group-id sg-XXXXXXXXXXXXXXXXX \
  --protocol -1 \
  --port -1 \
  --cidr 0.0.0.0/0

Paso 7 — Revisar Network ACL de la subred

A diferencia de los Security Groups, los Network ACLs son stateless. Esto significa que necesitas reglas explícitas tanto para el tráfico de entrada como de salida, incluyendo los puertos efímeros de retorno (1024-65535). Este es el error que más confunde a ingenieros con experiencia en Security Groups: el SG permite el tráfico, el ping sale, pero la respuesta nunca llega porque el ACL bloquea el tráfico de retorno en el rango efímero.

# Obtener el Network ACL asociado a la subred
aws ec2 describe-network-acls \
  --filters Name=association.subnet-id,Values=subnet-XXXXXXXXXXXXXXXXX \
  --query 'NetworkAcls[*].{AclId:NetworkAclId,Entradas:Entries[*].{Regla:RuleNumber,Protocolo:Protocol,Accion:RuleAction,CIDR:CidrBlock,Egress:Egress}}' \
  --output json

Verifica que existan reglas ALLOW para tráfico de salida (Egress: true) y de entrada (Egress: false) que cubran los rangos necesarios. La Network ACL por defecto de una VPC permite todo el tráfico, pero si fue modificada o si creaste una ACL personalizada, puede estar bloqueando tráfico silenciosamente.

graph TD START(["EC2 sin Internet"]) START --> Q1{"¿IGW adjunto
a la VPC?"} Q1 -->|No| FIX1["Crear y adjuntar IGW
Paso 2"] Q1 -->|Sí| Q2{"¿Route Table tiene
ruta 0.0.0.0/0 → IGW?"} FIX1 --> Q2 Q2 -->|No| FIX2["Agregar ruta al IGW
Paso 4"] Q2 -->|Sí| Q3{"¿Instancia tiene
IP pública o EIP?"} FIX2 --> Q3 Q3 -->|No| FIX3["Asignar EIP
Paso 5"] Q3 -->|Sí| Q4{"¿Security Group
permite egress?"} FIX3 --> Q4 Q4 -->|No| FIX4["Agregar regla egress
Paso 6"] Q4 -->|Sí| Q5{"¿Network ACL
permite tráfico?"} FIX4 --> Q5 Q5 -->|No| FIX5["Revisar reglas ACL
Paso 7"] Q5 -->|Sí| OK(["Conectividad restaurada"]) FIX5 --> OK

Experiencia de campo: el diagnóstico que siempre falla primero

El escenario más frecuente en producción: el ingeniero verifica el Security Group, ve que el puerto 443 está abierto en egress, asume que todo está bien y pasa los siguientes 40 minutos revisando configuraciones de la aplicación. El problema real era que la subred estaba asociada a la Route Table principal de la VPC, que solo tenía la ruta local (10.0.0.0/16 → local) y ninguna ruta hacia el IGW.

La señal que lo confirma: desde la instancia, curl -v https://8.8.8.8 cuelga indefinidamente en lugar de devolver un error de conexión rechazada. Una conexión rechazada significa que el paquete llegó a algún lado. Un timeout sin respuesta significa que el paquete nunca salió de la subred.

El fix fue asociar la subred a una Route Table que tenía la ruta 0.0.0.0/0 → igw-xxx. El IGW ya existía y estaba adjunto. La instancia ya tenía IP pública. Solo faltaba ese vínculo entre la subred y la tabla de rutas correcta.

Un timeout de red en AWS casi siempre es un problema de routing o de ACL stateless — no de Security Group. Los SGs rechazan conexiones activamente; el routing simplemente deja caer los paquetes en silencio.

Verificación final del acceso a Internet en EC2

Con todas las capas configuradas, verifica la conectividad desde la instancia. Si tienes acceso SSH, ejecuta directamente desde la instancia:

# Verificar resolución DNS y conectividad HTTP
curl -I https://www.google.com

# Verificar conectividad ICMP (si el Security Group permite ICMP de salida)
ping -c 4 8.8.8.8

# Verificar la tabla de rutas del sistema operativo dentro de la instancia
ip route show

El comando ip route show debe mostrar una ruta default (default via 10.x.x.1) apuntando al gateway de la subred. Si esa ruta no existe, el problema está en la configuración de red del sistema operativo de la instancia, no en la infraestructura de VPC.

Política IAM mínima para ejecutar estos diagnósticos

Si estás ejecutando estos comandos desde una instancia EC2, un rol de CI/CD, o una cuenta con permisos restringidos, necesitas al menos los siguientes permisos para leer y modificar la configuración de red:

🔽 Ver política IAM mínima requerida
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "LecturaRed",
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "ec2:DescribeInternetGateways",
        "ec2:DescribeRouteTables",
        "ec2:DescribeSubnets",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeNetworkAcls",
        "ec2:DescribeAddresses"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ModificacionRed",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateInternetGateway",
        "ec2:AttachInternetGateway",
        "ec2:CreateRoute",
        "ec2:CreateRouteTable",
        "ec2:AssociateRouteTable",
        "ec2:ModifySubnetAttribute",
        "ec2:AllocateAddress",
        "ec2:AssociateAddress",
        "ec2:AuthorizeSecurityGroupEgress"
      ],
      "Resource": "*"
    }
  ]
}

Las acciones Describe/List de EC2 requieren Resource: * — no admiten restricción por ARN de recurso específico según la Service Authorization Reference de AWS.

Próximos pasos y recursos adicionales

Una vez que el acceso a Internet funciona correctamente en tu VPC personalizada, considera estos pasos para consolidar la arquitectura de red:

  • Si necesitas que instancias en subredes privadas accedan a Internet sin exponer una IP pública, implementa un NAT Gateway en la subred pública y actualiza la Route Table de las subredes privadas.
  • Revisa la documentación oficial de AWS sobre Internet Gateways para entender los casos límite con IPv6.
  • Para auditar cambios de red en el futuro, habilita VPC Flow Logs — son esenciales para diagnosticar problemas de conectividad sin acceso directo a la instancia.
  • Si el entorno requiere alta disponibilidad, considera distribuir subredes públicas en múltiples Availability Zones con sus propias asociaciones de Route Table.

Glosario de términos clave — EC2 y VPC personalizada

TérminoDefinición operativa
Internet Gateway (IGW)Componente de VPC que permite comunicación entre instancias con IP pública e Internet. Realiza NAT 1:1. Debe estar adjunto a la VPC para funcionar.
Route TableConjunto de reglas que determinan hacia dónde se enruta el tráfico de red desde una subred. Cada subred debe estar asociada a exactamente una Route Table.
Subred públicaSubred cuya Route Table tiene una ruta 0.0.0.0/0 apuntando a un IGW. No es una propiedad intrínseca de la subred, sino de su configuración de routing.
Network ACLFiltro de red stateless a nivel de subred. Requiere reglas explícitas de entrada y salida, incluyendo puertos efímeros para tráfico de retorno.
Elastic IP (EIP)Dirección IPv4 pública estática asignable a una instancia EC2 o NAT Gateway. Persiste independientemente del ciclo de vida de la instancia.

Comentarios

Entradas populares de este blog

Actualizar Contenido en CloudFront: Cómo Crear una Invalidación para Limpiar el Caché del Edge

Aumentar el Timeout de Lambda: Configuración, Límites y Diagnóstico en Producción