Conectar Dos VPCs con VPC Peering: Guía Completa de Configuración y Tablas de Rutas

Tienes dos VPCs en la misma cuenta y región, y los recursos en cada una necesitan comunicarse usando IPs privadas — sin pasar por internet. El VPC Peering es la solución nativa de AWS para este caso, pero el error más común no está en crear la conexión: está en olvidar actualizar las tablas de rutas en ambos lados, o en tener bloques CIDR solapados que AWS rechaza silenciosamente hasta que intentas enrutar tráfico.

TL;DR — Conectar Dos VPCs con VPC Peering

PasoAcciónDónde
1Verificar que los CIDRs no se solapanConsola / CLI
2Crear la solicitud de Peering ConnectionVPC solicitante
3Aceptar la solicitudVPC aceptante
4Actualizar tabla de rutas en VPC-A → apuntar al CIDR de VPC-BRoute Table VPC-A
5Actualizar tabla de rutas en VPC-B → apuntar al CIDR de VPC-ARoute Table VPC-B
6Verificar Security Groups permiten el tráficoInstancias destino

Cómo Funciona el VPC Peering

Un VPC Peering Connection es una conexión de red entre dos VPCs que permite enrutar tráfico entre ellas usando direcciones IPv4 o IPv6 privadas. El tráfico viaja a través de la infraestructura de red de AWS — no pasa por internet, por una VPN, ni por un gateway físico separado.

Lo que mucha gente no entiende al principio: el peering en sí mismo es solo un canal. No enruta nada automáticamente. Para que el tráfico fluya, cada VPC necesita una entrada explícita en su tabla de rutas que diga 'el tráfico hacia el CIDR del otro lado va por esta Peering Connection'. Si falta una sola de esas entradas, la comunicación es unidireccional o inexistente.

Restricciones importantes que debes conocer antes de empezar:

  • Sin CIDR solapado: Si VPC-A usa 10.0.0.0/16 y VPC-B también, el peering no puede establecerse. AWS lo rechaza.
  • Sin enrutamiento transitivo: Si VPC-A tiene peering con VPC-B, y VPC-B tiene peering con VPC-C, VPC-A no puede alcanzar VPC-C a través de VPC-B. Cada par necesita su propio peering directo.
  • Mismo account, misma región: Este caso es el más simple. Peering entre cuentas distintas o regiones distintas requiere pasos adicionales de aceptación.
graph LR A["VPC-A 10.0.0.0/16"] -->|"1. Solicitud de Peering"| PCX["Peering Connection pcx-0123... Estado: active"] PCX -->|"2. Acepta"| B["VPC-B 10.1.0.0/16"] A --> RTA["Route Table VPC-A 10.1.0.0/16 → pcx-..."] B --> RTB["Route Table VPC-B 10.0.0.0/16 → pcx-..."] RTA -->|"3. Tráfico enrutado"| PCX RTB -->|"3. Tráfico enrutado"| PCX PCX --> SGA["Security Group Instancia en VPC-A"] PCX --> SGB["Security Group Instancia en VPC-B"]
  1. VPC-A (10.0.0.0/16) inicia la solicitud de Peering Connection hacia VPC-B.
  2. VPC-B (10.1.0.0/16) acepta la solicitud — en el mismo account y región esto puede hacerse inmediatamente.
  3. La Peering Connection queda en estado active, pero el tráfico aún no fluye.
  4. Cada VPC necesita una entrada en su Route Table apuntando al CIDR del otro lado con el Peering Connection ID como target.
  5. Los Security Groups de las instancias destino deben permitir el tráfico entrante desde el rango CIDR de origen.

Paso 1: Verificar que los CIDRs No Se Solapan

Antes de crear nada, confirma los bloques CIDR de ambas VPCs. Si se solapan, tendrás que rediseñar la red — no hay workaround para esto en VPC Peering.

