Sunday, October 30, 2016

Strongswan to Amazon Virtual Private Gateway

Recently I needed to connect a Rackspace subnet to an AWS subnet. Our VPN software of choice in Rackspace was Strongswan, and for Amazon we wanted to use Amazon's Virtual Private Gateway (VPG).

I figured this would be easy. Set up the Virtual Private Gateway, Customer Gateway, and VPN Connection in AWS, set up Strongswan, and done. Should really only take a few minutes.

It took many hours, spread over a couple of weeks, before I actually had it working. Google searches yielded many sample configurations for Strongswan against Amazon Virtual Private Gateways, but none of them worked for me. I'm providing the configuration that worked for us in the hopes that others can be spared the same pain of figuring it out. The end configuration is straightforward: the part that was troublesome was determining the correct set of options for /etc/ipsec.conf. The only other Strongswan file I modified was /etc/ipsec.secrets; everything else was left untouched (as provided by the Debian Strongswan installation).

The pieces:

  • Rackspace subnet 192.168.17.0/24.
  • Amazon subnet 172.18.0.0/16.

The steps:

  1. In Rackspace, spin up a Debian 8.6 (Jessie) server for Strongswan with three network interfaces:
    1. PublicNet — this is the public interface over which Strongswan will communicate to the Amazon Virtual Private Gateway. Let's say Rackspace gave us 1.2.3.4 as the IP address of this interface.
    2. ServiceNet — the Rackspace network for communication to Rackspace services, not used by Strongswan.
    3. 192.168.17.0/24 — our private subnet on the Rackspace side. The Strongswan server will forward traffic between this network and the Amazon 172.18.0.0/16 network.
  2. On the Strongswan server, set up iptables appropriately. I'm not going to cover iptables configuration here. There was nothing specific to Strongswan other than ensuring that both subnets were allowed and forwarding was allowed between them.
  3. On the Strongswan server, enable forwarding. In /etc/sysctl.conf, set net.ipv4.ip_forward=1 and either trigger a reload or just reboot.
  4. In AWS, create the Virtual Private Gateway: nothing at all to configure here.
  5. Create the Customer Gateway. Set Routing to Static and provide the external IP of the Strongswan server (1.2.3.4 from the Strongswan box above).
  6. In AWS, create the VPN Connection. Set Routing Options to Static and provide the Rackspace subnet (192.168.17.0/24) in Static IP Prefixes.
  7. In AWS, in the Route Propagation tab of the appropriate Route Table, set Propagate to true for the Virtual Private Gateway. This was the only routing configuration that was needed; I did not need to configure any routes in Amazon or on the Strongswan server for the Strongswan gateway to route appropriately.
  8. In AWS, on the Tunnel Details tab of the VPN Connection, take note of the IP address of Tunnel 1 (we won't be using the second tunnel). Let's say this value was 5.6.7.8.
  9. In AWS, select Download Configuration on the VPN Connection and choose Vendor: Generic, Platform: Generic, and Software: Vendor Agnostic. From this file, locate the Pre-Shared Key for IPSec Tunnel #1. Let's say this value was htFtWOVqKkss2EamZ36rFoPefECU18XJ.
  10. On the Strongswan server from step 1, install Strongswan (in this case Strongswan 5.2.1):
     apt-get install strongswan
  11. On the Strongswan server, update /etc/ipsec.secrets to contain the following (and only the following) to map the Pre-Shared Key to the Amazon Tunnel 1 endpoint:
     5.6.7.8 : PSK "htFtWOVqKkss2EamZ36rFoPefECU18XJ"
  12. On the Strongswan server, update /etc/ipsec.conf to contain the following (and only the following):
    conn %default
      mobike=no
      compress=no
      authby=psk
      keyexchange=ikev1
      ike=aes128-sha1-modp1024!
      ikelifetime=28800s
      esp=aes128-sha1-modp1024!
      lifetime=3600s
      rekeymargin=3m
      keyingtries=3
      installpolicy=yes
      dpdaction=restart
      type=tunnel
    
    conn dc-aws1
      leftsubnet=192.168.17.0/24
      right=5.6.7.8
      rightsubnet=172.18.0.0/16
      auto=start
    
    Note how the only unique values here are the subnets (leftsubnet=192.168.17.0/24 and rightsubnet=172.18.0.0/16) and the Amazon Tunnel 1 endpoint (right=5.6.7.8). Everything else is boilerplate.
  13. Restart Strongswan, and done!

After the last step, Tunnel 1 of the VPN connection should have a Status of UP. Running ipsec status on the Strongswan server should show something like

root@theserver:~# ipsec status
Security Associations (1 up, 0 connecting):
     dc-aws1[1]: ESTABLISHED 5 seconds ago, 1.2.3.4[1.2.3.4]...5.6.7.8[5.6.7.8]
     dc-aws1{1}:  INSTALLED, TUNNEL, ESP in UDP SPIs: cf07b51b_i 1965694d_o
     dc-aws1{1}:   192.168.17.0/24 === 172.18.0.0/16 
root@theserver:~# 

Note that while I managed to get it working on a Debian Jessie server, I tried but failed to get the same configuration working on CentOS 7. Different defaults for Strongswan, different default software or settings on CentOS 7, or a combination of both? It remains a mystery.