Automatic VPN with iOS and iPadOS

One shortcoming of the native settings on the iPhone and the iPad is that you can’t easily set up on-demand or automatic VPNs. While there is no way to do it in the GUI, you can, however create a profile and install it with all the necessary information and logic.

Profiles are just XML documents saved with the .mobileconfig extension.

I am not going to give an exhaustive tutorial of profiles, rather a working example (the one I use). I have removed the actual data (user names, passwords, shared secrets); you substitute your values in the appropriate places. Change the UUIDs to any random UUID in the same format. For more information on the profile structure and what options you have, you can consult the Apple documentation.

This example is what I use to connect to the L2TP VPN on my Ubiquiti UDM Pro.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>PayloadContent</key>
  <array>
    <dict>
      <key>IPSec</key>
      <dict>
        <key>AuthenticationMethod</key>
        <string>SharedSecret</string>
        <key>LocalIdentifierType</key>
        <string>KeyID</string>
        <key>SharedSecret</key>
        <data>
        Your-Shared-Secret-String
        </data>
        <key>DisconnectOnIdle</key>
        <integer>0</integer>
        <key>OnDemandEnabled</key>
        <integer>1</integer>
        <key>OnDemandRules</key>
        <array>
        
          <!-- Don't VPN when on home ethernet -->
          
          <dict>
            <key>InterfaceTypeMatch</key>
            <string>Ethernet</string>
            <key>DNSDomainMatch</key>
            <array>
              <string>home</string>
              <string>home.com</string>
            </array>
            <key>Action</key>
            <string>Disconnect</string>
            <key>DNSServerAddressMatch</key>
            <array>
              <string>192.168.1.1</string>
            </array>
            <key>Action</key>
            <string>Disconnect</string>
          </dict>
                    
          <!-- If at home, no need for VPN -->
    
          <dict>
          <key>InterfaceTypeMatch</key>
            <string>Wifi</string>
          <key>SSIDMatch</key>
            <array>
              <string>MyWifi SSID</string>
              <string>Another SSID</string>
            </array>
          <key>Action</key>
            <string>Disconnect</string>
          </dict>

          <!-- Always use VPN on cellular.  Change "Connect" to "Disconnect" if you don't want VPN with cellular -->

          <dict>
          <key>InterfaceTypeMatch</key>
            <string>Cellular</string>
          <key>Action</key>
            <string>Connect</string>
          </dict>

          <!-- Use VPN on any other WiFi network -->
          
          <dict>
          <key>InterfaceTypeMatch</key>
            <string>Any</string>
          <key>Action</key>
            <string>Connect</string>
          </dict>
        </array>
      </dict>
      <key>IPv4</key>
      <dict>
        <key>OverridePrimary</key>
        <integer>1</integer>
      </dict>
      <key>PPP</key>
      <dict>
        <key>AuthName</key>
        <string>vpn_user</string>
        <key>AuthPassword</key>
        <string>my_complex_password</string>
        <key>CommRemoteAddress</key>
        <string>vpnhost.server.com</string>
      </dict>
      <key>PayloadDescription</key>
      <string>Configures VPN settings</string>
      <key>PayloadDisplayName</key>
      <string>Home VPN (Cellular)</string>
      <key>PayloadIdentifier</key>
      <string>com.apple.vpn.managed.57624016-843E-4BDF-94F0-F501A2A21379</string>
      <key>PayloadType</key>
      <string>com.apple.vpn.managed</string>
      <key>PayloadUUID</key>
      <string>58654016-845E-4BAE-94FE-F603A2B21329</string>
      <key>PayloadVersion</key>
      <integer>1</integer>
      <key>Proxies</key>
      <dict>
        <key>HTTPEnable</key>
        <true/>
        <key>HTTPPort</key>
        <integer>3128</integer>
        <key>HTTPProxy</key>
        <string>host.proxy.com</string>
        <key>HTTPSEnable</key>
        <true/>
        <key>HTTPSPort</key>
        <integer>3128</integer>
        <key>HTTPSProxy</key>
        <string>host.proxy.com</string>
      </dict>
      <key>UserDefinedName</key>
      <string>Technomancer</string>
      <key>VPNType</key>
      <string>L2TP</string>
    </dict>
  </array>
  <key>PayloadDescription</key>
  <string>This is a VPN Profile to connect back home using L2TP (including Cellular).</string>
  <key>PayloadDisplayName</key>
  <string>Home VPN (Cellular)</string>
  <key>PayloadIdentifier</key>
  <string>MyVPN.CDF577B6-9D2A-421E-9B11-679EC9249325</string>
  <key>PayloadRemovalDisallowed</key>
  <false/>
  <key>PayloadType</key>
  <string>Configuration</string>
  <key>PayloadUUID</key>
  <string>D8C395A8-8270-4644-921B-E5E4D58A3C37</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
</dict>
</plist>

Leave a Comment