# Obtener CIDR de todas las VPCs en la región
aws ec2 describe-vpcs \
  --query 'Vpcs[*].{VpcId:VpcId,CIDR:CidrBlock,Name:Tags[?Key==`Name`].Value|[0]}' \
  --output table \
  --region us-east-1

Anota los VPC IDs y sus CIDRs. Para este ejemplo usaremos:

  • VPC-A: vpc-0a1b2c3d4e5f00001 — CIDR 10.0.0.0/16
  • VPC-B: vpc-0a1b2c3d4e5f00002 — CIDR 10.1.0.0/16

Paso 2: Crear la Solicitud de VPC Peering Connection

Dado que ambas VPCs están en el mismo account y región, el campo --peer-owner-id y --peer-region usan los mismos valores que la VPC solicitante. La solicitud se crea desde VPC-A hacia VPC-B.

aws ec2 create-vpc-peering-connection \
  --vpc-id vpc-0a1b2c3d4e5f00001 \
  --peer-vpc-id vpc-0a1b2c3d4e5f00002 \
  --peer-owner-id 123456789012 \
  --region us-east-1 \
  --tag-specifications 'ResourceType=vpc-peering-connection,Tags=[{Key=Name,Value=peering-vpc-a-to-vpc-b}]'

El comando devuelve un objeto con el VpcPeeringConnectionId — algo como pcx-0123456789abcdef0. Guarda ese ID, lo necesitas en todos los pasos siguientes.

# Verificar el estado de la solicitud
aws ec2 describe-vpc-peering-connections \
  --filters Name=status-code,Values=pending-acceptance \
  --query 'VpcPeeringConnections[*].{ID:VpcPeeringConnectionId,Status:Status.Code,Requester:RequesterVpcInfo.VpcId,Accepter:AccepterVpcInfo.VpcId}' \
  --output table \
  --region us-east-1

Paso 3: Aceptar la Solicitud de Peering

En el mismo account y región, puedes aceptar la solicitud inmediatamente. Si la VPC aceptante estuviera en otra cuenta, el propietario de esa cuenta tendría que ejecutar este comando.

aws ec2 accept-vpc-peering-connection \
  --vpc-peering-connection-id pcx-0123456789abcdef0 \
  --region us-east-1

Confirma que el estado cambió a active:

aws ec2 describe-vpc-peering-connections \
  --vpc-peering-connection-ids pcx-0123456789abcdef0 \
  --query 'VpcPeeringConnections[0].Status' \
  --region us-east-1

Si ves {"Code": "active", "Message": "Active"}, el canal está establecido. Pero repito: el tráfico todavía no fluye.

Paso 4: Actualizar las Tablas de Rutas — El Paso que Más Se Olvida

Este es el punto donde la mayoría de los ingenieros pierde tiempo. El peering está activo, hacen ping entre instancias, no funciona, y empiezan a revisar Security Groups cuando el problema real es que las rutas no existen.

Necesitas identificar qué tablas de rutas están asociadas a las subnets donde viven tus instancias en cada VPC. Una VPC puede tener múltiples tablas de rutas — actualiza solo las que necesitan alcanzar el otro lado.

# Listar tablas de rutas de VPC-A con sus asociaciones de subnet
aws ec2 describe-route-tables \
  --filters Name=vpc-id,Values=vpc-0a1b2c3d4e5f00001 \
  --query 'RouteTables[*].{RouteTableId:RouteTableId,Subnets:Associations[*].SubnetId}' \
  --output table \
  --region us-east-1
# Listar tablas de rutas de VPC-B
aws ec2 describe-route-tables \
  --filters Name=vpc-id,Values=vpc-0a1b2c3d4e5f00002 \
  --query 'RouteTables[*].{RouteTableId:RouteTableId,Subnets:Associations[*].SubnetId}' \
  --output table \
  --region us-east-1

Una vez identificadas las tablas relevantes, agrega las rutas. Supongamos que la tabla de rutas de VPC-A es rtb-00000000000000001 y la de VPC-B es rtb-00000000000000002.

