Deep Dive: Understanding Apple IKEv2 VPN Configuration Profiles

Understand an IKEv2 VPN configuration profile for Apple Devices

Deep Dive: Understanding Apple IKEv2 VPN Configuration Profiles
Photo by Chris Buckwald / Unsplash

Apple devices support VPN configuration through mobile configuration profiles—XML files that define connection settings, security parameters, and behavior rules. For IKEv2 VPNs, these profiles offer granular control over encryption algorithms, authentication methods, and on-demand connection rules that aren't accessible through the standard Settings interface.

This guide breaks down the structure of an IKEv2 VPN configuration profile, explaining each parameter so you can customize profiles for your own VPN infrastructure.

Profile Structure Overview

An Apple configuration profile is a property list (plist) XML file with a .mobileconfig extension. It contains one or more payloads, each configuring a specific feature. For VPN, we need a com.apple.vpn.managed payload.

Here's the skeleton structure:

<?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>
    <!-- VPN payload goes here -->
  </array>
  <key>PayloadDisplayName</key>
  <string>VPN Configuration Name</string>
  <key>PayloadIdentifier</key>
  <string>com.yourcompany.vpn.profile</string>
  <key>PayloadType</key>
  <string>Configuration</string>
  <key>PayloadUUID</key>
  <string>unique-uuid-here</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
</dict>
</plist>

The outer dictionary defines the profile container. The interesting configuration lives inside PayloadContent.

The VPN Payload

Here's a complete IKEv2 VPN payload with all common parameters:

<dict>
  <key>IKEv2</key>
  <dict>
    <key>AuthenticationMethod</key>
    <string>None</string>

    <key>RemoteAddress</key>
    <string>vpn.example.com</string>

    <key>RemoteIdentifier</key>
    <string>vpn.example.com</string>

    <key>ExtendedAuthEnabled</key>
    <true/>

    <key>IKESecurityAssociationParameters</key>
    <dict>
      <key>EncryptionAlgorithm</key>
      <string>AES-256-GCM</string>
      <key>IntegrityAlgorithm</key>
      <string>SHA2-384</string>
      <key>DiffieHellmanGroup</key>
      <integer>20</integer>
      <key>LifeTimeInMinutes</key>
      <integer>1440</integer>
    </dict>

    <key>ChildSecurityAssociationParameters</key>
    <dict>
      <key>EncryptionAlgorithm</key>
      <string>AES-256-GCM</string>
      <key>IntegrityAlgorithm</key>
      <string>SHA2-384</string>
      <key>DiffieHellmanGroup</key>
      <integer>20</integer>
      <key>LifeTimeInMinutes</key>
      <integer>1440</integer>
    </dict>

    <key>EnablePFS</key>
    <true/>

    <key>DeadPeerDetectionRate</key>
    <string>Medium</string>

    <key>DisableMOBIKE</key>
    <integer>0</integer>

    <key>DisableRedirect</key>
    <integer>0</integer>

    <key>EnableCertificateRevocationCheck</key>
    <integer>0</integer>

    <key>UseConfigurationAttributeInternalIPSubnet</key>
    <integer>0</integer>

    <key>OnDemandEnabled</key>
    <integer>1</integer>

    <key>OnDemandRules</key>
    <array>
      <dict>
        <key>Action</key>
        <string>Connect</string>
      </dict>
    </array>
  </dict>

  <key>IPv4</key>
  <dict>
    <key>OverridePrimary</key>
    <integer>1</integer>
  </dict>

  <key>PayloadDescription</key>
  <string>Configures VPN settings</string>

  <key>PayloadDisplayName</key>
  <string>vpn.example.com</string>

  <key>PayloadIdentifier</key>
  <string>com.apple.vpn.managed.unique-id</string>

  <key>PayloadType</key>
  <string>com.apple.vpn.managed</string>

  <key>PayloadUUID</key>
  <string>unique-uuid-here</string>

  <key>PayloadVersion</key>
  <integer>1</integer>

  <key>Proxies</key>
  <dict>
    <key>HTTPEnable</key>
    <integer>0</integer>
    <key>HTTPSEnable</key>
    <integer>0</integer>
  </dict>

  <key>UserDefinedName</key>
  <string>My VPN Connection</string>

  <key>VPNType</key>
  <string>IKEv2</string>
</dict>

Parameter Reference

Connection Settings

RemoteAddress

<key>RemoteAddress</key>
<string>vpn.example.com</string>

The hostname or IP address of your VPN server. Use a DNS name when possible for flexibility.

RemoteIdentifier

<key>RemoteIdentifier</key>
<string>vpn.example.com</string>

The server's IKE identity. Usually matches the server's certificate subject or SAN. Must match what your server presents during negotiation.

AuthenticationMethod

<key>AuthenticationMethod</key>
<string>None</string>

