On demand VPN with iOS and OpenVPN

by Michael Urspringer - 25.04.2015

I can connect to my internal network from outside via an OpenVPN tunnel. However I need to manually start the VPN connection on my iPhone or iPad every time before I want to access one of my internal machines. So I looked for a way to automate that and starting the VPN connection with OpenVPN on my iOS devices on demand.

Here I describe the steps which I have done to obtain that:

I assume that you already have a working VPN connection from your iOS device via OpenVPN and have access to the certificate files you created for that.

First you need to create a certificate file in PKCS12 format which contains both your certificate and your private key. I have created that file with the following OpenSSL command:

openssl pkcs12 -export -inkey your_private_key_file.key -in your_certificate_file.crt -name a_name_for_your_certificate -out your_pkcs12_file.p12

Now we need to create a mobile configuration profile for iOS. As the “Apple Configuration Tool for Windows” no longer exists and the official tool “Apple Configurator” is only available for Mac I used the “OpenVPN iOS Configuration Profile Utility“. You might need to install RubyGems before if you not have it setup already on your machine (I did all these steps on my Raspberry Pi where I had that installed before).

I used the following command to create my profile:

ovpnmcgen.rb generate --host my_vpn_host_name --proto udp --port listening_vpn_port --trusted-ssids the_WLAN_SSID_of_my_home_network --security-level medium --cafile my_ca_file_used_for_vpn --p12file the_pkcs12_file_created_before --ovpnconfigfile the_openvpn_config_file.ovpn -o the_name_of_the_generated_output_file.mobileconfig a_user_identifier a_device_identifier

Unfortunately currently the “ovpnmcgen” tool does not support the “DNSDomainMatch” directive which is needed for automatic enabling VPN as soon as you access a host in your internal network.

So you manually need to add the following parameters to the “OnDemandRules” section in your “the_name_of_the_generated_output_file.mobileconfig” file . I have highlighted the lines you need to add:

<key>VPN</key>
 <dict>
 <key>AuthenticationMethod</key>
 <string>Certificate</string>
 <key>OnDemandEnabled</key>
 <integer>1</integer>
 <key>OnDemandRules</key>
 <array>
 <dict>
 <key>Action</key>
 <string>Disconnect</string>
 <key>InterfaceTypeMatch</key>
 <string>WiFi</string>
 <key>SSIDMatch</key>
 <array>
 <string>the_WLAN_SSID_of_my_home_network</string>
 </array>
 </dict>
 <dict> <key>Action</key> <string>EvaluateConnection</string> <key>ActionParameters</key> <array> <dict> <key>Domains</key> <array> <string>urs.local</string> <string>*.urs.local</string> </array> <key>DomainAction</key> <string>ConnectIfNeeded</string> </dict> </array> </dict> <dict> <key>Action</key>
 <string>Ignore</string>
 <key>InterfaceTypeMatch</key>
 <string>WiFi</string>
 </dict>
 <dict>
 <key>Action</key>
 <string>Disconnect</string>
 <key>InterfaceTypeMatch</key>
 <string>Cellular</string>
 </dict>
 <dict>
 <key>Action</key>
 <string>Ignore</string>
 </dict>
 </array>

You need to replace “urs.local” with the domain name of your internal network. Accessing a host with this domain name (e.g. “myhost.urs.local”) will then automatically trigger a VPN connection.

Now you do have a configuration file which you can install as a profile in your iOS device. You need to somehow transfer it to your device. You can either mail it to you (might be unsecure as someone can get access to your file …) or transfer it via iTunes or (as I did) place it on your own Owncloud server and open it with Safari on your iOS device.

To install the profile you need first to enter your iOS password and after that the password for your private key you used while creating the PKCS12 file.

As soon as you have installed the profile you are ready to go.

With the configuration described above a VPN connection will be established automatically as soon as you try to access a hostname in your local network (here: “urs.local”). If you come back home with your device and connect to your own Wifi network the VPN will be disconnected again automatically.

Tagged with:  

9 Responses to On demand VPN with iOS and OpenVPN

  1. […] Providing VPN access to my internal network from outside via OpenVPN. I already described what you need to do to automatically connect via VPN if a ressource from the home network is accessed on iOS devices in that article. […]

  2. Jose says:

    Thank you for this tutorial. Easy to follow and concise!. My VPN is working on demand following your steps but I have two questions. How can I configure IPs instead of domain names? (I think that starting with IOS 9 is not possible). And, how can I stop VPN when is idle (for example after 10 minutes of inactivity?

  3. You are right, since September 2015 Apple does no longer allow IP addresses but only domain names.

    Regarding the automatic disconnect, try to play with something like that:

    DisconnectOnIdle
    1
    DisconnectOnIdleTimer
    900

    • Sorry, WordPress has removed all lower than and greater than characters 🙁 Here again, change all brackets in these lines with lower than and greater than characters:

      (key)DisconnectOnIdle(/key)
      (integer)1(/integer)
      (key)DisconnectOnIdleTimer(/key)
      (integer)900(/integer)

      Let me know if you got it working.

      • Jose says:

        Hi Michel
        I have modified my mobileconfig file inserting OnIdle code between these lines and is not working:

        (key)VPN(/key)
        (dict)
        ….
        (key)DisconnectOnIdle(/key)
        (integer)1(/integer)
        (key)DisconnectOnIdleTimer(/key)
        (integer)600(/integer)
        ….
        (key)AuthenticationMethod(/key)
        (string)Certificate(/string)
        (key)OnDemandEnabled(/key)
        (integer)1(/integer)
        (key)OnDemandRules(/key)

        Maybe I’m doing something wrong but my VPN still up after ten minutes of inactivity.
        Thank you!

        • Sorry Jose. No other idea unfortunately….

          • Jose says:

            Seems that DisconnectOnIdle don’t work with OpenVPN but there’s a workaround for this. If I disable “reconnect on wake up” in OpenVPN app settings I get more or lees what I want. That is, when the device goes to sleep, VPN will still down after wake up until a new on demand rule is tiggered. For me this behavior is OK.
            Thank you Michael for your article and your help!

  4. Nuno says:

    This also applies if I have purchased a VPN through any provider?

Leave a Reply

© 2000-2015 Michael Urspringer