# En VPC-A: agregar ruta hacia el CIDR de VPC-B via la Peering Connection
aws ec2 create-route \
  --route-table-id rtb-00000000000000001 \
  --destination-cidr-block 10.1.0.0/16 \
  --vpc-peering-connection-id pcx-0123456789abcdef0 \
  --region us-east-1
# En VPC-B: agregar ruta hacia el CIDR de VPC-A via la Peering Connection
aws ec2 create-route \
  --route-table-id rtb-00000000000000002 \
  --destination-cidr-block 10.0.0.0/16 \
  --vpc-peering-connection-id pcx-0123456789abcdef0 \
  --region us-east-1
graph TD PKT["Paquete desde Instancia en VPC-A 10.0.1.5"] PKT --> RT_A["Route Table VPC-A Busca destino 10.1.x.x"] RT_A -->|"Match: 10.1.0.0/16 Target: pcx-0123..."| PCX["Peering Connection pcx-0123456789abcdef0"] PCX --> NACL_B["NACL Subnet VPC-B Stateless: verifica reglas inbound"] NACL_B -->|"Permitido"| SG_B["Security Group Instancia destino VPC-B Stateful: verifica inbound"] SG_B -->|"Permitido"| INST_B["Instancia destino 10.1.2.10 en VPC-B"] NACL_B -->|"DENY rule"| DROP["Paquete descartado sin notificación"]
  1. La Route Table de VPC-A tiene una entrada: destino 10.1.0.0/16 → target pcx-...
  2. La Route Table de VPC-B tiene una entrada: destino 10.0.0.0/16 → target pcx-...
  3. Sin ambas entradas, el tráfico es unidireccional o no llega.

Paso 5: Verificar y Ajustar Security Groups

Las rutas permiten que los paquetes lleguen a la instancia destino. Los Security Groups deciden si esa instancia los acepta. Un Security Group en VPC-B que solo permite tráfico desde 10.1.0.0/16 va a rechazar conexiones desde 10.0.0.0/16 aunque las rutas estén perfectas.

# Ver las reglas de inbound del Security Group de la instancia destino en VPC-B
aws ec2 describe-security-groups \
  --group-ids sg-0123456789abcdef0 \
  --query 'SecurityGroups[0].IpPermissions' \
  --output json \
  --region us-east-1
# Agregar regla que permita tráfico TCP desde el CIDR de VPC-A (ejemplo: puerto 443)
aws ec2 authorize-security-group-ingress \
  --group-id sg-0123456789abcdef0 \
  --protocol tcp \
  --port 443 \
  --cidr 10.0.0.0/16 \
  --region us-east-1

Una alternativa más segura en entornos donde los Security Groups de VPC-A son conocidos: referenciar el Security Group de origen directamente en lugar del CIDR. Esto funciona porque ambas VPCs están en el mismo account.

# Permitir tráfico desde un Security Group específico de VPC-A
aws ec2 authorize-security-group-ingress \
  --group-id sg-0123456789abcdef0 \
  --protocol tcp \
  --port 443 \
  --source-group sg-0fedcba9876543210 \
  --region us-east-1

Diagnóstico: Cuando el Peering Está Activo pero el Tráfico No Fluye

Escenario real: peering en estado active, rutas agregadas, y aun así el ping entre instancias falla. Lo primero que revisé fueron los Security Groups — parecían correctos. Lo segundo fue Network ACLs — y ahí estaba el problema. Las NACLs de la subnet en VPC-B tenían una regla DENY explícita para rangos 10.0.0.0/8 heredada de una política de seguridad antigua.

Las NACLs son stateless — necesitas reglas de entrada y de salida en ambos lados. Los Security Groups son stateful, las NACLs no.

# Revisar NACLs asociadas a las subnets de VPC-B
aws ec2 describe-network-acls \
  --filters Name=vpc-id,Values=vpc-0a1b2c3d4e5f00002 \
  --query 'NetworkAcls[*].{AclId:NetworkAclId,Entries:Entries[*].{Rule:RuleNumber,Action:RuleAction,CIDR:CidrBlock,Protocol:Protocol}}' \
  --output json \
  --region us-east-1