For username/password authentication (EAP), set to None. The actual authentication happens via ExtendedAuth (EAP-MSCHAPv2). Other options include Certificate for certificate-based authentication.

ExtendedAuthEnabled

<key>ExtendedAuthEnabled</key>
<true/>

Enables EAP authentication. When true, the device prompts for username and password (or uses saved credentials).

Security Association Parameters

The IKE Security Association (Phase 1) and Child Security Association (Phase 2) parameters define the cryptographic algorithms used.

EncryptionAlgorithm

<key>EncryptionAlgorithm</key>
<string>AES-256-GCM</string>

Options include:

  • AES-256-GCM - AES-256 in Galois/Counter Mode (recommended)
  • AES-256 - AES-256 in CBC mode
  • AES-128-GCM - AES-128 in GCM mode
  • AES-128 - AES-128 in CBC mode
  • 3DES - Triple DES (not recommended)

AES-256-GCM provides authenticated encryption, combining confidentiality and integrity in one operation. It's the modern choice.

IntegrityAlgorithm

<key>IntegrityAlgorithm</key>
<string>SHA2-384</string>

Options include:

  • SHA2-512 - SHA-2 with 512-bit output
  • SHA2-384 - SHA-2 with 384-bit output
  • SHA2-256 - SHA-2 with 256-bit output
  • SHA1-96 - SHA-1 (deprecated, avoid)

When using GCM encryption, the integrity algorithm provides additional assurance but GCM already includes authentication.

DiffieHellmanGroup

<key>DiffieHellmanGroup</key>
<integer>20</integer>

The Diffie-Hellman group for key exchange. Higher numbers indicate stronger (and slower) groups:

  • 14 - 2048-bit MODP (minimum acceptable)
  • 15 - 3072-bit MODP
  • 16 - 4096-bit MODP
  • 19 - 256-bit ECP (P-256)
  • 20 - 384-bit ECP (P-384, recommended)
  • 21 - 521-bit ECP (P-521)

Group 20 (P-384) offers excellent security with reasonable performance.

LifeTimeInMinutes

<key>LifeTimeInMinutes</key>
<integer>1440</integer>

How long the security association remains valid before rekeying. 1440 minutes (24 hours) is typical. Shorter values increase security slightly but add overhead.

Connection Behavior

EnablePFS

<key>EnablePFS</key>
<true/>

Perfect Forward Secrecy. When enabled, compromise of long-term keys doesn't compromise past session keys. Always enable this.

DeadPeerDetectionRate

<key>DeadPeerDetectionRate</key>
<string>Medium</string>

How frequently to check if the VPN server is still reachable:

  • None - Disabled
  • Low - Less frequent checks
  • Medium - Balanced (recommended)
  • High - Frequent checks

Higher rates detect failures faster but consume more battery on mobile devices.

DisableMOBIKE

<key>DisableMOBIKE</key>
<integer>0</integer>

MOBIKE (IKEv2 Mobility and Multihoming) allows the connection to survive IP address changes—crucial for mobile devices switching between Wi-Fi and cellular. Set to 0 (enabled) unless you have specific reasons to disable.

DisableRedirect

<key>DisableRedirect</key>
<integer>0</integer>

Whether to follow IKE redirects from the server. Generally leave enabled (0).

Traffic Routing

OverridePrimary (Full Tunnel)

<key>IPv4</key>
<dict>
  <key>OverridePrimary</key>
  <integer>1</integer>
</dict>

When set to 1, all traffic routes through the VPN (full tunnel). Set to 0 for split tunnel where only specific destinations use the VPN.

For security-focused VPN usage, full tunnel (1) is recommended—it ensures all traffic is protected.

On-Demand Rules

On-demand rules control when the VPN automatically connects or disconnects.

Always Connect:

<key>OnDemandEnabled</key>
<integer>1</integer>
<key>OnDemandRules</key>
<array>
  <dict>
    <key>Action</key>
    <string>Connect</string>
  </dict>
</array>

The VPN connects automatically whenever the device has network connectivity.

Connect Except on Specific Networks:

<key>OnDemandRules</key>
<array>
  <dict>
    <key>InterfaceTypeMatch</key>
    <string>WiFi</string>
    <key>SSIDMatch</key>
    <array>
      <string>HomeNetwork</string>
      <string>TrustedOffice</string>
    </array>
    <key>Action</key>
    <string>Disconnect</string>
  </dict>
  <dict>
    <key>Action</key>
    <string>Connect</string>
  </dict>
</array>

This disconnects on trusted Wi-Fi networks (by SSID) and connects everywhere else.

Connect Only for Specific Domains:

<key>OnDemandRules</key>
<array>
  <dict>
    <key>Action</key>
    <string>EvaluateConnection</string>
    <key>ActionParameters</key>
    <array>
      <dict>
        <key>Domains</key>
        <array>
          <string>internal.company.com</string>
        </array>
        <key>DomainAction</key>
        <string>ConnectIfNeeded</string>
      </dict>
    </array>
  </dict>
