The built-in Android VPN client allows for a choice of PPTP, L2TP and L2TP IPSec VPN connections. Due to security flaws with PPTP, and L2TP offering no encryption I opted to set up an L2TP IPSec VPN which as you'll discover wasn't the easiest of rides.
IPSec is a security layer running on top of IP ('Internet Protocol'). My VPN end point again is my Ubuntu 10.04 server running the Openswan VPN suite. My client as already mentioned is an Android Google Nexus One 2.3.4; however, this setup has been tested on Froyo (2.2 , 2.2.1 and 2.2.2) and Gingerbread (2.3.3 and 2.3.4) using this configuration.
Trying to comprehend what happens during the creation of an IPSec VPN, I've drafted a novice parody & overview of what I believe happens based on my understanding (please shout in the comments if I've misunderstood).
A VPN Parody
A VPN is formed by encrypting a transport tunnel between two nodes. The nodes usually take the forn of a client-server or srever-server. Think of tunneling as having a computer delivered to you by UPS. The vendor packs the computer (point to point protocol) into a box (encapsulating protocol) which is then put on a UPS truck (transport protocol) which is then locked so bystanders cannot see what the truck contains (IPSec protocol). This all occurs at the vendor's warehouse (entry tunnel interface). The truck (transport protocol) travels over the highways (Internet) to your home (exit tunnel interface) and delivers the computer. The truck is unlocked (IPSec protocol) so you can see inside the truck, you open the box (encapsulating protocol) and remove the computer (passenger protocol).
OS = Ubuntu 10.04 Desktop LTS
Kernel = 2.6.32-31-generic
L2TP daemon = xl2tpd 1.2.7
IPsec Implementation = Openswan 2.6.28
IPsec Stack = Netkey ('26sec') - (supplied as part of Kernel 2.6)
IKE / Key management daemon = pluto - (supplied as part of Openswan)
A good background resource with lots of detail is Using a Linux L2TP/IPsec VPN server .
Overview of the tools involved
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 responsilbe for establishing, maintaining and terminating the PPP connection. L2TP does not provide any encryption or confidentiality itself; it relies on an encryption protocol encrypts then tunnel to provide privacy, hence L2TP are encrypted by using it with IPSec. xl2tpd is an open source implementation of the L2TP tunneling protocol and is a fork from l2tpd maintained by the Xelerance Corporation. xl2tpd replaces the obsolete and unmaintained l2tpd.
Openswan: is a set of tools for doing IPsec on Linux operating systems. The toolset consists of three major components:
- configuration tools
- key management tools (aka pluto )
- kernel components (KLIPS and sec).
Note, IKE implementations can only negotiate with other IKE implementations, so IKE must be on each node that is to be an endpoint of an IKE-negotiated Security Association. No other nodes need to be running IKE.
IKE deals with two kinds of Security Associations. The first part of a negotiation between IKE instances is to build an ISAKMP (Internet Security Association and Key Management Protocol) SA. An ISAKMP SA is used to protect communication between the two IKEs. The second part of the security association for the IKEs is to build the IPsec SAs, these are used to carry protected PPP traffic between the systems. The negotiation of the ISAKMP SA is known as Phase 1. Any negotiation under the protection of an ISAKMP SA, including the negotiation of IPsec SAs, is part of Phase 2.
In short, the IKE instance is prepared to automate the management of Security Associations in an IPsec environment. The actual secure transmission of packets is the responsibility of Netkey.
It is worth noting that pluto only implements a subset of IKE, but enough for it to interoperate with other instances of pluto, and many other IKE implementations. pluto uses shared secrets or RSA signatures to authenticate peers with whom it is negotiating. pluto implements ISAKMP SAs itself. After it has negotiated the IPsec SA, it directs Netkey to implement it. When pluto shuts down, it closes all Security Associations (killing the VPN tunnel).
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.
For Linux kernel 2.6, there is a choice of either KLIPS or Netkey, however, the Netkey components are already included in the 2.6 kernel. Netkey partially replaces KLIPS which was the previous IPSec stack used predominantly before Netkey shipped with kernel 2.6.
Users should note that Netkey unlike KLIPS hooks into the kernel networking code differently. With Netkey packets are intercepted by the IPsec stack after they are received on the physical (ethX) interface, this complicates iptables-based firewall rules. This interception also creates problems when using NAT and IPsec on the same machine, since the packet does not traverse through all the iptables as expected. Unencrypted packets never travel the POSTROUTING table.
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: In this post will be a Google Nexus One with Android 2.2.1-2.3.4 using an IPsec PSK tunnel with the l2tp secret not enabled. The client also support PPTP, basic L2TP and also certificate based authentication (the latter I've yet to get working on the Android side).
VPN Overview in practice
- The VPN client (android phone), connects to the server, specifically the ipsec daemon (Openswan) on port 4500.
- The key management daemon (IKE pluto) kicks off and negotiates the Phase 1 ISAKMP Security Association on behalf of IPSec.
- With the ISAKMP SA in place the IKE (pluto) is now safe to negotiate the Phase 2 IPSec SA using the pre shared key on behalf of IPSec.
- Once authenticated with the pre shared key, encrypted traffic can now pass between the client and server. Authentication can now be initiated for the Point to Point (PPP) tunnel.
- xl2tpd kicks in to handle the PPP authentication and PPP Link Establishment using the Link Control Protocol (LCP). LCP creates the tunnel to the destination network and prepares the authentication protocol which is used in step 8.
- xl2tpd also negotiates and finds out if the two nodes in the PPP connection agree on any compression or encryption algorithm. If the answer is yes then it is implemented in steps 8 and 9.
- xl2tpd now initiates user authentication and will prompt for a username and password.
- Because the L2TP secret is disabled in this post, the credentials are sent to pppd (instead of the L2TP daemon) for authentication. There are different methods for secure User Authentication, in this example we use CHAPS to secure the authentication. Once authenticated the L2TP tunnel can now be set up encapsulated inside of the IPSec encrypted packets. This is the only time when the user must take care in exchanging credentials to prevent interception i.e. don't use plain text to authenticate user credentials. If for any reason these credentials were captured by an intruder, then the intruder may be able to take control of the connection.
- pppd now initiates the PPP tunnel and invokes the Network Layer Protocol(s) that were selected during the link establishment phase (step 6). The Network Layer Protocols include IPCP which assigns the dynamic IP address to the PPP client, and if permitted compression is also now negotiated.
- PPP tunnel now up and IP assigned, with any luck you’re finally on your private network from your smart phone all under the guise of VPN.
1. Install Openswan 2.6.28
The version supplied with Ubuntu 10.04 Lucid is version 2.6.23, I had some issues with this build so I manually compiled and install 2.6.28 from the source. See below for the steps:
sudo apt-get install build-essential libgmp3-dev gawk flex bison
tar -xzvf openswan-2.6.28.tar.gz
sudo make programs
sudo make install
sudo /etc/init.d/ipsec restart
2. Install xl2tpd
The version supplied with Ubuntu 10.04 Lucid is version 1.2.5, this has some bugs so I'll move up to version 1.2.7 which works. This isn't in the repositories for Lucid as it is supplied with Natty (11.04) but you can still download and install the package from:
3. Configure xl2tpd
Open up the xl2pd configuration file:
sudo gedit /etc/xl2tpd/xl2tpd.conf
Change the xl2tpd.conf according to your setup. My xl2tpd.conf file look something like below. It is a minimal xl2tpd config, the idea is to provide an L2TP daemon to which remote L2TP clients can connect. In my config the internal (protected) network is 192.168.1.0/24. The remote clients connec to 192.168.1.51 to 192.168.1.55, this probably isn't the best approach. You would ideally want your remote clients on a separated IP range such as 10.10.10.0/24 (i.e. 10.10.10.1 … 10.10.10.254). However this reduces any headaches I may experience with routing.
The listen-addr parameter can be used if you want to bind the L2TP daemon to a specific IP address instead of to all interfaces. For instance, you can bind it to the interface of the internal LAN (e.g. 192.168.1.98 in the example below).
listen-addr = 192.168.1.100 ;this is the external network address for the Ubuntu server
ipsec saref = no ;Netkey which I am using does not support SAref at this time
auth file = /etc/ppp/chap-secrets
port = 1701
debug tunnel = yes
debug avp = yes
debug packet = yes
debug network = yes
debug state = yes
ip range = 192.168.1.51-192.168.1.55
local ip = 192.168.1.50
require chap = yes
refuse pap = yes
require authentication = yes
name = Yourservername
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
Save and Close.
4. Configure PPP
You can modify this file according to your requirement. The entire configuration is completed from xl2tp side, now time to configure the PPP parameters.
sudo gedit /etc/ppp/options.xl2tpd
You can change your dns & wins server IP address in the file. You can also add some other parameters that are supported by your pppd, like
require-mschap-v2, see the man page of your pppd.
Save and Close.
5. Configure CHAPS
The authentification data for L2TP is stored in the file /etc/ppp/chap-secrets. The same chap-secrets file can be used, if you are using mschap protocol in option file. To edit the file:
sudo gedit /etc/ppp/chap-secrets
The IP address field is showing the remote tunnel static IP address. You can assign the dynamic IP addresses also by using radius server & dhcp-pppd plugin etc. But I don’t know what is the easiest method to do this & how to. Also my requirement is completed by using static IP address.
# Secrets for authentication using CHAP
# client server secret IP addresses
# username servername password Assigned IP
username * "yoursecrethere" *
You probably also want to define a username and an IP address for the client above. Create a new line for each additional user you want to authenticate with CHAPS. I only have one client so it's not a big issue.
Save, Close and make sure you set the permissions on your chap-secret file to keep it private.
sudo chown root:root /etc/ppp/chap-secrets
sudo chmod 600 /etc/ppp/chap-secrets
6. Run xl2tpd
After doing the entire above configuration, you can start xl2tpd. First create the l2tp run control, this is a workaround for a bug in xl2tpd 1.2.7
sudo touch /var/log/xl2tpd/l2tp-control
Then start the daemon using this command:
The -D option is opening the debug of xl2tpd. It is recommended to start the application in debugging mode at first time (during testing time). Remove –D option to stop the debugs.
7. Configure IPSec (Pluto / Netkey)
Open up the IPSec configuration file:
sudo gedit /etc/ipsec.conf
This file is sensitive to formatting, ensure you have the appropriate tab indents in place.
# /etc/ipsec.conf - Openswan IPsec configuration file
# RCSID $Id: ipsec.conf.in,v 1.16 2005/07/26 12:29:45 ken Exp $
# This file: /usr/share/doc/openswan/ipsec.conf-sample
# Manual: ipsec.conf.5
version 2.0 # conforms to second version of ipsec.conf specification
# basic configuration
# NAT-TRAVERSAL support, see README.NAT-Traversal
# exclude networks used on server side by adding %v4:!a.b.c.0/24
# OE is now off by default. Uncomment and change to on, to enable.
# which IPsec stack to use. netkey,klips,mast,auto or none
# Add connections here
Save and Close.
For information....nhelpers: Pluto can also use helper children to off-load cryptographic operations. This behavior can be fine tuned using the --nhelpers. Pluto will start (n-1) of them, where n is the number of CPU's you have (including hypherthreaded CPU's). A value of 0 forces pluto to do all operations in the main process. A value of -1 tells pluto to perform the above calculation. Any other value forces the number to that amount.
8. Configure the IPSec secret pre shared key
Open up the IPSec secrets file:
sudo gedit /etc/ipsec.secrets
This file is sensitive to formatting, ensure you have the appropriate tab indents in place.
Add the following line to the file:
: PSK "yourpresharedkey"
Save and Close.
Make sure you set the permissions on your secrets file to keep it private.
sudo chown root:root /etc/ipsec.secrets
sudo chmod 600 /etc/ipsec.secrets
9. Configure the Linux Kernel
For Openswan to work icmp redirection must be disabled and IP forwarding also needs to be activated. For persistence these settings should be amended in /etc/sysctl.conf
sudo gedit /etc/sysctl.conf
Add the following lines (adjusting for your network adapters):
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 and Close. Then reload the settings:
sudo sysctl -p /etc/sysctl.conf
10. Verify the configuration
By now you should be pretty much done, time to check your configuration:
sudo ipsec verify
The output should be along the lines of:
11. Configuring the firewall
1. Enable VPN pass through on your router.
2. Forward the following to the Ubuntu server:
- Protocol 50
- Protocol 51
- 500/UDP IKE
- 4500/UDP (If you are using NAT-Traversal to tunnel through NAT/other Firewalls)
3. Allow the following ports:
- 500/UDP IKE
- 4500/UDP NAT-T
- 1701/UDP L2TP
First check the ipsec interface using ifconfig, for me this is ppp0. Then modify and add the following rules to enable masquerading:
sudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo /sbin/iptables -A FORWARD -i eth0 -o ppp0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo /sbin/iptables -A FORWARD -i ppp0 -o eth0 -j ACCEPT
The forwarding and NAT rules will of course be specific to the respective configuration The above rules allow authenticated clients to connect to everything that interface eth0 leads to (the Internet in this case).
12. Start VPN server / IPSec daemon on Ubuntu boot
The easiest option I found here was to add the following line to my rc.local script which is executed at boot time. This script is executed after all of networking bits and bobs which should therefore make it a lot easier to get the IPSec server to start.
sudo vi /etc/rc.local
Save and exit.
13. Setting up Android for the VPN connection (Froyo/Gingerbread)
- Settings >
- Wireless & networks >
- VPN Settings >
- Add VPN >
- L2TP/IPSec PSK;
- Enter your details as below:
- VPN Name = your VPN server description can be anything you want
- Set VPN Server = your server IP address or your dynamic dns hostname
- Set IPSec preshared key = enter your preshared key as setup
- Enable L2TP secret = unchecked
- DNS seach domains = leave blank
Note I don't use an L2TP secret in this blog, here's why... personally I don't think it adds much to the overall process. pppd already authenticates the user using CHAPS authentication to set up the tunnel and pluto authenticates the encryption of the tunnel using the pre shared key. Having yet another gatekeeper to authenticate the tunnel seems a little pointless, offering only another set of credentials to remember and area to troubleshoot hence I don't discuss it in this post mainly to keep are rather complex process as simple as possible.
Note: Certificate based authentication
Work in progress... on hold until iOS implements certificate based auth for L2TP IPSec.
14. Setting up iPhone iOS for the VPN connection
The following steps I used on an iPhone 3GS iOS 5.0, 5.01 and 5.1 to connect to the Ubuntu IPSec VPN.
- Add VPN Configuration:
- Select L2TP
- Description: any
- Server: server address
- Account: ubuntu username
- RSA SecurID: off
- Password: as per /etc/ppp/chap-secrets
- Secret: PSK as per /etc/ipsec.secrets
- Send All Traffic: on
- Proxy: off
As Jacco points out one problem is that Apple do not appear to send a “Delete SA” message when the device disconnects. The IPsec connection remains up and the VPN client may not be able to reconnect, and reports an error. He pointed out that the problem is resolved when Dead Peer Detection (DPD) times out, the SA itself times out (if DPD is disabled) or the Openswan daemon is restarted. For this reason it is highly recommended to enable DPD on the Openswan VPN server by adding these parameters to your Openswan configuration (suggested time-out values):
These lines need to be added to /etc/ipsec.conf under the connection configuration and not the daemon configuration from my experience. Putting them in the before the connection configuration will cause openswan to fail when restarting reporting a "confread.c:248: load_setup: Assertion `kw->keyword.keydef->validity & kv_config' failed" error in the terminal.
The example config in the body of this post has already been updated to reflect this addition.
Other Useful resources
Eclectic Security: Secure IPsec/L2TP VPN for on the road android devices
BrainBlog: Android L2TP/IPSec VPN mini-howto
Jacco de Leeuw: Using a Linux L2TP/IPsec VPN server