Busca reglas con RuleAction: deny que cubran el rango CIDR de VPC-A. Las reglas se evalúan en orden numérico ascendente — una DENY con número bajo bloquea todo lo que venga después.

Pensar en las NACLs como un firewall de subnet y en los Security Groups como un firewall de instancia ayuda a recordar el orden de evaluación: el tráfico pasa primero por la NACL antes de llegar a la instancia donde el Security Group toma la decisión final.

Verificación End-to-End del VPC Peering

# Confirmar estado final de la Peering Connection
aws ec2 describe-vpc-peering-connections \
  --vpc-peering-connection-ids pcx-0123456789abcdef0 \
  --query 'VpcPeeringConnections[0].{Status:Status.Code,RequesterCIDR:RequesterVpcInfo.CidrBlock,AccepterCIDR:AccepterVpcInfo.CidrBlock}' \
  --output table \
  --region us-east-1
# Verificar que las rutas existen en la tabla de VPC-A
aws ec2 describe-route-tables \
  --route-table-ids rtb-00000000000000001 \
  --query 'RouteTables[0].Routes[?VpcPeeringConnectionId!=null]' \
  --output table \
  --region us-east-1
# Verificar que las rutas existen en la tabla de VPC-B
aws ec2 describe-route-tables \
  --route-table-ids rtb-00000000000000002 \
  --query 'RouteTables[0].Routes[?VpcPeeringConnectionId!=null]' \
  --output table \
  --region us-east-1

Si ambas consultas devuelven entradas con el pcx-... correcto y estado active, la configuración de red está completa.

IAM: Permisos Mínimos para Configurar VPC Peering

Si estás ejecutando estos comandos desde un rol IAM (no el root de la cuenta), necesitas los siguientes permisos mínimos:

🔽 Ver política IAM mínima para VPC Peering
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VPCPeeringManagement",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateVpcPeeringConnection",
        "ec2:AcceptVpcPeeringConnection",
        "ec2:DescribeVpcPeeringConnections",
        "ec2:DeleteVpcPeeringConnection",
        "ec2:CreateTags"
      ],
      "Resource": "*"
    },
    {
      "Sid": "RouteTableManagement",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateRoute",
        "ec2:DeleteRoute",
        "ec2:DescribeRouteTables"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SecurityGroupManagement",
      "Effect": "Allow",
      "Action": [
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeNetworkAcls",
        "ec2:DescribeVpcs"
      ],
      "Resource": "*"
    }
  ]
}

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

Próximos Pasos y Documentación para VPC Peering

Con el VPC Peering activo y las rutas configuradas en ambos lados, la comunicación entre instancias usando IPs privadas debería funcionar. Si tu arquitectura crece a más de dos o tres VPCs que necesitan comunicarse entre sí, evalúa AWS Transit Gateway — el modelo hub-and-spoke escala mejor que una malla de peering connections individuales.

Para entornos multi-cuenta, el proceso de aceptación de peering requiere coordinación entre los propietarios de cada cuenta, y puedes usar AWS RAM (Resource Access Manager) para simplificar la gestión.

Referencias oficiales:

Glosario — Términos Clave de VPC Peering

TérminoDefinición
VPC Peering ConnectionConexión de red entre dos VPCs que permite enrutar tráfico usando IPs privadas a través de la infraestructura de AWS.
CIDR solapadoCondición donde dos VPCs tienen rangos de direcciones IP que se superponen, impidiendo establecer un peering.
Enrutamiento transitivoCapacidad de enrutar tráfico a través de una VPC intermediaria — no soportado en VPC Peering.
NACL (Network ACL)Firewall stateless a nivel de subnet. Evalúa reglas de entrada y salida independientemente.
Peering Connection ID (pcx-...)Identificador único de la conexión de peering, usado como target en las entradas de las tablas de rutas.

Related Posts

Comentarios

Entradas populares de este blog

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

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