</array>

The VPN connects only when accessing specific domains.

Installing Profiles

iOS/iPadOS

  1. Transfer the .mobileconfig file via AirDrop, email attachment, or web download
  2. The device shows "Profile Downloaded" notification
  3. Go to Settings → General → VPN & Device Management
  4. Tap the downloaded profile
  5. Tap Install, enter device passcode if prompted
  6. Review the profile contents and confirm installation

macOS

  1. Double-click the .mobileconfig file
  2. System Preferences/Settings opens to the Profiles pane
  3. Review the profile and click Install
  4. Enter administrator credentials if prompted

Generating UUIDs

Each profile and payload needs unique UUIDs. Generate them with:

uuidgen

Or in Python:

import uuid
print(uuid.uuid4())

Complete Example Profile

Here's a ready-to-customize template. Replace the values in angle brackets:

<?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>IKEv2</key>
      <dict>
        <key>AuthenticationMethod</key>
        <string>None</string>
        <key>ChildSecurityAssociationParameters</key>
        <dict>
          <key>EncryptionAlgorithm</key>
          <string>AES-256-GCM</string>
          <key>IntegrityAlgorithm</key>
          <string>SHA2-384</string>
          <key>DiffieHellmanGroup</key>
          <integer>20</integer>
          <key>LifeTimeInMinutes</key>
          <integer>1440</integer>
        </dict>
        <key>DeadPeerDetectionRate</key>
        <string>Medium</string>
        <key>DisableMOBIKE</key>
        <integer>0</integer>
        <key>DisableRedirect</key>
        <integer>0</integer>
        <key>EnableCertificateRevocationCheck</key>
        <integer>0</integer>
        <key>EnablePFS</key>
        <true/>
        <key>ExtendedAuthEnabled</key>
        <true/>
        <key>IKESecurityAssociationParameters</key>
        <dict>
          <key>EncryptionAlgorithm</key>
          <string>AES-256-GCM</string>
          <key>IntegrityAlgorithm</key>
          <string>SHA2-384</string>
          <key>DiffieHellmanGroup</key>
          <integer>20</integer>
          <key>LifeTimeInMinutes</key>
          <integer>1440</integer>
        </dict>
        <key>OnDemandEnabled</key>
        <integer>1</integer>
        <key>OnDemandRules</key>
        <array>
          <dict>
            <key>Action</key>
            <string>Connect</string>
          </dict>
        </array>
        <key>RemoteAddress</key>
        <string><YOUR_VPN_SERVER></string>
        <key>RemoteIdentifier</key>
        <string><YOUR_VPN_SERVER></string>
        <key>UseConfigurationAttributeInternalIPSubnet</key>
        <integer>0</integer>
      </dict>
      <key>IPv4</key>
      <dict>
        <key>OverridePrimary</key>
        <integer>1</integer>
      </dict>
      <key>PayloadDescription</key>
      <string>Configures VPN settings</string>
      <key>PayloadDisplayName</key>
      <string><YOUR_VPN_SERVER></string>
      <key>PayloadIdentifier</key>
      <string>com.apple.vpn.managed.<UNIQUE_ID></string>
      <key>PayloadType</key>
      <string>com.apple.vpn.managed</string>
      <key>PayloadUUID</key>
      <string><GENERATE_UUID></string>
      <key>PayloadVersion</key>
      <integer>1</integer>
      <key>Proxies</key>
      <dict>
        <key>HTTPEnable</key>
        <integer>0</integer>
        <key>HTTPSEnable</key>
        <integer>0</integer>
      </dict>
      <key>UserDefinedName</key>
      <string><FRIENDLY_NAME></string>
      <key>VPNType</key>
      <string>IKEv2</string>
    </dict>
  </array>
  <key>PayloadDisplayName</key>
  <string>IKEv2 VPN (<YOUR_VPN_SERVER>)</string>
  <key>PayloadIdentifier</key>
  <string><GENERATE_UUID></string>
  <key>PayloadRemovalDisallowed</key>
  <false/>
  <key>PayloadType</key>
  <string>Configuration</string>
  <key>PayloadUUID</key>
  <string><GENERATE_UUID></string>
  <key>PayloadVersion</key>
  <integer>1</integer>
</dict>
</plist>

The profile parameters must match your VPN server's configuration. If you're building an IKEv2 server, ensure the cipher suites, DH groups, and authentication methods align.


Footnotes:

[1] Apple Configuration Profile Reference: https://developer.apple.com/documentation/devicemanagement/vpn
[2] IKEv2 Cipher Suites: https://wiki.strongswan.org/projects/strongswan/wiki/IKEv2CipherSuites
[3] Apple Enterprise IT Documentation: https://support.apple.com/guide/deployment/