What You’ll Learn

What You’ll Need

Note: The cost for a VPC with a connected VPN is about $40 per month. For testing and validation, the cost will be minimal, but ensure that you tear down the VPN after your testing is complete. Additionally, in this tutorial, a virtual Cisco Catalyst 8000 router will be used. Configurations may need to be adjusted based on the router operating system and version.

The high-level architecture and terms to create this VPN connection are given below. Note that these terms are specific to AWS, and while similar constructs may exist within other cloud providers, they may not be called the same.

AWS VPN Diagram

Before any VPN connection can be established, an AWS VPC must be created. A VPC is an AWS representation of a logically segmented network, within which resources like compute instances, VPNs, or Kubernetes clusters can be instantiated. For this tutorial, we’ll simply use the VPC to create our customer VPN gateway separate from the rest of our cloud resources, but in a production example, this VPC could be holding a variety of resources that would then be accessed over the VPN.

Creating the AWS VPC

Begin by logging in to your AWS console and accessing the VPC configuration service by searching for VPC.

VPC search

Once at the VPC landing page, click Create VPC in the upper-right corner of the window.

New VPC creation

This will display the VPC creation menu. Because we will be creating all resources manually, select the VPC only radio button and fill in the required information. Ensure that the Classless Inter-Domain Routing (CIDR) block is unique from your existing subnets within your local network.

New VPC CIDR

Creating the Subnet, Associating to the VPC

The next step will be to carve out a subnet from the CIDR block that will be associated with the VPN. This is done by selecting Subnets from the left side of the window, then clicking the New Subnet button in the upper-right corner of the subnets control pane.

Creating new subnets

When the Create Subnet menu appears, you will need to select a VPC to which the subnet will be attached. By selecting the VPC you created in the previous step, the top-level CIDR block associated with that VPC will be populated. The subnet that you will create must be carved out of that VPC’s CIDR block. (In the example, a /25 out of the original /24 is used.) Once the required information has been filled in, click Create Subnet.

New subnet window

Creating the Customer Gateway

Next, we’ll create the customer gateway, which is the configuration object that provides details of your on-premises connection to AWS. To access the “Customer gateways” configuration page, you may need to scroll down the left pane of the window until you reach the “Virtual private network (VPN)” configuration section. Once at the Customer gateways configuration, click Create customer gateway.

Create customer gateway

