Debian VPN Server for iPhone

This HowTo describes how to set-up your Debian machine as a VPN server for the iPhone. The iPhone uses L2TP over IPsec as a VPN protocol. Others are possible as well but here we stick to L2TP over IPsec.

Installation

Install the following packages:

Network layout

Internet === Router (10.0.0.1) === Debian PC (10.0.0.2) 

Configuration

freeradius

First we configure freeradius. In /etc/freeradius/clients.conf change the default secret (line 101):

secret          = mysecret

Create a default user for freeradius by adding the following lines in /etc/freeradius/users:

DEFAULT         Auth-Type := System
                Fall-Through = Yes

With this Auth-Type system users of the Debian PC will be used for freeradius. Add users to your system as required if existing users are not appropriate.

l2tpns

The implementation of L2TP on the iPhone (and OS-X in general) has some flaws which prevent it from working with l2tpns out of the box. The hackish way around that is to comment out a few lines in the source of l2tpns.c:

--- l2tpns_orig.c       2006-06-22 17:30:50.000000000 +0200
+++ l2tpns.c    2011-06-13 09:22:38.000000000 +0200
@@ -2835,6 +2835,7 @@
                        }
                }
                // Send hello
+               /*
                if (tunnel[t].state == TUNNELOPEN && !tunnel[t].controlc && (time_now - tunnel[t].lastrec) > 60)
                {
                        controlt *c = controlnew(6); // sending HELLO
@@ -2842,6 +2843,7 @@
                        LOG(3, 0, t, "Sending HELLO message\n");
                        t_actions++;
                }
+               */
 
                // Check for tunnel changes requested from the CLI
                if ((a = cli_tunnel_actions[t].action))

Get the source via apt-get source l2tpns, change l2tpns.c, recompile and copy the l2tpns binary to /usr/sbin/.

In /etc/l2ptns/ip_range a range of IP addresses which will be assigned to VPN clients can be defined. The IP range shall be a subnet of your own internal network.

10.0.0.32/28

/etc/l2tpns/startup-config is the main configuration file for l2tpns. Most of the settings can be left commented out. Only the following lines are active in my setup:

set debug 2
set log_file "/var/log/l2tpns"
set pid_file "/var/run/l2tpns.pid"
set l2tp_secret ""
set primary_dns 10.0.0.2
set secondary_dns 10.0.0.2
set primary_radius 127.0.0.1
set primary_radius_port 1812
set radius_secret "mysecret"
set accounting_dir "/var/run/l2tpns/acct"
set bind_address 10.0.0.2
set send_garp yes
set peer_address 10.0.0.1
set throttle_speed 64
set cluster_interface lo
set cluster_hb_interval 100
set cluster_hb_timeout 20

Make sure you have set peer_address to the IP of your router. The setting primary_radius is set to the the local IP since freeradius is running on the same machine. In my case primary_dns is set to the IP of the Debian machine since I'm running a local DNS server.

openswan

In /etc/ipsec.secrets we add our ipsec secret. This is then later on used for configuring the VPN connection on your iPhone:

10.0.0.2: PSK "mykey"

The ipsec main configuration file /etc/ipsec.conf is looking like this:

# /etc/ipsec.conf - Openswan IPsec configuration file

# 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
config setup
        # NAT-TRAVERSAL support, see README.NAT-Traversal
        nat_traversal=yes
        # exclude networks used on server side by adding %v4:!a.b.c.0/24
        virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12:!10.0.0.0/24
        # OE is now off by default. Uncomment and change to on, to enable.
        oe=off
        # which IPsec stack to use. auto will try netkey, then klips then mast
        protostack=netkey
        #
        #interfaces="ipsec0=br0"
        uniqueids=no
        
conn road_warrior
        rekey=no
        authby=secret
        pfs=no
        keyingtries=3
        dpddelay=10
        dpdtimeout=15
        dpdaction=clear
        compress=yes
        #
        left=10.0.0.2
        leftprotoport=17/1701
        leftnexthop=10.0.0.1
        #
        right=%any
        rightprotoport=17/%any
        rightsubnet=vhost:%no,%priv
        #
        auto=add

Make sure you have excluded your entire local IP range in virtual_private using !10.0.0.0/24. The setting left in the connection setup shall be set to the IP of your Debian machine. The setting leftnexthop is set to the IP of your router.

Network configuration

In order to map your VPN subnet to the local network ARP proxying can be used. Enable proxy_arp for your main network interface in /etc/network/interfaces:

iface eth0 inet static
        address 10.0.0.2
        netmask 255.255.255.0
        gateway 10.0.0.1
        up sysctl net.ipv4.conf.eth0.proxy_arp=1

On your router you have to forward udp packets to ports 500 and 4500 to your Debian PC:

iptables -t nat -I PREROUTING -i $WANDEV -p udp --dport 500 -j DNAT --to-destination 10.0.0.2
iptables -t nat -I PREROUTING -i $WANDEV -p udp --dport 4500 -j DNAT --to-destination 10.0.0.2

iPhone

On the iPhone go to Settings -> General -> Network -> VPN and create a new VPN configuration. Server shall be the external DNS name or IP of your router. Account shall be the user name existing on your Debian machine. RSA SecureID is OFF. Password is the password of the user used for the Account setting. Secret is the secret defined in /etc/ipsec.secrets.

iPhone VPN Setup