Skip to main content

Ensure Routing Tables for VPC Peering Are Least Access

Overview

This check ensures that your VPC peering route tables follow the principle of least privilege. Instead of routing all traffic or entire VPC CIDR blocks through a peering connection, you should only route traffic to the specific subnets that actually need to communicate.

Risk

When VPC peering routes are too broad (like 0.0.0.0/0 or an entire VPC CIDR), you create unnecessary network exposure:

  • Lateral movement: An attacker who compromises one VPC could potentially reach resources in the peered VPC that should not be accessible
  • Data exposure: Sensitive resources may become reachable across the peering connection unintentionally
  • Routing conflicts: Overly broad routes can cause traffic to be misrouted, especially with overlapping IP ranges

Remediation Steps

Prerequisites

You need permission to view and modify VPC route tables. If you plan to use the AWS CLI, ensure it is installed and configured.

AWS Console Method

  1. Open the VPC Console
  2. Click Route tables in the left navigation
  3. Select a route table associated with subnets that use VPC peering
  4. Click the Routes tab to review existing routes
  5. Identify any routes targeting a peering connection (pcx-xxxxx) that use:
    • 0.0.0.0/0 (all IPv4 traffic)
    • The entire peer VPC CIDR (e.g., 10.0.0.0/16)
  6. For each overly broad route:
    • Click Edit routes
    • Delete the broad route
    • Add new routes for only the specific subnets you need to reach (e.g., 10.0.1.0/24, 10.0.2.0/24)
    • Click Save changes
  7. Repeat for all route tables in both VPCs involved in the peering connection

Tip: Document which subnets actually need to communicate before making changes. If you are unsure, consult your network team or review VPC Flow Logs.

AWS CLI (optional)

List VPC Peering Connections

aws ec2 describe-vpc-peering-connections \
--region us-east-1 \
--query 'VpcPeeringConnections[*].{ID:VpcPeeringConnectionId,RequesterVPC:RequesterVpcInfo.VpcId,AccepterVPC:AccepterVpcInfo.VpcId,Status:Status.Code}' \
--output table

View Routes in a Specific Route Table

aws ec2 describe-route-tables \
--region us-east-1 \
--route-table-ids <your-route-table-id> \
--query 'RouteTables[0].Routes[?VpcPeeringConnectionId!=`null`]'

Find Route Tables with Peering Routes

aws ec2 describe-route-tables \
--region us-east-1 \
--query 'RouteTables[?Routes[?VpcPeeringConnectionId!=`null`]].{RouteTableId:RouteTableId,VpcId:VpcId}'

Delete an Overly Broad Route

aws ec2 delete-route \
--region us-east-1 \
--route-table-id <your-route-table-id> \
--destination-cidr-block 10.0.0.0/16

Add a Specific Subnet Route

aws ec2 create-route \
--region us-east-1 \
--route-table-id <your-route-table-id> \
--destination-cidr-block 10.0.1.0/24 \
--vpc-peering-connection-id <your-peering-connection-id>

Example: Replace Broad Route with Specific Subnets

# Remove the broad route
aws ec2 delete-route \
--region us-east-1 \
--route-table-id rtb-12345678 \
--destination-cidr-block 10.0.0.0/16

# Add specific subnet routes
aws ec2 create-route \
--region us-east-1 \
--route-table-id rtb-12345678 \
--destination-cidr-block 10.0.1.0/24 \
--vpc-peering-connection-id pcx-abcdef12

aws ec2 create-route \
--region us-east-1 \
--route-table-id rtb-12345678 \
--destination-cidr-block 10.0.2.0/24 \
--vpc-peering-connection-id pcx-abcdef12
CloudFormation (optional)

Use CloudFormation to define specific subnet routes for VPC peering. This template adds a single route; deploy multiple stacks or modify for additional routes.

AWSTemplateFormatVersion: '2010-09-09'
Description: VPC Peering with Least Privilege Routing

Parameters:
PeeringConnectionId:
Type: String
Description: The VPC Peering Connection ID
RouteTableId:
Type: String
Description: The Route Table ID to configure
DestinationCidrBlock:
Type: String
Description: Specific subnet CIDR to route (e.g., 10.1.1.0/24)
AllowedPattern: ^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$

Resources:
PeeringRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref RouteTableId
DestinationCidrBlock: !Ref DestinationCidrBlock
VpcPeeringConnectionId: !Ref PeeringConnectionId

Outputs:
RouteTableId:
Description: The Route Table ID that was configured
Value: !Ref RouteTableId

Deploy with:

aws cloudformation deploy \
--region us-east-1 \
--template-file peering-route.yaml \
--stack-name vpc-peering-route-app-subnet \
--parameter-overrides \
PeeringConnectionId=pcx-abcdef12 \
RouteTableId=rtb-12345678 \
DestinationCidrBlock=10.0.1.0/24
Terraform (optional)

Use Terraform to manage specific peering routes. This configuration creates routes for a list of specific CIDRs.

variable "route_table_id" {
description = "The ID of the route table to configure"
type = string
}

variable "vpc_peering_connection_id" {
description = "The ID of the VPC peering connection"
type = string
}

variable "destination_cidr_blocks" {
description = "List of specific subnet CIDRs to route through the peering connection"
type = list(string)
}

resource "aws_route" "peering_routes" {
count = length(var.destination_cidr_blocks)
route_table_id = var.route_table_id
destination_cidr_block = var.destination_cidr_blocks[count.index]
vpc_peering_connection_id = var.vpc_peering_connection_id
}

Example terraform.tfvars:

route_table_id            = "rtb-12345678"
vpc_peering_connection_id = "pcx-abcdef12"
destination_cidr_blocks = [
"10.0.1.0/24", # Application subnet
"10.0.2.0/24" # Database subnet
]

Apply with:

terraform init
terraform plan
terraform apply

Verification

After making changes, confirm that:

  1. Your applications can still communicate as expected across the peering connection
  2. Route tables only contain specific subnet CIDRs (not 0.0.0.0/0 or entire VPC CIDRs) for peering targets
CLI Verification Commands

Check Routes for a Peering Connection

aws ec2 describe-route-tables \
--region us-east-1 \
--route-table-ids <your-route-table-id> \
--query 'RouteTables[0].Routes[?VpcPeeringConnectionId!=`null`].{Destination:DestinationCidrBlock,Target:VpcPeeringConnectionId}'

Find Any Remaining Broad Routes

Look for routes with /16 or larger prefixes (smaller prefix number = broader route):

aws ec2 describe-route-tables \
--region us-east-1 \
--query 'RouteTables[*].Routes[?VpcPeeringConnectionId!=`null`]' \
--output table

Additional Resources

Notes

  • Symmetric routing: Remember to configure routes in both VPCs. If VPC A needs to reach subnet X in VPC B, and VPC B needs to reach subnet Y in VPC A, configure routes on both sides.
  • Security groups and NACLs: Route tables control where traffic can flow, but security groups and network ACLs control whether it is allowed. Use all three for defense in depth.
  • Testing: Test connectivity after changes. Use tools like ping, telnet, or AWS Reachability Analyzer to verify expected paths still work.
  • Transit Gateway alternative: If you have many VPCs that need to communicate, consider using AWS Transit Gateway instead of multiple peering connections. It provides centralized routing control.