Setting up a Hardware VPN connection to your AWS VPC using CloudFormation – For Dummies

In this post, we will see a detailed step by step guide for configuring a Site-to-Site, Hardware VPN connection using AWS CloudFormation.

Types of VPN connections 

There are primarily 2 types of VPN connections :

Site-to-site VPN and Remote access VPN

1) Site-to-site ( S-2-S ) VPN : Site-to-site VPN’s connect entire networks to each other – for example, connecting your entire customer network to your VPC ( Virtual Private Cloud ).

2) Remote access VPN : They connect individual hosts to private networks – for example, developers working from their homes who need to access the VPC.

For more detailed information, refer to Whats-the-difference-between-site-to-site-and-remote-vpn?

Site-to-site VPN can be further distinguished into 2 types :

1) Hardware VPN : These use dedicated hardware VPN appliances which are managed entirely by the cloud hosting service. The advantages of using a H/W VPN is that reliability, high availability, security, maintenance and performance is entirely the headache of the service provider. The con is that data transfer is quite costly and only a S-2-S VPN is possible, remote access isn’t.

2) Software VPN : These use softwares such as OpenSwan or OpenVPN configured on a machine inside your VPC. The advantages are low cost and possibility of having either a S-2-S or a remote access solution. On the other side, management of the VPN connection is entirely in your hands.

We will be setting up a Site-to-Site, Hardware VPN connection as per the steps below.

Prerequisites

1) You should have an existing AWS account.

2) Install the AWS CLI as per the instructions here : http://docs.aws.amazon.com/cli/latest/userguide/installing.html

3) Once the CLI is installed, configure it as per the instructions here : http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html

4) Commands you need to know :

Create a stack : aws cloudformation create-stack –stack-name YourStackName –template-body file://your_cf_template.json

Update a stack : aws cloudformation update-stack –stack-name YourStackName –template-body file://your_cf_template.json

And you are ready to go!

Step 1 : Create a VPC

"Resources" : {
  "myVPC" : {
    "Type" : "AWS::EC2::VPC",
    "Properties" : {
      "CidrBlock" : "10.0.0.0/16",
      "Tags" : [ {"Key" : "Name", "Value" : "My Test VPC"} ]
    }
  }
}

Enter the above code in a json file and run the “create stack” command. Poof! A VPC will be created (having the CIDR range specified) which can be checked in the web console.

Step 2 : Create a customer gateway configuration

Once the VPC is created, lets create a customer gateway. Add the below code, to the “Resources” object.

 "myVpcCustomerGateway": {
         "Type": "AWS::EC2::CustomerGateway",
         "Properties": {
              "BgpAsn": 65000,
              "IpAddress": "Internet facing IP of the customer gateway",
              "Tags": [
                    {
                        "Key": "Name",
                        "Value": "My Test Customer Gateway"
                    }
              ],
              "Type": "ipsec.1"
         }
}

Now, every time we change the stack, we will run the “update stack” command. When you run this command, a customer gateway will be created.

Important Note : There are 2 types of routing, static and dynamic.  For dynamic routing, the customer gateway device should support the Border Gateway Protocol. Dynamic routing should be used for high availability across multiple VPN connections. Static routing is used when you don’t need to route your traffic via an alternate VPN connection when one VPN connection fails.

When dynamic routing is chosen, you need to provide a BgpAsn number of your customer gateway. It is not needed for static routing.

CloudFormation however has an open issue because of which, providing a BgpAsn is mandatory. The trick here is that if we need static routing, we give a default value of the BgpAsn eg. 65000.

Step 3 : Create a virtual private gateway

"myVpcVpnGateway": {
       "Type": "AWS::EC2::VPNGateway",
       "Properties": {
            "Type": "ipsec.1",
            "Tags": [
                {
                        "Key": "Name",
                        "Value": "My Test VPN Gateway"
                }
             ]
       }
}

Step 4 : Attach the VPN Gateway created above to your VPC

"myVpcVpnGatewayAttachment" : {
       "Type" : "AWS::EC2::VPCGatewayAttachment",
       "Properties" : {
              "VpcId" : {"Ref" : "myVPC"},
                "VpnGatewayId" : { "Ref" : "myVpcVpnGateway" }
       }
}

Step 4 : Create a VPN connection

