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.
- 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.
- 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
First, spin up your EC2 instance and attach your Elastic IP.
SSH into your EC2 instance and run:
$ sudo apt-get install openswan
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.
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.
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 theinclude /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.
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
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
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"
Now let's actually load our spanking-new configuration files.
$ sudo service ipsec stop
$ sudo service ipsec start
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.
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>
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.