Sören Bleikertz
23 Feb 2010

Amazon VPC with Linux

This post will cover how to connect a Amazon Virtual Private Cloud (VPC) with a Linux-based VPN gateway. In Amazon’s Network Guide for setting up a gateway connecting a VPC with existing infrastructure, they only provide specific configurations for Juniper and Cisco devices. Other devices, like a Linux-based VPN gateway, are covered by their documentation for Generic Devices, but lack specific configuration files. In this post I will explain how to setup a VPN gateway using racoon, ipsec-tools, and quagga on Ubuntu Linux.

Setup a VPC

The first thing to do is to follow the VPC tutorial and setting up all the VPC objects, like vpn-gateway, vpc, subnet etc. When specifying the customer VPN gateway, you can assume a private BGP ASN like 65530, which we will use later in the example configuration files. Just follow the steps in the tutorial and skip the part of configuring the customer VPN gateway, which we will do afterwards. Having completely configured the Amazon side of the VPN, we can immediately test the configuration of our customer VPN gateway.

Setup of IPSec

First, you have to install the necessary packages for running a VPN gateway using IPSec: apt-get install ipsec-tools racoon. In case you are running a packet filter on the VPN machine, please allow UDP port 500 for racoon/IKE.

When creating a VPN connection in the Setup a VPC section, Amazon will provide you with all the required configuration parameter for setting up the IPSec tunnel. Of particular interest are the Pre-Shared Keys and the IP addresses, which can look like the following:

Outside IP Addresses:
  - Customer Gateway:        : 1.2.3.4
  - VPN Gateway              : 72.21.209.225

Inside IP Addresses
  - Customer Gateway         : 169.254.255.2/30
  - VPN Gateway              : 169.254.255.1/30

Outside IP Addresses:
  - Customer Gateway:        : 1.2.3.4
  - VPN Gateway              : 72.21.209.193

Inside IP Addresses
  - Customer Gateway         : 169.254.255.6/30
  - VPN Gateway              : 169.254.255.5/30

We pretend that the external IP address of our customer VPN gateway is 1.2.3.4, but you will have to replace that value in the following configuration files with your actual address.

Update: The IP addresses of the VPN gateways can be in the opposite order, i.e. 72.21.209.193 for the address range 169.254.255.1/30. If this is the case, the ipsec-tools.conf have to be adjusted accordingly.

/etc/racoon/psk.txt

This file holds the pre-shared keys for the two IPSec tunnels:

72.21.209.225 password1
72.21.209.193 password2

/etc/ipsec-tools.conf

In this file we specify the IPSec policies for the two tunnels:

flush;
spdflush;

spdadd 169.254.255.2/30 169.254.255.1/30 any -P out ipsec
   esp/tunnel/1.2.3.4-72.21.209.225/require;

spdadd 169.254.255.1/30 169.254.255.2/30 any -P in ipsec
   esp/tunnel/72.21.209.225-1.2.3.4/require;

spdadd 169.254.255.6/30 169.254.255.5/30 any -P out ipsec
   esp/tunnel/1.2.3.4-72.21.209.193/require;

spdadd 169.254.255.5/30 169.254.255.6/30 any -P in ipsec
   esp/tunnel/72.21.209.193-1.2.3.4/require;

spdadd 169.254.255.2/30 192.168.0.0/24 any -P out ipsec
   esp/tunnel/1.2.3.4-72.21.209.225/require;

spdadd 192.168.0.0/24 169.254.255.2/30 any -P in ipsec
   esp/tunnel/72.21.209.225-1.2.3.4/require;

spdadd 169.254.255.6/30 192.168.0.0/24 any -P out ipsec
   esp/tunnel/1.2.3.4-72.21.209.193/require;

spdadd 192.168.0.0/24 169.254.255.6/30 any -P in ipsec
   esp/tunnel/72.21.209.193-1.2.3.4/require;

The first part specifies to use tunnels between the customer VPN gateway and the two Amazon VPN endpoints for the internal IP addresses of the VPN. Please remember to change the 1.2.3.4 address with your actual address. The second part is necessary for specifying the policy of using the same tunnels when accessing the VPC subnet 192.168.0.0/24.

