Tag Archives: vpn

Easy IKEv2 VPN for mobile devices (inc iOS)

I recently obtained an iPhone and needed to connect it to my VPN. However my existing VPN server was an OpenVPN installation which works lovely on traditional desktop operating systems and Android, but the iOS client is a bit more questionable having last been updated in September 2014 (pre iOS 9).

I decided to look into what the “proper” VPN option would be for iOS in order to get something that should be supported by the OS as smoothly as possible. Last time I looked this was full of wonderful horrors like PPTP (not actually encrypted!!) and L2TP/IPSec (configuration hell), so I had always avoided like the plague.

However as of iOS 9+, Apple has implemented support for IKEv2 VPNs which offers an interesting new option. What particularly made this option attractive for me, is that I can support every device I have with the one VPN standard:

  • IKEv2 is built into iOS 9 and MacOS El Capitan.
  • IKEv2 is built into Windows 10.
  • Works on Android with a third party client (hopeful for native integration soonish?).
  • Naturally works on GNU/Linux.

Whilst I love OpenVPN, being able to use the stock OS features instead of a third party client is always nice, particularly on mobile where power management and background tasks behaviour can be interesting.

IKEv2 on mobile also has some other nice features, such as MOBIKE, which makes it very seamless when switching between different networks (like the cellular to WiFi dance we do constantly with phones/tablets). This is something that OpenVPN can’t do – whilst it’s generally fast and reliable at establishing a connection, a change in the network means issuing a reconnect, it doesn’t just move the current connection across.

 

Given that I run GNU/Linux servers, I went for one of the popular IPSec solutions available on most distributions – StrongSwan.

Unfortunately whilst it’s technical capabilities are excellent, it’s documentation isn’t great. Best way to describe it is that every option is documented, but what options and why you’d want to use them? Not so much. The “left” vs “right” style documentation is also a right pain to work with, it’s not a configuration format that reads nicely and clearly.

Trying to find clear instructions and working examples of configurations for doing IKEv2 with iOS devices was also difficult and there’s some real traps for young players such as generating SHA1 certs instead of SHA2 when using the tools with defaults.

The other fun is that I also wanted my iOS device setup properly to:

  1. Use certificate based authentication, rather than PSK.
  2. Only connect to the VPN when outside of my house.
  3. Remain connected to the VPN even when moving between networks, etc.

I found the best way to make it work, was to use Apple Configurator to generate a .mobileconfig file for my iOS devices that includes all my VPN settings and certificates in an easy-to-import package, but also (critically) allows me to define options that are not selectable to end users, such as on-demand VPN establishment.

 

After a few nights of messing around and cursing the fact that all the major OS vendors haven’t just implemented OpenVPN, I managed to get a working connection. To avoid others the same pain, I considered writing a guide – but it’s actually a really complex setup, so instead I decided to write a Puppet module (clone from github / or install from puppetforge) which does the following heavy lifting for you:

  • Installs StrongSwan (on a Debian/derived GNU/Linux system).
  • Configures StrongSwan for IKEv2 roadwarrior style VPNs.
  • Generates all the CA, cert and key files for the VPN server.
  • Generates each client’s certs for you.
  • Generates a .mobileconfig file for iOS devices so you can have a single import of all the configuration, certs and ondemand rules and don’t have to have a Mac to use Apple Configurator.

This means you can save yourself all the heavy lifting and setup a VPN with as little as the following Puppet code:

class { 'roadwarrior':
   manage_firewall_v4 => true,
   manage_firewall_v6 => true,
   vpn_name           => 'vpn.example.com',
   vpn_range_v4       => '10.10.10.0/24',
   vpn_route_v4       => '192.168.0.0/16',
 }

roadwarrior::client { 'myiphone':
  ondemand_connect       => true,
  ondemand_ssid_excludes => ['wifihouse'],
}

roadwarrior::client { 'android': }

The above example sets up a routed VPN using 10.10.10.0/24 as the VPN client range and routes the 192.168.0.0/16 network behind the VPN server back through. (Note that I haven’t added masquerading options yet, so your gateway has to know to route the vpn_range back to the VPN server).

It then defines two clients – “myiphone” and “android”. And in the .mobileconfig file generated for the “myiphone” client, it will specifically generate rules that cause the VPN to maintain a constant connection, except when connected to a WiFi network called “wifihouse”.

The certs and .mobileconfig files are helpfully placed in  /etc/ipsec.d/dist/ for your rsync’ing pleasure including a few different formats to help load onto fussy devices.

 

Hopefully this module is useful to some of you. If you’re new to Puppet but want to take advantage of it, you could always check out my introduction to Puppet with Pupistry guide.

If you’re not sure of my Puppet modules or prefer other config management systems (or *gasp* none at all!) the Puppet module should be fairly readable and easy enough to translate into your own commands to run.

There a few things I still want to do – I haven’t yet done IPv6 configuration (which I’ll fix since I run a dual-stack network everywhere) and I intend to add a masquerade firewall feature for those struggling with routing properly between their VPN and LAN.

I’ve been using this configuration for a few weeks on a couple iOS 9.3.1 devices and it’s been working beautifully, especially with the ondemand configuration which I haven’t been able to do on any other devices (like Android or MacOS) yet unfortunately. The power consumption overhead seems minimal, but of course your mileage may vary.

It would be good to test with Windows 10 and as many other devices as possible. I don’t intend for this module to support non-roadwarrior type configs (eg site-to-site linking) to keep things simple, but happy to merge any PRs that make it easier to connect more mobile devices or branch routers back to a main VPN host. Also happy to merge PRs for more GNU/Linux distribution support- currently only support Debian/Ubuntu, but it shouldn’t be hard to add others.