In the resulting configuration window, you’ll need to add a name, Border Gateway Protocol (BGP) autonomous system number (in case you wish to have BGP running to exchange routes; this example will use static routing), and the public IP address of the VPN headend router on premises. In a production environment, this device would have the public IP address attached to one of its interfaces. However, if you have an environment (like mine) where your VPN router is behind Network Address Translation (NAT), use the public IP address assigned from your ISP. (If you receive a DHCP address, a service like https://www.whatismyip.com can be used to find your public IP.)

Create CGW window

Once the information has been populated, click Create customer gateway.

The first part of the VPN network plumbing has been completed. The next steps will focus on completing the AWS side of the VPN as well as tuning the security policies (key exchange, encryptions, and so on).

Creating the VPG

Whereas the customer gateway was a configuration object that told AWS where the on-premises VPN endpoint resides, the VPG sets up the “VPN concentrator” within the AWS infrastructure. This is accessed under the “Virtual private network (VPN)” configuration section. Once selected, click Create virtual private gateway. The configuration options for this are straightforward.

Create VPG

In this example, we’ll just use the default autonomous system options from AWS, though it won’t be necessary; we will only be doing static peering over the VPN.

Once the VPG has been created, it will need to be associated to a VPC. This is done by selecting the newly created VPG using the radio button and then clicking the Actions button toward the upper right of the window. Once the drop-down menu appears, select Attach to VPC.

Associate VPG to VPC

Once the Attach to VPC dialog box appears, select the VPC that was created earlier as the attachment point. This will connect the disparate parts of the configuration together.

Attachment

Creating the Route Table

Now that we have the VPG set up, we can create the route table for the VPN connection. This is done by selecting the Route tables menu item under the Virtual Private Cloud section. Click Create route table.

The next step will be to create the route table itself. This is done by providing a name, then binding to the VPC that we created in the previous steps, and then clicking Create new route table.

Creating the route table

Once that is complete, you will be returned to view all created route tables. From here, you’ll need to select the route table that you just created, then click Subnet associations in the middle of the window, followed by Edit subnet associations.

Associating the subnet

This will bring up a new window in which the subnet created earlier can be associated to the route table. Select the subnet created previously, and save the association by clicking the button in the lower-right corner.

Subnet association dialogue

The final component in creating the route table is to allow the VPG to propagate routes into the VPC. This is done by selecting the route table, then clicking the Route Propagation menu item in the middle of the screen. From there, click Edit route propagation.

Note: You should notice that your VPG is already listed under the “Route propagation” tab. This VPG should indicate that it is not configured for propagation.

Route propagation defaults

When the “Edit route propagation” window loads, check the enable box for the VPG that you created in a previous step, then click Save.

Propagate da routes!

Creating the VPN Connection

At this point, all the scaffolding has been created for the VPN to be initiated. The only remaining piece is to create the VPN connection itself, which binds the customer gateway and VPG together, along with the VPN-related security policies (encryption, Diffie-Hellman key, and so on).

Begin by choosing Site-to-Site VPN connections from the left pane and then selecting Create VPN connection. This will bring up a new window with a few different configuration sections.

The first section deals with the association of the customer gateway to the VPG. You’ll need to provide a name for the VPN connection, then select the previously created VPG and customer gateways.

Create VPN connection window

Below this section, routing is defined between the AWS and customer endpoints. In our example, we’ll use static routing and define the remote side subnets that will be allowed to communicate over the VPN (the 192.168.128.0/24 subnet in my case).

Routing options

The next steps are related to the tunnel options for the IPsec connections. By default, AWS will create two tunnels for the VPN, both of which will need to be established, so whichever options are selected for Tunnel 1, be sure to duplicate for Tunnel 2.

Start by expanding the Tunnel 1 options by clicking the arrow next to the text. Inside CIDRs and keys are left at their defaults for AWS to generate; more on this later. The next step is changing the encryption, integrity, and Diffie-Hellman groups. By default, all possible methods are selected; however, based on the Cisco Next Generation Cryptography document (Appendix A), the following minimums should be adhered to:

Using this information, we can select the following options:

VPN options part 1

VPN options part 2

Nearly all the rest of the options can be left at the default values. In the test example, some values toward the bottom of the VPN connection settings have been changed. These are the “Startup action” radio button and the “Tunnel activity log” check box.

The Startup action indicates which side should initiate the connection. By default, the Add action will suffice; this means that the on-premises router will initiate the connection (and it is required if the public IP address of the tunnel changes because of DHCP). In the Start setting, the AWS tunnel will initiate the connection (and you must have a static IP address).

The Tunnel activity log option will log all VPN activity to an AWS CloudWatch logging group. This will potentially incur additional costs if the VPN is left long term, but it will allow for deeper visibility into the AWS side of the VPN. Additionally, the CloudWatch log group must be set up prior to selecting this option. (CloudWatch can be opened by searching for CloudWatch in the AWS service search at the top of the console window.)

Tunnel logging and activity

Once this is complete, click Create VPN connection at the bottom of the window. The VPN configuration within AWS is now complete.

Ensuring Access via Security Groups

While the VPN configuration is complete, a security group must be created that allows communication from your IP address to the AWS VPC. (Think of this like an ACL that allows access.) To create a new security group, scroll up to Security Groups under the Security menu on the left side, and click Create security group.

Once the “Create security group” window appears, give the security group a name and then associate it to the VPC that we created for this VPN. Unfortunately, the names of the VPCs are not given when a VPC is selected—only the VPC ID value. The easiest way to ensure that the correct VPC is chosen is to select the X next to the pre-populated VPC ID, then click in the box again. This will provide a drop-down of all of the VPCs within your account, with names of the VPCs. (Once the VPC is selected, the name will disappear.)

We now need to ensure that an inbound traffic rule is created for the VPC. By default, all traffic is blocked unless the VPC initiates it (which is covered in the outbound rule). Scroll down to Inbound rules and create a new rule. This can be as permissive or restricted as desired. For this example, I’m allowing all traffic from a given IP address. (I’m obscuring mine using 1.1.1.1, but there is a drop-down menu item that says “MyIP,” which will read your public IP address and insert it as a /32 route in the rules automatically.)

Security group config

Once the rule has been created and the security group appears as desired, click Create security group.

We’re now ready to stand up the VPN connection!

Now that the VPN infrastructure has been created, we can begin to configure our on-premises router to connect to the AWS native VPN infrastructure.

Downloading Prebuilt AWS Configuration

AWS will provide a configuration for your devices, which can serve as a template for about 80 percent of the configuration if desired. This is found by going back to Site-to-Site VPN connections in the left window and then selecting the radio button of the VPN connection that was built through our previous steps. Once selected, the Download Configuration button at the upper right of the window will “un-gray” and allow you to click it. Once clicked, a pop-up window will appear, allowing you to select which vendor, platform, and OS version you are running. For our configuration, we should use the following parameters:

VPN configuration download options

We can then select Download and have the templated configuration delivered to our workstation. Once the configuration file is downloaded, it can be opened with any text editor.

Regardless of whether you use the actual configuration, the file contains some important information regarding the VPN connection, including:

Both of these items could be found on the AWS control panel if needed. For the most part, these configs will work, but there is even a disclaimer at the top of the download configuration pop-up indicating that these configs are just templates and that any advanced configuration will require modification.

Inspecting the Configuration (Why are there two tunnels?)

AWS automatically creates two tunnel endpoints with every VPN connection, and the configuration downloaded reflects this. Unfortunately, the downloaded configuration assumes that the two tunnels will reside on different routers. However, in this example, both tunnels will reside on the same device. Because of this, there is a lot of duplicated configuration (steps 1, 2, and 4 in the downloaded configuration) that can be omitted if you are configuring both tunnels on a single device.

Aside from that, most of the configuration can be applied without issue (depending on ciphers and support of your on-premises router). In this instance, adding the configuration and verifying through the commands show crypto ipsec sa and show crypto ikev2 sa will indicate the status of the VPN tunnel, and debugging each of those items using debug crypto ikev2 packet and debug crypto ipsec will indicate where the error is (assuming that proper configuration exists on the router and its upstreams).

Modified Configuration

For a simplified configuration, you can download the configuration located here. This configuration distills a majority of what the AWS sample config provides as well as simplifies the repetitive config for both tunnels existing on a single device. The main points to replace are as follows:

Some assumptions are made for the fragmentation and maximum segment size (MSS) and maximum transmission unit (MTU). However, in this instance, even if large packets are sent, given that there is no traffic, the CPU load on the device (regardless of physical or virtual) should not be significant.

Once the configuration has been edited and applied to your edge device, the tunnels should connect to AWS. We can verify this using show crypto ikev2 sa [detail], a sample output of which is shown here:

Tunnel-id Local                 Remote                fvrf/ivrf            Status
1         192.168.128.92/4500   18.188.20.197/4500    none/none            READY
      Encr: AES-GCM, keysize: 128, PRF: SHA512, Hash: None, DH Grp:20, Auth sign: PSK, Auth verify: PSK
      Life/Active Time: 86400/3498 sec
      CE id: 0, Session-id: 8
      Local spi: D0FEBF22F785D17A       Remote spi: 087FD023A8444DCB
      Status Description: Negotiation done
      Local id: <local-ip-address>
      Remote id: 18.188.20.197
      Local req msg id:  2              Remote req msg id:  349
      Local next msg id: 2              Remote next msg id: 349
      Local req queued:  2              Remote req queued:  349
      Local window:      5              Remote window:      1
      DPD configured for 10 seconds, retry 2
      IETF Std Fragmentation  enabled.
      Dynamic Route Update: disabled
      IETF Std Fragmentation MTU in use: 1172 bytes.
      Extended Authentication not configured.
      NAT-T is detected inside
      Cisco Trust Security SGT is disabled
      Initiator of SA : No
      PEER TYPE: Other

Tunnel-id Local                 Remote                fvrf/ivrf            Status
7         192.168.128.92/4500   3.22.91.236/4500      none/none            READY
      Encr: AES-GCM, keysize: 256, PRF: SHA512, Hash: None, DH Grp:20, Auth sign: PSK, Auth verify: PSK
      Life/Active Time: 86400/17717 sec
      CE id: 0, Session-id: 9
      Local spi: F7370E5592A6420E       Remote spi: AF46005072767428
      Status Description: Negotiation done
      Local id: <local-ip-address>
      Remote id: 3.22.91.236
      Local req msg id:  12             Remote req msg id:  1763
      Local next msg id: 12             Remote next msg id: 1763
      Local req queued:  12             Remote req queued:  1763
      Local window:      5              Remote window:      1
      DPD configured for 10 seconds, retry 2
      IETF Std Fragmentation  enabled.
      Dynamic Route Update: disabled
      IETF Std Fragmentation MTU in use: 1172 bytes.
      Extended Authentication not configured.
      NAT-T is detected inside
      Cisco Trust Security SGT is disabled
      Initiator of SA : No
      PEER TYPE: Other

Note that the encryption method, key size, Diffie-Helman group, etc. all align with the configuration that we applied to both the AWS and Cisco endpoints.

Once we can confirm that the Internet Key Exchange version 2 (IKEv2) security associations have been established, we can verify whether the IPsec security associations have formed as well. The command to view the output is show crypto ipsec sa [detail], and the output should look similar to the following:

interface: Tunnel1
    Crypto map tag: Tunnel1-head-0, local addr 192.168.128.92

   protected vrf: (none)
   local  ident (addr/mask/prot/port): (0.0.0.0/0.0.0.0/0/0)
   remote ident (addr/mask/prot/port): (0.0.0.0/0.0.0.0/0/0)
   current_peer 3.22.91.236 port 4500
     PERMIT, flags={origin_is_acl,}
    #pkts encaps: 0, #pkts encrypt: 0, #pkts digest: 0
    #pkts decaps: 0, #pkts decrypt: 0, #pkts verify: 0
    #pkts compressed: 0, #pkts decompressed: 0
    #pkts not compressed: 0, #pkts compr. failed: 0
    #pkts not decompressed: 0, #pkts decompress failed: 0
    #pkts no sa (send) 0, #pkts invalid sa (rcv) 0
    #pkts encaps failed (send) 0, #pkts decaps failed (rcv) 0
    #pkts invalid prot (recv) 0, #pkts verify failed: 0
    #pkts invalid identity (recv) 0, #pkts invalid len (rcv) 0
    #pkts replay rollover (send): 0, #pkts replay rollover (rcv) 0
    ##pkts replay failed (rcv): 0
    #pkts tagged (send): 0, #pkts untagged (rcv): 0
    #pkts not tagged (send): 0, #pkts not untagged (rcv): 0
    #pkts internal err (send): 0, #pkts internal err (recv) 0

     local crypto endpt.: 192.168.128.92, remote crypto endpt.: 3.22.91.236
     plaintext mtu 1438, path mtu 1500, ip mtu 1500, ip mtu idb GigabitEthernet1
     current outbound spi: 0xC65652BC(3327546044)
     PFS (Y/N): Y, DH group: group20

     inbound esp sas:
      spi: 0x4516AE7B(1159114363)
        transform: esp-gcm 256 ,
        in use settings ={Tunnel UDP-Encaps, }
        conn id: 21518, flow_id: CSR:19518, sibling_flags FFFFFFFF80004048, crypto map: Tunnel1-head-0, initiator : True
         sa timing: remaining key lifetime (k/sec): (4608000/3120)
        IV size: 8 bytes
        replay detection support: Y
        Status: ACTIVE(ACTIVE)

     inbound ah sas:

     inbound pcp sas:

     outbound esp sas:
      spi: 0xC65652BC(3327546044)
        transform: esp-gcm 256 ,
        in use settings ={Tunnel UDP-Encaps, }
        conn id: 21517, flow_id: CSR:19517, sibling_flags FFFFFFFF80004048, crypto map: Tunnel1-head-0, initiator : True
         sa timing: remaining key lifetime (k/sec): (4608000/3120)
        IV size: 8 bytes
        replay detection support: Y
        Status: ACTIVE(ACTIVE)

     outbound ah sas:

     outbound pcp sas:

interface: Tunnel2
    Crypto map tag: Tunnel2-head-0, local addr 192.168.128.92

   protected vrf: (none)
   local  ident (addr/mask/prot/port): (0.0.0.0/0.0.0.0/0/0)
   remote ident (addr/mask/prot/port): (0.0.0.0/0.0.0.0/0/0)
   current_peer 18.188.20.197 port 4500
     PERMIT, flags={origin_is_acl,}
    #pkts encaps: 0, #pkts encrypt: 0, #pkts digest: 0
    #pkts decaps: 0, #pkts decrypt: 0, #pkts verify: 0
    #pkts compressed: 0, #pkts decompressed: 0
    #pkts not compressed: 0, #pkts compr. failed: 0
    #pkts not decompressed: 0, #pkts decompress failed: 0
    #pkts no sa (send) 0, #pkts invalid sa (rcv) 0
    #pkts encaps failed (send) 0, #pkts decaps failed (rcv) 0
    #pkts invalid prot (recv) 0, #pkts verify failed: 0
    #pkts invalid identity (recv) 0, #pkts invalid len (rcv) 0
    #pkts replay rollover (send): 0, #pkts replay rollover (rcv) 0
    ##pkts replay failed (rcv): 0
    #pkts tagged (send): 0, #pkts untagged (rcv): 0
    #pkts not tagged (send): 0, #pkts not untagged (rcv): 0
    #pkts internal err (send): 0, #pkts internal err (recv) 0

     local crypto endpt.: 192.168.128.92, remote crypto endpt.: 18.188.20.197
     plaintext mtu 1438, path mtu 1500, ip mtu 1500, ip mtu idb GigabitEthernet1
     current outbound spi: 0xCDD8C713(3453536019)
     PFS (Y/N): Y, DH group: group20

     inbound esp sas:
      spi: 0xDEBBED0(233553616)
        transform: esp-gcm 256 ,
        in use settings ={Tunnel UDP-Encaps, }
        conn id: 21516, flow_id: CSR:19516, sibling_flags FFFFFFFF80004048, crypto map: Tunnel2-head-0, initiator : True
         sa timing: remaining key lifetime (k/sec): (4608000/1000)
        IV size: 8 bytes
        replay detection support: Y
        Status: ACTIVE(ACTIVE)

     inbound ah sas:

     inbound pcp sas:

     outbound esp sas:
      spi: 0xCDD8C713(3453536019)
        transform: esp-gcm 256 ,
        in use settings ={Tunnel UDP-Encaps, }
        conn id: 21515, flow_id: CSR:19515, sibling_flags FFFFFFFF80004048, crypto map: Tunnel2-head-0, initiator : True
         sa timing: remaining key lifetime (k/sec): (4608000/1000)
        IV size: 8 bytes
        replay detection support: Y
        Status: ACTIVE(ACTIVE)

     outbound ah sas:

     outbound pcp sas:

Finally, we can validate the status of the tunnels through the AWS control panel for our site-to-site VPN connection. Return to the Site-to-Site VPN connections page and select the created VPN connection. In the middle of the window, select the Tunnel details tab. This should bring up a table of the tunnels, endpoint IP addresses, and status. Both tunnels should show “Up” under the status column.

VPN tunnel status within AWS control panel

The VPN has now been configured!

Learn More