This project provides an automated solution for deploying a secure multi-VPC network infrastructure on AWS using Terraform. It creates two interconnected VPCs with public and private subnets, VPC peering, flow logging, and EC2 instances, enabling secure and monitored communication between isolated network environments.
This infrastructure implements AWS networking best practices including:
- Isolated network segments with public and private subnets
- Secure VPC peering for inter-VPC communication
- Comprehensive network monitoring with VPC Flow Logs to CloudWatch
- Granular access control with security groups and NACLs
- Automated state management with S3 and DynamoDB backend
The project is organized into the following modules:
- Root Module: Orchestrates the entire infrastructure deployment
- VPC Module: Creates VPC, subnets, security groups, and NACLs
- EC2 Module: Deploys EC2 instances in public and private subnets
- Two fully configured VPCs with public and private subnets
- VPC peering connection for inter-VPC communication
- Internet gateways for public internet access
- Security groups with least-privilege access controls
- Network ACLs for subnet-level security
- CloudWatch Log Group for VPC Flow Logs
- Customizable log retention periods
- Traffic monitoring for security and compliance
- EC2 instances in both public and private subnets for each VPC
- Enhanced security with IMDSv2 enforcement
- Elastic IPs for public instances
- IAM roles and policies with least privilege
- Security groups with specific ingress/egress rules
- Network ACLs for additional network security
- VPC Flow Logs for network traffic monitoring
- AWS CLI installed and configured with appropriate credentials
- Terraform >= 1.0.0
- AWS account with appropriate permissions
- Key pair created in AWS for EC2 instance access
- Choose one of the following authentication methods:
~/.aws/config
- Contains configuration settings like region, output format~/.aws/credentials
- Contains your access keys
# Create the .aws directory (if it doesn't exist)
# Windows
mkdir %USERPROFILE%\.aws
# macOS/Linux
mkdir -p ~/.aws
# Create/edit the credentials file
# Windows
notepad %USERPROFILE%\.aws\credentials
# macOS/Linux
nano ~/.aws/credentials
# Add your credentials
[default]
aws_access_key_id = YOUR_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY
# Create/edit the config file
# Windows
notepad %USERPROFILE%\.aws\config
# macOS/Linux
nano ~/.aws/config
# Add your configuration
[default]
region = <your-aws-region>
output = json
aws configure
# Then enter your access key, secret key, region, and output format when prompted
# Windows
set AWS_ACCESS_KEY_ID=your_access_key
set AWS_SECRET_ACCESS_KEY=your_secret_key
set AWS_REGION=<your-aws-region>
# macOS/Linux
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export AWS_REGION=<your-aws-region>
- For production environments, consider using AWS IAM Roles with AssumeRole.
- For enterprise environments, consider integrating with AWS SSO.
Learn more about authentication methods in the Terraform AWS Provider Documentation.
First, set up the S3 bucket and DynamoDB table for Terraform state management:
# Make the script executable
chmod +x setup_terraform_backend.sh
# Run the script
./setup-remote-state.sh
This script creates:
- An S3 bucket for state storage with versioning and encryption and DynamoDB table for state locking
- Remote state storage ensures team collaboration
# For a new project (no existing state)
terraform init
# For existing project with local state files
terraform init -migrate-state
# Preview the changes
terraform plan
# Apply the configuration
terraform apply -auto-approve
The infrastructure establishes a VPC peering connection between VPC-1 and VPC-2, allowing direct communication between resources in both VPCs:
resource "aws_vpc_peering_connection" "vpc_peering" {
vpc_id = module.vpc_1.vpc_id
peer_vpc_id = module.vpc_2.vpc_id
auto_accept = false
tags = {
Name = "Peering-${var.vpc_configs.vpc1.name}-to-${var.vpc_configs.vpc2.name}"
Side = "Requester"
Environment = var.environment
}
}
Routes are automatically configured in all route tables to enable traffic flow between the VPCs.
VPC Flow Logs are configured to capture network traffic for VPC-1:
resource "aws_flow_log" "vpc1_flow_log" {
log_destination = aws_cloudwatch_log_group.vpc_flow_logs_group.arn
log_destination_type = "cloud-watch-logs"
traffic_type = var.flow_logs_config.traffic_type
vpc_id = module.vpc_1.vpc_id
iam_role_arn = aws_iam_role.vpc_flow_logs_role.arn
max_aggregation_interval = var.flow_logs_config.aggregation_interval
tags = {
Name = "${var.vpc_configs.vpc1.name}-FlowLog"
Environment = var.environment
}
}
The logs are stored in CloudWatch and can be used for security analysis, troubleshooting, and compliance.
The VPC module creates a complete VPC infrastructure including:
- VPC with custom CIDR block
- Public and private subnets
- Internet Gateway
- Route tables
- Security groups
- Network ACLs
For detailed documentation, see the VPC Module README.
The EC2 module deploys EC2 instances in both public and private subnets:
- Public instance with Elastic IP
- Private instance without public internet access
- Security group associations
- IMDSv2 configuration for enhanced security
For detailed documentation, see the EC2 Module README.
The infrastructure enables secure communication between two VPCs through VPC peering, with traffic flowing through public and private subnets. VPC Flow Logs capture all network traffic for monitoring and analysis.
VPC Peering
VPC-1 <-------------------------> VPC-2
| |
| |
Internet Internet
Gateway Gateway
| |
v v
Public Subnet <---> Private Subnet Public Subnet <---> Private Subnet
| | | |
v v v v
EC2 Instance EC2 Instance EC2 Instance EC2 Instance
Key Component Interactions:
- Internet traffic flows through Internet Gateways to public subnets
- Private subnets can communicate with public subnets in the same VPC
- VPC peering enables direct communication between VPCs
- Security groups control instance-level access
- NACLs provide subnet-level security
- VPC Flow Logs capture all network traffic
- CloudWatch stores and manages flow logs
To add more VPCs, extend the vpc_configs
variable in your terraform.tfvars
file:
vpc_configs = {
vpc1 = { ... },
vpc2 = { ... },
vpc3 = {
name = "VPC-3"
cidr_block = "10.3.0.0/16"
public_subnet_cidr = "10.3.0.0/24"
private_subnet_cidr = "10.3.1.0/24"
availability_zone = "ap-south-1a"
create_internet_gateway = true
}
}
Then update the main.tf file to create the new VPC and establish peering connections.
To enable flow logs for VPC-2 or additional VPCs, add a new flow log resource:
resource "aws_flow_log" "vpc2_flow_log" {
log_destination = aws_cloudwatch_log_group.vpc_flow_logs_group.arn
log_destination_type = "cloud-watch-logs"
traffic_type = var.flow_logs_config.traffic_type
vpc_id = module.vpc_2.vpc_id
iam_role_arn = aws_iam_role.vpc_flow_logs_role.arn
max_aggregation_interval = var.flow_logs_config.aggregation_interval
tags = {
Name = "${var.vpc_configs.vpc2.name}-FlowLog"
Environment = var.environment
}
}
After deploying the infrastructure, we can verify that the VPC peering connection is working correctly:
-
Connect to VPC-1's public EC2 instance ("public-server") using EC2 Instance Connect in the AWS Console
-
Obtain the private IP address of VPC-2's public EC2 instance from the AWS Console or Terraform outputs
-
Run the following command to test connectivity across the VPC peering connection:
ping <VPC-2's Public EC2 instance's Private IPv4 address>
-
We should see successful ping replies, confirming that traffic is flowing between the VPCs through the peering connection. The instances are communicating via their private IP addresses across VPCs.
To verify, review the VPC Flow Logs to monitor and analyze network traffic:
- Navigate to CloudWatch in the AWS Console
- Go to Log groups > VPCFlowLogsGroup > Log Streams
- Select the log stream for VPC-1
- We should see entries for the ping traffic we generated in the previous step
- The logs will show source and destination IP addresses, ports, protocol (ICMP for ping), and whether the traffic was accepted or rejected
- Look for records with source and destination IPs matching the VPC CIDR blocks
- Flow logs include: source/destination IPs, ports, protocol, packet counts, etc.
- Identify the ICMP traffic (protocol 1) from the ping test
- Verify the source IP (VPC-1 instance) and destination IP (VPC-2 instance)
- Confirm that traffic was accepted by security groups and NACLs
Flow log entries confirm that the traffic is flowing between the VPCs as expected through the peering connection. These logs are valuable for security analysis, troubleshooting network connectivity issues, and compliance reporting.
- Error: "VPC Peering Connection not in 'active' state"
Solution: Ensure both VPCs exist and auto-accept is enabled
# Verify peering connection status aws ec2 describe-vpc-peering-connections --region ap-south-1
- Error: "InvalidParameterException: The specified log group does not exist"
Solution: Ensure IAM roles and policies are correctly configured
# Verify log group exists aws logs describe-log-groups --region ap-south-1
- Error: Unable to SSH into private instances
- Solution: Ensure we're connecting through the public instance as a bastion host
- Least Privilege: The IAM roles and policies follow the principle of least privilege
- Network Isolation: Private subnets are not directly accessible from the internet
- Traffic Monitoring: VPC Flow Logs capture all network traffic for security analysis
- IMDSv2 Enforcement: EC2 instances require token-based metadata access
- Security Groups: Inbound and outbound traffic is restricted based on specific rules
Contributions to this project are welcome. Please follow these steps to contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/your-feature-name
) - Commit your changes with clear, descriptive messages
- Ensure all Terraform configurations pass validation (
terraform validate
) - Update documentation as needed
- Submit a Pull Request with a comprehensive description of changes
For major changes or features, please open an issue first to discuss what we would like to change.
MIT
Heeyaichen Konsam