Skip to content

Instantly share code, notes, and snippets.

@inthecloud247
Forked from winhamwr/tutorial.md
Created June 5, 2013 21:51
Show Gist options
  • Save inthecloud247/5717605 to your computer and use it in GitHub Desktop.
Save inthecloud247/5717605 to your computer and use it in GitHub Desktop.

Creating a dynamic site-to-site VPN with OpenSwan on Ubuntu 10.04 on EC2

Wes Winham winhamwr@gmail.com

There are many tutorials floating around the web that almost get you a dynamic VPN in EC2. The goal of this tutorial is to be a one-stop-shop for this specific setup.

This is heavily derived from this EC2 example and this Ubuntu 10.04 example.

What You'll Get

  • Config files that don't change when new instances are launched (the private ec2 ip doesn't matter).
  • An EC2 box that can securely access a private subnet on the remote network.
  • No special access from the remote endpoint to your EC2 box.
  • The ability to use Elastic IPs to manage which box is connected.
  • Compatibility with cisco and openswan endpoints.
  • No need to update the remote endpoint config.

Things You'll Need

  • A fresh Ubuntu 10.04 instance on EC2
  • $ELASTIC_IP: An elastic IP
  • $CONN_NAME: A unique name for your connection. eg. my_ec2_vpn
  • $RIGHT_PUBLIC_IP: The public IP of your other VPN endpoint.
  • $SECURE_PSK: A random pre-shared key to secure your connection.
  • $RIGHT_SUBNET: The private subnet your EC2 box should access on the remote network:

Note: If you only need to access a single IP on the remote network, use a /32 netmask for your $RIGHT_SUBNET. eg. 192.169.3.54/32

Configuration

First, spin up your EC2 instance and attach your Elastic IP.

Install OpenSwan

SSH into your EC2 instance and run:

$ sudo apt-get install openswan

Fix Linux Networking

Once OpenSwan is installed, you'll have access to the $ sudo ipsec verify command. This command checks certain linux network paramenters to ensure that your system properly supports OpenSwan.

Run this command and you should see something like:

$ sudo ipsec verify
Checking your system to see if IPsec got installed and started correctly:
Version check and ipsec on-path                                 [OK]
Linux Openswan U2.6.23/K2.6.32-318-ec2 (netkey)
Checking for IPsec support in kernel                            [OK]
NETKEY detected, testing for disabled ICMP send_redirects       [FAILED]

  Please disable /proc/sys/net/ipv4/conf/*/send_redirects
  or NETKEY will cause the sending of bogus ICMP redirects!

NETKEY detected, testing for disabled ICMP accept_redirects     [FAILED]

  Please disable /proc/sys/net/ipv4/conf/*/accept_redirects
  or NETKEY will accept bogus ICMP redirects!

Checking for RSA private key (/etc/ipsec.secrets)               [OK]
Checking that pluto is running                                  [OK]
Pluto listening for IKE on udp 500                              [OK]
Pluto listening for NAT-T on udp 4500                           [OK]
Two or more interfaces found, checking IP forwarding            [FAILED]
Checking for 'ip' command                                       [OK]
Checking for 'iptables' command                                 [OK]
Opportunistic Encryption Support                                [DISABLED]

The gist of this is that the Ubuntu AMI's must use the NETKEY stack and that you must make configuration tweaks to support that. You also need to enable IP forwarding because the EC2 instance has multiple network devices.

You will make these changes using the /etc/sysctl.conf file and the sysctl command. This will cause changes in the proc file system at paths like /proc/sys/net/ipv4/conf/*/send_redirects, but by editing this file, you ensure those changes are reflected on reboot.

Edit /etc/sysctl.conf and add or uncomment the following lines:

net.ipv4.ip_forward=1

net.ipv4.conf.all.accept_redirects = 0

net.ipv4.conf.all.send_redirects = 0

net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0

net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0

Now use the sysctl command to load your new configuration:

$ sudo sysctl -p /etc/sysctl.conf

If you succeeded, running $ sudo ipsec verify again should show everything [OK] with the exception of Opportunistic Encryption Support, which we don't need.

Open the EC2 Security Group

In order for the VPN to initiate a connection, we must allow the traffic to pass through EC2's firewall. This is managed via Security Groups.

To modify the ec2 security groups, open the AWS Console, select EC2 and then select the Security Groups section.

Open UDP access on ports 500 and 4500 for a group in use by your EC2 instance.

Configure IPSec

You'll configure your IPSec connection using 3 different files:

  • /etc/ipsec.conf: This is the main configuration file, where we declare overall configurations and then define the $RIGHT_SUBNET as a non-private range.
  • /etc/ipsec.d/$CONN_NAME.conf: Included via the include /etcipsec.d/*.conf line in /etc/ipsec.conf, we use this to define our specific tunnel.
  • /etc/ipsec.secrets: Here we define the pre-shared key used by the connection.

You'll control reloading these configuration files with:

$ sudo service ipsec stop
$ sudo service ipsec start

Modify the following files to match this configuration, remembering to replace the $ALL_CAPS variables with the actual value.

Configure: /etc/ipsec.conf

version 2.0

config setup
		nat_traversal=yes
		virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$RIGHT_SUBNET
		protostack=netkey

include /etc/ipsec.d/*.conf

Configure: /etc/ipsec.d/$CONN_NAME.conf

conn $CONN_NAME
		authby=secret
		forceencaps=yes
		auto=start
		left=%defaultroute
		leftid=$ELASTIC_IP
		leftsourceip=$ELASTIC_IP
		right=$RIGHT_PUBLIC_IP
		rightid=$RIGHT_PUBLIC_IP
		rightsubnet=$RIGHT_SUBNET

Configure: /etc/ipsec.secrets

We use 0.0.0.0 for one side of the connection to ensure that no matter the ec2 internal ip we use to identify ourselves (as indicated by left=%defaultroute), we use this key if the connection is coming from our expected remote endpoint.

$RIGHT_PUBLIC_IP 0.0.0.0: PSK "$SECURE_PSK"

Restart OpenSwan

Now let's actually load our spanking-new configuration files.

$ sudo service ipsec stop
$ sudo service ipsec start

Test the Connection

To test the connection, run the following command (replacing $CONN_NAME with the appropriate value):

$ sudo ipsec auto --up $CONN_NAME

If everything is kosher, you should see two lines similar to the following (apd is the value of $CONN_NAME in this case):

117 "apd" #3: STATE_QUICK_I1: initiate
004 "apd" #3: STATE_QUICK_I2: sent QI2, IPsec SA established tunnel mode

Awesome. Now our tunnel is up, so let's see if we can send some traffic through. Pick an IP address in your $RIGHT_SUBNET that should respond to pings and run:

$ ping <something_on_right_subnet>

You should see pings coming back.

Testing Without Ping

If you don't have a box to target that should respond to ping, you can try running a port scan to see if you can at least reach the machine.

$ nmap -PN <something_on_right_subnet>

Monitoring traffic

While you're running your ping or nmap, you can view the traffic with tcpdump.

$ tcpdump -n host <RIGHT_PUBLIC_IP>

If you don't see ESP packets in tcpdump, then they aren't being tunneled. Try:

$ tcpdump -n host <something_on_right_subnet>

If that shows ICMP (or other if using nmap) packets, then you're sending packets around the tunnel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment