VPN Server for Android Clients

Use cases

This guide describes the configuration of a VPN server for protecting the traffic of Android phones and tablets; in other words we want the phone to establish a protected connection to a trusted VPN server and use this connection for accessing the Internet.

The Android device may have a public address and direct connection to the VPN server:

Internet <---> VPN Server <---> Android Phone
                1.1.1.1           2.2.2.2

Or may be sitting behind a NAT operated by the carrier:

Internet <---> VPN Server <---> Carrier NAT <---> Android Phone
                1.1.1.1           3.3.3.3          10.10.10.10

This case will require some extra care with the server side setup.

1.1.1.1, 2.2.2.2 and 3.3.3.3 are public, routable addresses, while 10.10.10.10 is a private address.

L2TP/IPSec

This VPN mode uses L2TP (Layer 2 Tunneling Protocol) to establish a tunnel between your client to the server. L2TP by itself does not provide any encryption, so IPSec is used to carry the L2TP packets.

It seems that the new version of the Android OS codename Ice Cream Sandwich (ICS) has some interoperability problems with both Openswan and Strongswan (see this bug report); this document will focus on using Racoon on the server, which works fine.

Software Needed

This guide is based on the packages from the current stable distribution (Squeeze). The following packages are needed:

aptitude install racoon xl2tpd iptables

racoon

Racoon is an IPSec key exchange (IKE) server, its role it's to negotiate the keys with the client in order to establish an IPSec Security Association (SA).

This scenario requires a so called "road warrior" configuration, where one endpoint of the tunnel (the client) is not known beforehand. The authentication at IPSec level can be done either using RSA certificates or with PSK and XAUTH.

RSA Certificates

The files needed for RSA authentication are:

Why do you have two raccoon.conf config sections? Can this be combined with the other part of the raccoon.conf? It is a little confusing...

Racoon is configured with the file /etc/racoon/racoon.conf; the first directive sets the path of the certificates:

path certificate "/etc/racoon/certs";

Then there's the configuration of the of the remote node; since the client is roaming we use the anonymous keyword to indicate that the remote address is not known. The rest of the configuration is pretty standard, with racoon taking care of the IPSec policy and enabling NAT traversal support. Dead Peer Detection (DPD) is enabled with an interval of 20 seconds: this means that racoon will periodically query the client to see if it's still there and will drop the tunnel after 5 (by default) failed communication attempts. Mobile clients they may to drop off without releasing the tunnel, DPD helps releasing the SA after a short timeout.

remote anonymous {
        exchange_mode main;

        my_identifier fqdn "my.server.com";
        certificate_type x509 "myserver-cert.pem" "myserver-key.pem";
        ca_type x509 "myserver-cacert.pem";

        generate_policy on;
        nat_traversal on;

        dpd_delay 20;

        proposal {
                encryption_algorithm aes;
                hash_algorithm md5;
                authentication_method rsasig;
                dh_group modp1024;
        }
}

The last block defines the parameter used by the SA; again the remote endpoint is not know we the keyword anonymous is required. The crypto algorithms available are not restricted even though Android currently only uses AES and MD5.

sainfo anonymous {
        encryption_algorithm aes, 3des;
        authentication_algorithm hmac_sha1, hmac_md5;
        compression_algorithm deflate;
}

PSK (Pre-Shared Key)

While certificate-based authentication can be considered more secure, the PSK authentication is easier to set up.

Edit /etc/racoon/psk.txt and add the shared secret. You will need to use "*" as the IP Address since the client address is not known beforehand.

* mySharedSecret

"mySharedSecret" will need to be entered only once when VPN is created. Please make sure it is a complex key. This secret has nothing to do with the PPP password that is set up later.

Add the following to /etc/racoon/racoon.conf:

remote anonymous {
        exchange_mode main;

        generate_policy on;
        nat_traversal on;

        dpd_delay 20;

        proposal {
                encryption_algorithm aes;
                hash_algorithm md5;
                authentication_method pre_shared_key;
                dh_group modp1024;
        }
}

Please copy the relevant sainfo bits from RSA Cert section. The configuration differs only in authentication_method - pre_shared_key instead of rsasig.

xl2tpd

xl2tpd is a very simple L2TP daemon, it works standalone and does not require an external DHCP or RADIUS server which simplifies the deployment when there are only a handful of clients.

The main configuration file is /etc/xl2tpd/xl2tpd.conf:

[global]
access control = no

In the global section we disable the builtin access control of the daemon since the remote IP address is not known. The next section defines the server side configuration of L2TP, also knows as L2TP Network Server (LNS):

[lns default]
ip range = 192.168.200.100-192.168.200.110
local ip = 192.168.200.10
require authentication = yes
require chap = yes
refuse pap = yes
length bit = yes
name = l2tpd
pppoptfile = /etc/ppp/xl2tpd-options

The first directive (ip range) defines the address pool used for the remote endpoint of the tunnel (in the example 10 addresses are available), and the second defines the local endpoint of the tunnel (not the machine public address!). Authentication is then enabled but only using CHAP. name sets the address of the server as far as L2TP is concerned, this will be also used for authentication. Lastly pppoptfile defines the location of the configuration file for PPPD.

In case of troubles it's possible to enable debug output for xl2tpd itself adding the following statements in the global section:

debug avp = yes
debug network = yes
debug state = yes
debug tunnel = yes

To see what PPPD is doing add this line to the LNS section:

ppp debug = yes

The additional L2TP secret is not enabled since it adds next to nothing in terms of security.

PPPD

PPPD maintains the point-to-point tunnel between the server and the phone and is automatically started by xl2tpd. The configuration file for PPPD is specified in the configuration file of xl2tpd and in this example is /etc/ppp/xl2tpd-options:

auth
nodefaultroute
lock
proxyarp
require-chap
ms-dns 8.8.8.8
ms-dns 8.8.4.4

This configuration enables authentication using CHAP, and pushes two DNS address to the client (in the example Google Public DNS service is used). The authentication data is read from /etc/ppp/chap-secrets:

myusername      l2tpd   test1234        *

The fields are:

This password will need to be entered every time a VPN is set up on the devices running Android < 4.0. Later releases allow storing the password provided that the device lock screen is protected by PIN, password or a pattern key.

Forwarding and iptables

This examples assumes that the client has been assigned a private address by xl2tpd so forwarding and masquerading are needed.

Forwarding between interface is controlled by /proc/sys/net/ipv4/ip_forward and must be enabled (i.e. set to 1); this setting can be made persistent adding the following line to either /etc/sysctl.conf or to a separate file in /etc/sysctl.d/ (run /etc/init.d/procps start to apply the setting immediatly):

net.ipv4.ip_forward=1

That alone is sufficient to let the packets from the phone reach the public interface of the server; however the packets have a private address as the source and hence are not routable: the server must rewrite the packet on the fly overwriting the address with its own when packets go out and do the reverse when replies come back (this is called masquerading). Assuming that eth0 is dynamic and the public interface of the server:

iptables -t nat -A POSTROUTING -o eth0 -s 192.168.200.0/24 -j MASQUERADE

If the public interface of the server uses a static IP, then use SNAT instead of MASQUERADE, with the IP address of the public interface (12.34.56.78 in this example).

iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -j SNAT --to-source 12.34.56.78

The rule above rewrites all the packets going out the public interface and coming from the private pool set aside for the phones (as per xl2tpd configuration).

Assuming that the server firewall and not left wide open the following rules are needed to ensure that packets for the VPN go through:

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

You probably already have this one, it lets through packets from connections that have been already accepted.

iptables -A INPUT -p udp --dport 500 -j ACCEPT
iptables -A INPUT -p udp --dport 4500 -j ACCEPT

These rules are for IKE and NAT-T and are required by racoon. The firewall will have to let pass IPSec/ESP traffic:

iptables -A INPUT -p esp -j ACCEPT

This last rule is actually not needed when using only NAT-T since IPSec packets and encapsulated in UDP packages; next the firewall must accept packets to the L2TP deamon, but not just any packet: only those that are part of a IPSec SA; in this way xl2tpd will only receive packets after racoon has established a tunnel:

iptables -A INPUT -p udp -m policy --dir in --pol ipsec -m udp --dport 1701 -j ACCEPT

Client behind NAT

If the client is behind a NAT racoon generates the wrong IPSec policies (see this post for more informations). To fix this issue it's possible to manually load a policy that forces the encryption of all the communication with the L2TP daemon; to do this create a new file /etc/ipsec-tools.d/l2tp.conf with the following content:

spdadd 1.1.1.1[l2tp] 0.0.0.0/0 udp -P out ipsec
        esp/transport//require;
spdadd 0.0.0.0/0 1.1.1.1[l2tp] udp -P in ipsec
        esp/transport//require;

Where 1.1.1.1 is the public IP address of the VPN server.

Run /etc/init.d/setkey start to apply the settings immediatly.

Client side configuration

This example is based on Android 2.2 device using Pre-Shared Key. The kernels that come with Android emulator do not support the VPN (2.3 version fails at creating a key socket and 4.0+ fail since they are missing PPPoX modules).

Select a corresponding entry from the list of the available VPN types and configure it accordingly. IPSec shared key is mySharedSecret in the PSK example above.

01_VPN_types.png 02_VPN_config.png

Upon connection, a dialog pops up asking for PPP credentials:

03_VPN_connect.png 04_PPP_auth.png

Connection established:

05_VPN_connected.png