Network Security

AWS Site-to-Site VPN: Connecting On-Premise to Cloud

A step-by-step guide to establishing a secure IPSec tunnel between a corporate VPC and a remote network using both Manual Configuration (Openswan) and Terraform.

The Scenario

In this guide, we simulate a real-world hybrid cloud environment. We will connect a "Company HQ" (VPC A) to a "Remote CEO Office" (VPC B/On-Prem). While we use two VPCs for demonstration, the "CEO Office" acts exactly like a physical on-premise data center firewall.

Figure 1: High-level data flow through the encrypted tunnel.

1. Manual Configuration (The Hard Way)

Understanding the manual setup is crucial for debugging. We will configure the AWS side first, then the Linux-based router (Openswan) on the remote side.

Virtual Private Gateway (VGW)

Attached to the AWS VPC. Think of this as the "AWS side anchor" of the VPN cable.

Customer Gateway (CGW)

A logical representation of your remote device. It defines the IP address of the "Remote side anchor."

Step-by-Step AWS Setup

  1. VPC Creation: Create two VPCs with non-overlapping CIDRs (e.g., 10.0.0.0/16 and 192.168.0.0/16).
  2. Create VGW: In the VPC Dashboard, create a Virtual Private Gateway and Attach it to the "Company VPC".
  3. Create CGW: Create a Customer Gateway. Crucial: Use the Static Public IP of the "CEO/Remote" EC2 instance.
  4. Route Propagation: Go to Route Tables → Route Propagation → Enable. This automatically adds VPN routes.
  5. Create Connection: Create the Site-to-Site VPN Connection. Select the VGW and CGW created above.

Configuring Openswan (The Remote Router)

Once the VPN status is Pending in AWS, download the Generic Vendor Configuration file. SSH into your "Remote" EC2 instance (acting as the on-prem router).

Important: Ensure Source/Destination Checks are disabled on the EC2 instance acting as the router, or packets will be dropped.

1. System Configuration:

# Install Openswan
yum install openswan -y

# Enable IP Forwarding (Crucial for routing traffic)
vim /etc/sysctl.conf
# Add:
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0

# Apply changes
sysctl -p

2. Define the Secret Keys:

Edit /etc/ipsec.d/aws.secrets. Replace the IPs with the Tunnel 1 Outside IP from your AWS config file.

# Format: [Customer_Public_IP] [AWS_Tunnel_IP]: PSK "Your_Pre_Shared_Key"
54.12.34.56 203.0.113.10: PSK "mx_8473..."

3. Configure the Tunnel:

Edit /etc/ipsec.d/aws.conf.

conn Tunnel1
    authby=secret
    auto=start
    left=%defaultroute
    leftid=54.12.34.56  # Your EC2 Public IP
    right=203.0.113.10  # AWS Tunnel IP
    type=tunnel
    ikelifetime=8h
    keylife=1h
    phase2alg=aes128-sha1;modp1024
    ike=aes128-sha1;modp1024

4. Start Service: service ipsec start


2. Terraform Automation (The Easy Way)

For production environments, Infrastructure as Code (IaC) is preferred to ensure consistency. Below is a concise Terraform module to deploy the AWS side of the architecture.

resource "aws_vpn_gateway" "main" {
  vpc_id = aws_vpc.company_vpc.id
  tags   = { Name = "Main-VGW" }
}

resource "aws_customer_gateway" "remote" {
  bgp_asn    = 65000
  ip_address = var.remote_public_ip
  type       = "ipsec.1"
  tags       = { Name = "Remote-Office-CGW" }
}

resource "aws_vpn_connection" "site2site" {
  vpn_gateway_id      = aws_vpn_gateway.main.id
  customer_gateway_id = aws_customer_gateway.remote.id
  type                = "ipsec.1"
  static_routes_only  = true
}

resource "aws_vpn_connection_route" "office" {
  destination_cidr_block = var.remote_cidr
  vpn_connection_id      = aws_vpn_connection.site2site.id
}
variable "remote_public_ip" {
  description = "The Public IP of the On-Prem Firewall"
}
variable "remote_cidr" {
  description = "The internal network of the remote office"
  default     = "192.168.1.0/24"
}

3. Verification & Troubleshooting 🔧

The configuration is only half the battle. Here is how to verify the tunnel is actually passing traffic.

Navigate to the Site-to-Site VPN Connections tab. Click on "Tunnel Details". You should see Status: UP for at least one tunnel. If it says DOWN, check your Security Groups to ensure UDP port 500 and 4500 are open.

From an instance in the Company VPC, ping the Private IP of the Remote instance: ping 192.168.1.50.
Note: Pinging the Public IP will go over the internet, not the VPN. Always ping private IPs to test the tunnel.