IPSec VPN server setup in Amazon VPC with OpenSwan

10 minute read , Mar 12, 2014

The access to our Amazon VPC’s atm is based on ssh key pairs. While this is working fine and is pretty much secure it requires though each EC2 instance having public subnet interface which is not always desired. Usually the service layout is vertically divided in tiers with only LB’s and some application servers on the top being publicly accessible while the rest of them are private subnets only like application servers, databases, shared storage etc, thus keeping the public and private traffic separated. Also sometimes a situation may arise when we need access to a VPC but we don’t have the access keys on us or we need to access via untrusted wireless network. For this reasons setting up a VPN instance to allow clients, so called road worriers, to connect becomes necessity.

Overview

The VPN server setup will be on EC2 micro instance so monthly costs for running this server are around $5. It will be IPsec/L2TP VPN server which offers high security.

In short, the following are the key elements of the setup:

  • OS = Ubuntu 12.04 Server LTS
  • Kernel = 3.2.0-59-virtual
  • L2TP daemon = xl2tpd 1.3.1
  • IPsec Implementation = Openswan 2.6.37-1
  • IPsec Stack = Netkey (26sec) - (supplied as part of Kernel 2.6)
  • IKE / Key management daemon = pluto - (supplied as part of Openswan)

I’m going to give a short description of each of the parts involved here.

xl2tpd: is a Layer 2 Tunneling Protocol (L2TP) used to support virtual private networks (VPNs) (RFC2661). L2TP facilitates the tunneling of Point-to-Point Protocol (PPP) packets across an intervening network in a way that is as transparent as possible to both end-users and applications. The main purpose of this protocol is to tunnel PPP frames through IP networks using the Link Control Protocol (LCP) which is responsible for establishing, maintaining and terminating the PPP connection. L2TP does not provide any encryption or confidentiality itself; it relies on an encryption protocol to encrypt the tunnel and provide privacy, hence L2TP is used with IPSec that provides the encryption

Openswan: is a set of tools for doing IPsec on Linux operating systems. The tool-set consists of three major components:

  • configuration tools
  • key management tools (aka pluto )
  • kernel components (KLIPS and sec)

pluto: is the key management daemon, it is an IPsec Key Exchange (IKE) daemon. IKE's Job is to to negotiate Security Associations for the node it is deployed on. A Security Association (SA) is an agreement between two network nodes on how to process certain traffic between them. This process involves encapsulation, authentication, encryption, or compression.

netkey: is the name of the IPSec stack in the 2.6 kernel used to encrypt the PPP packets over the L2TP tunnel. Netkey is a relatively new IPsec stack is based on the KAME stack from BSD. Netkey is also referred to as 26sec or native stack. Netkey supports both IPv4 and IPv6.

pppd: is the Point-to-Point Protocol daemon which is used to manage network connections between two nodes. Specifically pppd sets up the transport for IP traffic within the L2TP tunnel for the VPN.

VPN client: any pc, mobile device or network using an IPsec PSK tunnel with the l2tp secret enabled. The client can also support PPTP, basic L2TP and also certificate based authentication.

Server installation and setup

Installation

Installation is fairly simple, we just run:

root@vpn-server:~# aptitude install -y openswan xl2tpd

IPsec configuration

We take backup of the ipsec config file /etc/ipsec.conf and modify it as follows:

version 2.0
 
config setup
  dumpdir=/var/run/pluto/
  nat_traversal=yes
  virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v6:fd00::/8,%v6:fe80::/10
  oe=off
  protostack=netkey
  nhelpers=0
  interfaces=%defaultroute
  #plutodebug=all
 
conn vpnpsk
  auto=add
  left=172.31.12.198
  leftid=<my-vpn-server-dns>
  leftsubnet=172.31.12.198/32
  leftnexthop=%defaultroute
  leftprotoport=17/1701
  rightprotoport=17/%any
  right=%any
  rightsubnetwithin=0.0.0.0/0
  forceencaps=yes
  authby=secret
  pfs=no
  type=transport
  auth=esp
  ike=3des-sha1
  phase2alg=3des-sha1
  dpddelay=30
  dpdtimeout=120
  dpdaction=clear

Important thing here is that the leftid needs to be pointing to the public IP (EIP of the EC2 instance) or the DNS name as in my case that is hosted in Route53.

Next we create random hard to guess PSK key (the one given below is not the one I used for the server of course):

root@vpn-server:~# ipsec ranbits --continuous 128
0xe37ef1c5f42eb7dde93a974a5dcc7b2c

Then we use this password key in the secrets file /etc/ipsec.secrets:

<my-vpn-server-dns> %any  : PSK "0xe37ef1c5f42eb7dde93a974a5dcc7b2c"

This line translated say any client connected to this host () should use this password as shared key. If we have created this for first time we need to set proper permissions:

root@vpn-server:~# chmod 600 /etc/ipsec.secrets

CHAP authentication

The CHAP authentication file /etc/ppp/chap-secrets is where we put our users and their credentials.