"myVpcVpnConnectionPrimary": {
       "Type": "AWS::EC2::VPNConnection",
       "Properties": {
           "Type": "ipsec.1",
           "CustomerGatewayId": {
             "Ref":"myVpcCustomerGateway"
            },
            "StaticRoutesOnly": true,
            "Tags": [
               {
                    "Key": "Name",
                    "Value": "My Test VPN Connection"
               }
             ],
             "VpnGatewayId": {
               "Ref" : "myVpcVpnGateway"
             }
       }
}

The “StaticRoutesOnly” option should be set to true if you choose the static routing option. If dynamic routing is chosen, this field need not be added.

Ok, let’s pause for a second. Once the above step is completed, this is what you have achieved :

Obviously, the connection will not be up until the customer gateway is configured, but this is how traffic will be routed from your customer network to your VPC. For each VPN connection, AWS provides you 2 tunnels which is their way of achieving high availability. The route table and the connection highlighted in red will be achieved via the next step ( This is the reverse routing process from your VPC back to your network ).

Step 5 : Allow propagation of the static routes to the main route table of the VPC

 "myVpcVpnGatewayRouteProp" : {
        "Type" : "AWS::EC2::VPNGatewayRoutePropagation",
        "Properties" : {
            "RouteTableIds" : ["rtb-1a3cab7f"],
            "VpnGatewayId" : {"Ref" : "myVpcVpnGateway"}
        },
        "DependsOn" : "myVpcVpnGatewayAttachment"
}

Step 6 : Add a static route from the customer network to your VPC

"myVpcConnectionRoutePrimary" : {
       "Type" : "AWS::EC2::VPNConnectionRoute",
       "Properties" : {
          "DestinationCidrBlock" : "A static IP within your customer network",
          "VpnConnectionId" : {"Ref" : "myVpcVpnConnectionPrimary"}
       }
}

Congrats! Your side of the work is done!!
Now, on your AWS console, on the “VPN connections” tab, for the VPN connection you have just created there will be a “Download Configuration” file. Download the file and provide it to your network administrator. You also need to provide two other things : a) The 2 tunnel IP’s which AWS provides you and b) The entire range of IP addresses you want to access from your network. Once the customer gateway is configured, your VPN connection is up and running!

Testing your connection 

Create a subnet in your VPC and launch an instance in it. Set the ACL of the subnet and the security group of the instance to allow communication. Now, from your customer network ping a machine in your VPC using its private IP. If the ping is successful, you have setup your VPN connection!

8 Comments

Add yours →

  1. Nicely explained about AWS VPC and VPN setup.
    Thank you for your contribution to tech world.

    Liked by 1 person

  2. Thanks.
    A couple of comments/questions:
    1. The format of the CloudFormation json file should wrap it all in a ‘{“AWSTemplateFormatVersion”: “2010-09-09″…}’ object.
    2. How can the “AWS::EC2::VPNGatewayRoutePropagation” resource find the RouteTableId automatically?

    Like

    • Thanks Amos.
      The VPNGatewayRoutePropagation can find the RouteTableId directly by specifying a reference as follows :
      “RouteTableIds”: [{“Ref” : “PrivateRouteTable”}] where PrivateRouteTable refers to the route table you have created with the same name.

      Like

      • Hi Yahya Poonawala,
        Can you offer some insight into the difference between AWS::EC2::VPNConnectionRoute and AWS::EC2::VPNGatewayRoutePropagation? Before reading your article I assumed that I could just create AWS::EC2::VPNConnectionRoute for each of the static routes I wanted defined. Is it required to define a routing table and use AWS::EC2::VPNGatewayRoutePropagation instead?

        Like

  3. Is there a way to pre-establish the VPG and VPN connection so I can just attach a new VPC created in my CloudFormation template ?

    I’d hate to have to bother our network admin to reconfigure our corporate router every time I delete / create my CloudFormation stack.

    Like

  4. Thank you for publishing this awesome article. I’m a long time reader but I’ve
    never been compelled to leave a comment. I subscribed to your blog
    and shared this on my Twitter. Thanks again for this
    great article!

    Liked by 1 person

  5. One sidenote, that route table(s) must be subnet routetables, not the main table of vpc or vpn routing is not working.

    Like

Leave a comment