/etc/racoon/racoon.conf

The racoon.conf contains the cryptographic parameters for the specific IPSec tunnels, which are obtained from the configuration provided by Amazon.

remote 72.21.209.193 {
        exchange_mode main;
        lifetime time 28800 seconds;
        proposal {
                encryption_algorithm aes128;
                hash_algorithm sha1;
                authentication_method pre_shared_key;
                dh_group 2;
        }
        generate_policy off;
}

remote 72.21.209.225 {
        exchange_mode main;
        lifetime time 28800 seconds;
        proposal {
                encryption_algorithm aes128;
                hash_algorithm sha1;
                authentication_method pre_shared_key;
                dh_group 2;
        }
        generate_policy off;
}

sainfo address 169.254.255.2/30 any address 169.254.255.1/30 any {
    pfs_group 2;
    lifetime time 3600 seconds;
    encryption_algorithm aes128;
    authentication_algorithm hmac_sha1;
    compression_algorithm deflate;
}

sainfo address 169.254.255.6/30 any address 169.254.255.5/30 any {
    pfs_group 2;
    lifetime time 3600 seconds;
    encryption_algorithm aes128;
    authentication_algorithm hmac_sha1;
    compression_algorithm deflate;
}

Setup of Inside IP Addresses and Getting Started

The next thing is to set the inside IP addresses on the network interface:

ip a a 169.254.255.2/30 dev eth0
ip a a 169.254.255.6/30 dev eth0

Followed by starting the IPSec services and establish the tunnels:

/etc/init.d/racoon start
/etc/init.d/setkey start

ping 169.254.255.1
ping 169.254.255.5

The ping commands at the end establish the tunnels and it may take a while until ICMP responses are received. The command racoonctl show-sa ipsec is also helpful to watch the state of the IPSec tunnels.

Setup of BGP Routing

After setting up the IPSec tunnels, which are hopefully working now and the Amazon VPN gateways are reachable, we have to set up the BGP routing. I have used the Quagga software router: apt-get install quagga. In /etc/quagga/daemons you have to enable the zebra and bgpd daemons. In case you are running a packet filter, please allow the Amazon VPN gateways to connect to TCP port 179 for BGP.

/etc/quagga/bgpd.conf

hostname ec2-vpn
password testPassword
enable password testPassword
!
log file /var/log/quagga/bgpd
!debug bgp events
!debug bgp zebra
debug bgp updates
!
router bgp 65530
bgp router-id 1.2.3.4
network 169.254.255.2/30
network 169.254.255.6/30
network 0.0.0.0/0
!
! aws tunnel #1 neighbour
neighbor 169.254.255.1 remote-as 7224
!
! aws tunnel #2 neighbour
neighbor 169.254.255.5 remote-as 7224
!
line vty

The router-id should be changed to the external IP address of your customer VPN gateway. The passwords should be changed as well to your preferred value. The bgpd configuration file just specifies the Amazon VPN gateways as BGP neighbours and that our machine will provide routing to the default network 0.0.0.0/0.

/etc/quagga/zebra.conf

hostname ec2-vpn
password testPassword
enable password testPassword
!
! list interfaces
interface eth0
interface lo
!
line vty

Zebra is used for managing the routing table. You should change the passwords in this configuration file as well.

Getting Started

Just activate quagga by /etc/init.d/quagga start and verify the reception of the VPC subnet routing by the Amazon VPN gateways, e.g. by checking the log file /var/log/quagga/bgpd for rcvd and UPDATE entries of the appropriate VPC subnet. You can also connect to the bgpd management console using nc localhost 2605 and type show ip bgp summary for displaying BGP information.

Afterwards you can launch an instance in your VPC following this guide and try to ping the instance from your customer VPN gateway.

Accessing the Internet from VPC Instances

In case you are wondering why your launched VPC instance can not access the Internet, I have not implemented this yet. I suppose you only have to do NAT on your VPN gateway for the VPC subnet, but I haven’t tested that.

Troubleshooting

Please follow the Amazon Troubleshooting Guide in case something does not work. If this also does not resolve your issues, you may leave a comment with appropriate log files and I will try to help out.