# Secrets for authentication using CHAP
# client    server  secret          IP addresses
 
<my-user>    l2tpd   <my-password>   *
<my-user-2>  l2tpd   <my-password-2>   192.168.42.41

We have two users here with their user name and password. The last parameter in the line specifies the ip address the client should get upon successful connection. The first user will simply get the first available ip from the pool specified in the xl2tpd configuration in the next step. If we have created this for first time we need to set proper permissions:

root@vpn-server:~# chmod 0600 /etc/ppp/chap-secrets

XL2TPD daemon

There two configuration files we need to setup here, first is /etc/xl2tpd/xl2tpd.conf.

[global]
port = 1701
 
;debug avp = yes
;debug network = yes
;debug state = yes
;debug tunnel = yes
 
[lns default]
ip range = 192.168.42.10-192.168.42.250
local ip = 192.168.42.1
require chap = yes
refuse pap = yes
require authentication = yes
name = l2tpd
;ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
/etc/ppp/options.xl2tpd
ipcp-accept-local
ipcp-accept-remote
ms-dns 8.8.8.8
ms-dns 8.8.4.4
noccp
auth
crtscts
idle 1800
mtu 1280
mru 1280
lock
connect-delay 5000

Firewall

We need to open TCP port 500, and UDP ports 500 (IKE), 1701 (L2TP) and 4500 (NAT-T) in the EC2 instance security group. On the server it self we need to set iptables for the ppp0 interface and the network the clients will get their ip’s from:

root@vpn-server:~# iptables -t nat -A POSTROUTING -s 192.168.42.0/24 -o eth0 -j MASQUERADE
root@vpn-server:~# iptables -A FORWARD -i eth0 -o ppp0 -m state --state RELATED,ESTABLISHED -j ACCEPT
root@vpn-server:~# iptables -A FORWARD -i ppp0 -o eth0 -j ACCEPT

To make this rules persist over reboots we need to install iptables-persistent package:

root@vpn-server:~# aptitude install iptables-persistent
root@vpn-server:~# iptables-save > /etc/iptables/rules.v4

Configure the kernel

Append the following to the end of the kernel config file.

net.ipv4.ip_forward=1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
net.ipv4.conf.lo.secure_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.eth0.secure_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0

save the file and make the rules effective:

root@vpn-server:~# sysctl -p

Final check