If you’re on Android, this VPN will work for you, but you may find the OpenVPN client better and more flexible since the Android client doesn’t have the same level of on demand functionality that iOS has built in. You may also find OpenVPN a better option if you’re regularly using restrictive networks that only allow “HTTPS” out, since it can be run on TCP/443, whereas StrongSwan IKEv2 runs on UDP port 500 or 4500.

Keeping Android Wifi Awake

I run a number of backgrounded applications on my Android phone, such as Nagios (server monitoring) CSipSimple (VoIP/SIP), OpenVPN (SSL-based VPN) and IMAP idle (push email).

Whilst this does impact battery life somewhat, I’ve got things reasonably well tuned so that the frequency of polling and keepalives is just long enough to prevent firewall timeouts, but long enough to avoid excessive waking of 3G & wifi hardware.

(For example, the default OpenVPN keepalive of 10 seconds is far more aggressive than what is actually needed, in reality, I was able to drop my phone back to one keepalive every 5 minutes – short enough to keep sessions active, but long enough that the transmitting hardware can sleep regularly whilst it isn’t needed).

However one problem I wasn’t able to fix, was the amount that the wifi disconnected – this would really screw up things, since services such as IMAP idle and SIP were trying to run over the VPN, but this would be broken by the VPN being dropped when wifi turned itself off.

I found the fix thanks to a friend who came around and told me about the hidden “Advanced” menu in the wifi network selection page:

When on the wifi network selection screen, you need to press the menu key (not sure what the option is for newer Android phones that don’t have the menu key any more?) and then a single “Advanced” menu item will appear.

Selecting this item will give you a couple extra options, including the important “Keep Wi-Fi on during sleep” option that stops the phone from dropping the wifi connection whenever you turn off the screen.

This resolved my issues with backgrounded services and I found it also made the phone generally perform better when doing any data-related services, since wifi didn’t have to renegotiate with the AP as frequently.

It’s not totally perfect, Android seems to sometimes have an argument with the AP and then drop the connection and waste a minute trying to reconnect, but it’s a lot better than it was. :-)

Why I hate DSL

mmm latency, delicious delicious latency

I’m living around 8km from the center of Auckland, New Zealand’s largest city, with only 8 mbits down and 0.84 mbits upstream in a very modern building with (presumably) good wiring installed. :'(

The above is what happens to your domestic latency when your server’s cronjobs decide to push 1.8GB of new RPMs up to a public repo, causing the performance to any other hosts to slow to a grinding halt. :-/

On the plus side it did make me aware of a fault in my server setup – one of my VMs was incorrectly set to use my secondary LDAP server as it’s primary authentication source, meaning it called back across the VPN over this DSL connection, so when this performance hit occurred, the server started having weird “hangs” due to processes blocking whilst waiting for authentication attempts to complete.

The sooner we can shift off DSL the better – there’s the possibility that my area might be covered with VDSL, but since I don’t think we’ll be here for too long, I’m not going to go to the effort to look at other access methods.

But I will make sure I carefully consider where UFB is getting laid when I come to buy property….

Android VPN Rage

Having obtained a shiny new Nexus S to replace my aging HTC Magic, I’ve been spending the last few days setting it up as I want it – favorite apps, settings, email, etc.

The setup is a little more complex for me, since I run most of my services behind a secure internal VPN – this includes email, SIP and other services.

 

On my HTC Magic, I ran OpenVPN which was included in Cynogenmod – this is ideal, since I run OpenVPN elsewhere on all my laptops and servers and it’s a very reliable, robust VPN solution.

With the Nexus S, I want to stick to stock firmware, but this means I only have the options of a PPTP or IPsec/L2TP VPN solution, both of which I consider to be very unpleasant solutions.

I ended up setting up IPsec (OpenSwan) + L2TP (xl2tp + ppp) and got this to work with my Android phone to provide VPN connectivity. For simplicity, I configured the tunnel to act as a default route for all traffic.

 

Some instant deal breakers I’ve discovered:

  1. Android won’t remember the VPN user password – I can fix this for myself by potentially moving to certificates, but this is a deal breaker for my work VPN with it’s lovely 32-char password as mandated by infrastructure team.
  2. Android disconnects from the VPN when changing networks – eg from 3G to wifi….. and won’t automatically reconnect.
  3. I’m unable to get the VPN to stand up on my internal RFC 1918 wifi range, for some reason the VPN establishes and then drops, yet works fine over 3G to the same server.

 

I love Android and I suspect many other platforms won’t be much better, but this really is a bit shit – I can only see a few options:

  1. Get OpenVPN modules onto my phone and setup OpenVPN tunnels for the stock firmware – for this, I will need to root the device, compile the Nexus kernel with tun module support, copy onto the phone and then install one of the UIs for managing the VPN.
  2. Switch to Cynogenmod to gain these features, at the cost of the stability of using the stable releases from Google/Samsung.
  3. Re-compile the source released by Samsung and apply the patches I want for OpenVPN support in the GUI from Cynogenmod.
  4. Re-compile the source released by Samsung and apply patches to the VPN controls in Android to fix VPN handling properly. Although this still doesn’t fix the fact that IPsec is a bit shit in general.

 

All of these are somewhat time intensive activities as well as being way beyond the level of a normal user, or even most technical users for that matter.

I’m wondering if option 3 is going to be the best from a learning curve and control perspective, but I might end up doing 1 or 2 just to get the thing up and running so I can start using it properly.

It’s very frustrating, since there’s some cool stuff I can now do on Android 2.3, like native SIP support that I just need to get the VPN online for first. :-(