Apple support a feature called 'VPN on Demand' despite the best efforts of both Apple and
VirnetX to sabotage this. There are three main requirements in order to implement this.
- You need to use a supported VPN client which can either be the built-in Cisco IPSec client or a supported SSL VPN client
- You need to use certificates for authentication instead of a pre-shared-key
- You need to use a MDM (Mobile Device Management) solution to configure and push the settings to the client device (iOS or Mac) including the VPN on Demand settings
With regards to the VPN client it would seem you can therefore use the built-in Cisco IPSec VPN client on your iOS or Mac client, however as we shall see Apple have made this as difficult as possible to achieve. While some techies may prefer an SSL solution and it is certainly the case that Apple's built-in IPSec client is falling behind with regards to newer security standards e.g. IKEv2, I prefer using the built-in client as there is no extra cost for it, nothing extra needs to be installed and in theory being from Apple themselves it will always be compatible with the current OS version.
Before I go on to how to get this working
despite Apple's best efforts, why do we want VPN on Demand? This can be for one of two reasons.
- To give access to an internal system that is not directly visible on the Internet and to do so in a way that is as seamless and automatic as possible in order to make things as easy as possible for users
- or to have a mobile device always route all traffic via a VPN connection so that its traffic is always protected even when using public WiFi hot-spots. By automating and enforcing this you avoid users forgetting to manually establish a VPN connection
The later reason is becoming more and more important these days with not only the threat of cyber-criminals but also Governments snooping on your traffic. So the goal is to have a compatible VPN server, a compatible VPN client and to configure things so that the VPN connection routes all traffic via it, and for the connection to be established
completely automatically.
I could have bought a commercial VPN server from Cisco, Juniper, SonicWall, F5, Aruba or CheckPoint but this would have been very expensive. It is not possible to use Apple's own VPN server solution as it only supports PPTP or L2TP, this is despite the fact that Apple use the open-source Racoon software which does support using Cisco IPSec. I initially looked at compiling and installing the standard unmodified Racoon software in OS X but this would risk causing incompatibilities with Apple's own software so my first effort was to install and configure Racoon in an Ubuntu Linux virtual machine using Virtualbox. Total cost £0
I initially and successfully did so with a pre-shared-key (henceforth referred to as PSK) and then added authentication via LDAP to OpenDirectory running on a Mac server. Total cost so far £0
I then setup a self-signed rootCA and server certificate and client certificate using XCA. Total cost so far £0
Note: Apple's built-in VPN client requires that server certificates have the server name also in a subject alternative name field (SAN). While it is possible to do this using the command line openssl tool or Certificate Assistant in Keychain Access, life is made much easier with XCA.
I reconfigured Racoon to use certificates instead of a PSK and likewise the test iPhone I was using initially running iOS 7.0.4. I then hit the first Apple bug. If you modify a VPN configuration on the iOS device changing it from using IPSec with a PSK to IPSec with a certificate, even though all the details are correctly filled in it will fail to connect. This is because even though you have switched from PSK mode to certificate mode which hides the Cisco 'Group' field, it will still try and use the Cisco 'Group' field. As this is irrelevant for a certificate authenticated connection the VPN server will reject the connection due to being very confused. Nothing on the iPhone will give you a clue about this so I had to dig through debug logs on the Linux server to track this down. To work around this you must delete the old VPN configuration and create a fresh one. Once I had cracked this I was able to successfully get the iPhone to connect and use a certificate and username/password to connect. Total cost so far £0 plus a lot of my hair being pulled out.
At this stage we now have a Cisco IPSec compatible VPN server using a certificate, and the iOS device also using a certificate and the username/password being authenticated via OpenDirectory. In theory we are now ready to setup the MDM system. At this point as a diversion I also got StrongSwan working in another Ubuntu Linux virtual machine using the same certificates as another alternative Cisco IPSec compatible server. I did not get it working with LDAP to OpenDirectory at this point because the standard version 4.5.2 of StrongSwan for Ubuntu 12.04 is too old to enable this, but I did get it working with manually defined username/password details. StrongSwan 5 or later would be able to use LDAP authentication.
I already had a copy of Server.app and hence Apple's ProfileManager so I set it up and was able to successfully enrol my test iPhone and push profiles over the air to it. I was using the same self-signed rootCA, plus an additional server certificate but the same client certificate. So far however I am unable to get ProfileManager to push this certificate to the iPhone. As far as I am concerned there is nothing wrong with the certificates as the same client certificate works when emailed to the iPhone directly, and works for the VPN connection from the iPhone, and what's more works when pushed over-the-air from the free
Cisco Meraki Systems Manager MDM solution. I therefore gave up on ProfileManager and switched to the free Cisco Meraki Systems Manager. I again enrolled the iPhone and created a profile in Systems Manager to push the client certificate to the iPhone and to also push a VPN configuration set to use that client certificate with a Cisco IPSec connection. This worked with a another major issue still to be resolved as we will see. Total cost so far £0 and the loss of some more hair.
Note: This certificate problem with ProfileManager may be a second Apple bug.
Having now successfully got a Cisco IPSec compatible VPN server working with certificates and successfully setup an MDM solution to push the settings to the iPhone I tested manual connections to the VPN server. This worked and I was able to enter and save and use the same OpenDirectory user credentials. However when I turned on VPN on Demand as part of the profile being pushed to the iPhone I discovered that the iPhone would not save the password, it would not let me edit the VPN configuration, there was also no way in the profile to define the password. As a result every time the VPN connection was told to connect I was asked again to re-enter the password. It turns out this is how currently it is 'supposed' to work. This makes it in not only my but many other peoples opinions an unusable solution for VPN on Demand. I personally consider this to be yet another Apple bug. (In Microsoft speak this would be described as a feature.)
Note: My Ubuntu Racoon VPN server had been configured to allow clients to save passwords and this had already been proven to work with manually configured VPN settings on the same iPhone.
I tried various options like an account with an empty password, not entering a username or %short name% in the VPN profile, even creating and manually editing a mobileconfig file with Xauth disabled. None of these options worked. It was beginning to look like I would have no choice but to pay for a commercial SSL VPN server.
I had when initially investigating this from the angle of 'how to do you save the password' found some discussions from other equally annoyed and frustrated Apple customers regarding this but none of these had listed a solution. By now I had gone as far as asking for a quote for an SSL VPN solution, however I did then find mention of something called Xauth-noauth for StrongSwan.
See
http://serverfault.com/questions/476033/strongswan-without-password-on-ios
I found this when I switched to searching for how to connect
without a username and password. As you can see other people have hit the same problem as I had. Fortunately someone (ecdsa) had come up with a solution which was to write a special Xauth module for use with StrongSwan which effectively ignores the Xauth details leaving just the certificate authentication active. With this the iPhone no longer asks for a password as it has not been asked by StrongSwan for one.
Note: There are normally two stages to authenticating a VPN connection, the first stage is either via a PSK or by exchanging and verifying SSL certificates, the second stage is eXtended AUTHentication or Xauth and is where the username and password are normally exchanged and verified.
I therefore dusted off my StrongSwan configured virtual machine. Unfortunately this Xauth-noauth module is only for StrongSwan 5.0.2 or later and as previously mentioned the standard version of StrongSwan for Ubuntu 12.04 is the much older and substantially different 4.5.2. As a pre-built StrongSwan 5 or later was not available for Ubuntu 12.04 I had to download the source code for
StrongSwan 5.1.2 and build it myself along with all its dependencies. I was however able to do this and install it and thankfully it did exactly what was wanted and no longer asked the iPhone for a username and password. I was therefore able to use the VPN profile from the Systems Manager MDM with VPN on Demand enabled and the iPhone was now able to
repeatedly connect without nagging me each time for the password! Yippee! Total cost so far - drum roll please - £0
Building StrongSwan 5.1.2 from scratch
First install dependencies
sudo apt-get install libpam0g-dev
sudo apt-get install libcurl4-openssl-dev
sudo apt-get install libcurl4-nss-dev
sudo apt-get install libldap2-dev
sudo apt-get install libgmp3-dev
Then download and uncompress source code
wget http://download.strongswan.org/strongswan-5.1.2.tar.bz2
tar -xjvf strongswan-5.1.2.tar.bz2
Then configure what modules to enable and compile and install (the configure command is all on a single line)
cd strongswan-5.1.2
./configure --prefix=/usr --sysconfdir=/etc --enable-curl --enable-ldap --enable-pkcs11 --enable-md4 --enable-openssl --enable-ccm --enable-gcm --enable-farp --enable-eap-identity --enable-eap-aka --enable-eap-aka-3gpp2 --enable-eap-md5 --enable-eap-gtc --enable-eap-mschapv2 --enable-eap-dynamic --enable-eap-radius --enable-eap-tls --enable-eap-ttls --enable-eap-peap --enable-eap-tnc --enable-xauth-eap --enable-dhcp --enable-charon --enable-xauth-pam --enable-xauth-noauth
sudo make
sudo make install
Here is the /etc/ipsec.conf I used for StrongSwan 5
# basic configuration
config setup
uniqueids=never
# Add connections here.
conn %default
authby=rsasig
leftrsasigkey=%cert
rightrsasigkey=%cert
keyingtries=1
keylife=60m
ikelifetime=240m
conn ios
keyexchange=ikev1
left=%defaultroute
leftsubnet=0.0.0.0/0
leftfirewall=yes
leftcert=serverCert.pem
right=%any
rightsubnet=10.0.1.0/24
rightsourceip=10.0.1.0/24
leftauth=rsa
rightauth=rsa
rightauth2=xauth-noauth
ike=aes128-sha1-modp2048,3des-sha1-modp1536
esp=aes128-sha1-modp2048,3des-sha1-modp1536
rekey=no
reauth=no
dpddelay=10
dpdtimeout=30
dpdaction=clear
auto=add
Update - 2014-09-13
After successfully running this StrongSwan VPN solution for several months with iPhone and iPad devices I discovered that users were unable to successfully connect over O2 cellular data connections, they were still able to connect over EE data, or WiFi connections. Narrowing down the circumstances was made more difficult by eliminating things like poor data connections, running out of data allowance, international roaming, confirming whether they they were using WiFi or not. Clearly there was something different about the O2 network upsetting things as the EE and WiFi connections used the same settings and even the same devices. After spending sometime investigating this it would seem that the O2 data network has problems with the size of packets used. For example if you connect using a pre-shared-key (which works) this will be a fairly small packet as the pre-shared-key is a straight forward password, however when you connect using certificates a copy of the certificate has to be sent and this is much bigger and did not work. Fortunately this has been easy to fix, StrongSwan has a command called fragmentation that enables handling splitting larger packets in to smaller ones and this has solved this problem. To use this you need to add the following line to the /etc/ipsec.conf file as shown above.
fragmentation=yes
The last step was tweaking the rules for VPN on Demand. Both Apple's ProfileManager and Cisco Meraki System Manager have very limited options for VPN on Demand that can be configured in their GUI interfaces. In fact they are so limited that effectively they can only accomplish option 1 I listed at the beginning which is to automate providing access to an internal server, and not to automate connecting via VPN all the time for all traffic. Fortunately Apple do document how to manually configure this. Yes I know it is a big shock but Apple does still provide some useful documentation sometimes.
See page 40 https://developer.apple.com/library/ios/featuredarticles/iPhoneConfigurationProfileRef/iPhoneConfigurationProfileRef.pdf
Update 2017-01-11 it has been brought to my attention that the above link no longer works, that is Apple have removed that page. The nearest equivalent currently working link I can find is
https://developer.apple.com/library/content/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010206-CH1-SW27
I therefore used
iPhone Configuration Utility to build a mobileconfig profile containing the client certificate and the VPN settings, I then exported it and edited this as per Apple's documentation above to use the URLStringProbe option to check for the ability to access a URL on my VPN server and if found to be true to trigger a VPN connection. This might be opposite of what you would expect but it is the correct choice to force a connection always to happen and by doing it this way if my server is down the URL test will fail and VPN on Demand will not be activated and the device will still be usable although not protected by a VPN connection. You therefore need to use a URL that is accessible
without a VPN connection. I then pushed this out to the iPhone using Systems Manager. With this installed my iPhone now as soon as it gets an Internet connection will automatically trigger a VPN connection which will route all traffic over it and all without any user interaction being needed. Grand total cost a massive £0!
As a final aside, all the above should apply equally to using Mac clients, testing this shall be my next project.
Links to Resources
VirtualBox or
ESXi 5.1
Ubuntu 12.04 Server
StrongSwan 5.1.2
Cisco Meraki Systems Manager
XCA
iPhone Configuration Utility 3.5 for Mac