root@vpn-server:~# 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.37/K3.2.0-58-virtual (netkey)
Checking for IPsec support in kernel                            [OK]
 SAref kernel support                                           [N/A]
 NETKEY:  Testing XFRM related proc values                      [OK]
    [OK]
    [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            [OK]
Checking NAT and MASQUERADEing                                  [OK]
Checking for 'ip' command                                       [OK]
Checking /bin/sh is not /bin/dash                               [WARNING]
Checking for 'iptables' command                                 [OK]
Opportunistic Encryption Support                                [DISABLED]

All is ok so now we can start the services and go on with client configuration.

root@vpn-server:~# /etc/init.d/ipsec restart
root@vpn-server:~# /etc/init.d/xl2tpd restart
 
root@vpn-server:~# ifconfig ppp0
ppp0      Link encap:Point-to-Point Protocol
          inet addr:192.168.42.1  P-t-P:192.168.42.10  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1280  Metric:1
          RX packets:10809 errors:0 dropped:0 overruns:0 frame:0
          TX packets:10375 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:2054854 (2.0 MB)  TX bytes:3895668 (3.8 MB)

Clients setup

Linux

Installing the client is fairly simple:

$ sudo aptitude install l2tp-ipsec-vpn

Then either launch the L2TP ipces VPM Manager from the Application menu or enable the L2TP applet as shown on the screen shot and click on it.

This basically does the following:

Adds the shared key to ipsec secrets file /etc/ipsec.secrets:

%any @<my-vpn-server-dns>: PSK 0t0xe37ef1c5f42eb7dde93a974a5dcc7b2c

Adds the connection to the xl2tpd conf file /etc/xl2tpd/xl2tpd.conf:

[lac SAI_VPC_AU]
lns = <my-vpn-server-dns>
pppoptfile = /etc/ppp/SAI_VPC_AU.options.xl2tpd
length bit = yes
redial = no

And sets the user credentials in the /etc/ppp/SAI_VPC_AU.options.xl2tpd file

This app has bug in the Ubuntu 12.04 version that doesn’t exist in 10.04, 11.04 or 11.10. The user password is not passed on during the connection and workaround is to set it manually in the /etc/ppp/SAI_VPC_AU.options.xl2tpd file.

So right after name line we add password line as shown below in the /etc/ppp/SAI_VPC_AU.options.xl2tpd file:

# /etc/ppp/SAI_VPC_AU.options.xl2tpd - Options used by PPP when a connection is made by an L2TP daemon
# $Id$
 
# Manual: PPPD(8)
 
# Created: Sun Mar 9 16:54:40 2014
#      by: The L2TP IPsec VPN Manager application version 1.0.6
#
# WARNING! All changes made in this file will be lost!
 
#debug
#dump
#record /var/log/pppd
 
plugin passprompt.so
ipcp-accept-local
ipcp-accept-remote
idle 72000
ktune
noproxyarp
asyncmap 0
noauth
crtscts
lock
hide-password
modem
noipx
 
ipparam L2tpIPsecVpn-SAI_VPC_AU
 
promptprog "/usr/bin/L2tpIPsecVpn"
 
refuse-eap
refuse-pap
refuse-mschap
refuse-mschap-v2
 
remotename ""
name "<my-user>"
password "<my-password>"
 
usepeerdns

Bad news is that when ever we use this VPN Manager again it will overwrite our changes and we’ll have to do it over again.

The log file from the server showing the session being successfully established:

Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: Connection established to <my-public-ip-reducted>, 1701.  Local: 49762, Remote: 50824 (ref=0/0).  LNS session is 'default'
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: control_finish: Warning: Peer did not specify transmit speed
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: start_pppd: I'm running:
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "/usr/sbin/pppd"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "passive"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "nodetach"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "192.168.42.1:192.168.42.10"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "refuse-pap"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "auth"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "require-chap"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "name"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "l2tpd"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "file"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "/etc/ppp/options.xl2tpd"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "ipparam"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "<my-public-ip-reducted>"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: "/dev/pts/3"
Mar  8 11:00:28 ip-172-31-12-198 xl2tpd[23625]: Call established with <my-public-ip-reducted>, Local: 32087, Remote: 16751, Serial: 1
Mar  8 11:00:28 ip-172-31-12-198 pppd[23907]: pppd 2.4.5 started by root, uid 0
Mar  8 11:00:28 ip-172-31-12-198 pppd[23907]: Using interface ppp0
Mar  8 11:00:28 ip-172-31-12-198 pppd[23907]: Connect: ppp0 <--> /dev/pts/3
Mar  8 11:00:28 ip-172-31-12-198 pppd[23907]: local  IP address 192.168.42.1
Mar  8 11:00:28 ip-172-31-12-198 pppd[23907]: remote IP address 192.168.42.10

Then I was able to connect to one of the servers in the VPC from my pc by simply using its private ip:

igorc@silverstone:~$ ssh ubuntu@172.31.18.41
The authenticity of host '172.31.18.41 (172.31.18.41)' can't be established.
ECDSA key fingerprint is d2:93:cd:e5:cc:6c:45:52:76:09:34:bf:6f:a4:fc:9d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.31.18.41' (ECDSA) to the list of known hosts.
ubuntu@172.31.18.41's password:
Welcome to Ubuntu 12.04.2 LTS (GNU/Linux 3.2.0-49-virtual x86_64)
 
 * Documentation:  https://help.ubuntu.com/
 
  System information as of Sat Mar  8 22:04:24 EST 2014
 
  System load:  0.16              Processes:           113
  Usage of /:   84.2% of 7.87GB   Users logged in:     0
  Memory usage: 50%               IP address for eth0: 172.31.18.41
  Swap usage:   0%                IP address for eth1: 172.31.51.41
 
  Graph this data and manage this system at https://landscape.canonical.com/
 
159 packages can be updated.
81 updates are security updates.
 
Get cloud support with Ubuntu Advantage Cloud Guest
  http://www.ubuntu.com/business/services/cloud
 
Use Juju to deploy your cloud instances and workloads.
  https://juju.ubuntu.com/#cloud-precise
*** /dev/xvda1 will be checked for errors at next reboot ***
 
You have new mail.
Last login: Thu Mar  6 15:25:36 2014 from <my-public-ip-reducted>
ubuntu@ip-172-31-18-41:~$

If we prefer to do the things manually, the start step-by-step (without applet) would be:

root@igor-laptop:~# service xl2tpd restart
root@igor-laptop:~# service ipsec restart
root@igor-laptop:~# ipsec auto --add SAI_VPC_AU
root@igor-laptop:~# ipsec auto --up SAI_VPC_AU
root@igor-laptop:~# echo "c SAI_VPC_AU" > /var/run/xl2tpd/l2tp-control

Then to end the VPN connection:

root@igor-laptop:~# ipsec auto --down SAI_VPC_AU
root@igor-laptop:~# echo "d SAI_VPC_AU" > /var/run/xl2tpd/l2tp-control
root@igor-laptop:~# service ipsec stop
root@igor-laptop:~# service xl2tpd stop

Mac

Open your network settings:

  • Click on the + button in the top-left corner of the interfaces list
  • Select a VPN interface, with IPSec L2TP and give it a name
  • In the address field, put the public IP of our VPN server (you can get it via nslookup)
  • In the account name field, put the value of the VPN_USER variable that you defined earlier.
  • Click on auth settings, fill your VPN_PASSWORD in the first field and your IPSEC_PSK in the second box. Click Ok
  • Click on Advanced Settings, select “Send all traffic” and click ok.
  • If you are running firewall then make sure the appropriate ports are not blocked (see the Firewall section)

Leave a Comment