Testing Per-App VPN

That you want to achieve

Currently the "Per-App VPN" in the test application information of the developer site Testing Per-App VPN
I'd like to VPN connection test for each application in reference to, but in a state that fails to connect
do not know what is wrong.
Do will not be your professor asks if put those who know?

For more information on implementing the contents are as follows.


Implementation content

• The NetworkExtension added to the application ID of provisioning profiles
enable Networkextension to Capabilities of Targets of · XCode

The following check boxes are all valid.
・ App Proxy
・ Content Filter
・ Packet Tunnel
・ DNS Proxy
  ※ Confirmed that the corresponding entitlement file is included in the project


・add the following to your Info.plist

<key>NETestAppMapping</key
<dict>
    <key>3D7A07D8-97D0-4E5A-BB04-1EB82DD12A35</key>
    <array>
        <string>my.greatenterprise.SuperApp</string>
    </array>
<dict>


Profile (installed at the AppleConfigrator2) install the created to the terminal for the test

→ more information on profiles Please refer to the contents of the following profile.

• Creating a source code of the VPN connection for the test

→ For more information please refer to the contents of the following source code.

The following error messages were executing this source code displays.


connectfaild:The operation couldn’t be completed. (NEVPNErrorDomain error 1.)


And the environment that was used to implement the Per-App VPN, the contents of the profile, the source code is as follows.


Development environment

10.1 Xcode
VPN server type: L2TP
IOS12.1.4 (IPhone8)
development language swift 4.2.1


<?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>PayloadUUID</key>
  <string>C3179238-32FE-406E-A3E1-30700BF42977</string>
  <key>PayloadType</key>
  <string>com.apple.vpn.managed.applayer</string>
      <key>PayloadIdentifier</key>
  <string>com.apple.vpn.managed.applayer.C3179238-32FE-406E-A3E1-30700BF42977</string>
  <key>VPNSubType</key>
  <string>xx.xx.***.appBundleID</string>
  <key>VPNType</key>
  <string>VPN</string>
  <key>UserDefinedName</key>
  <string>VPN_CONFIG</string>
  <key>PayloadDescription</key>
  <string>Configure VPN settings</string>
  <key>PayloadDisplayName</key>
  <string>VPN</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
  <key>VPNUUID</key>
  <string>3D7A07D8-97D0-4E5A-BB04-1EB82DD12A35</string>
  <key>IPv4</key>
  <dict>
  <key>OverridePrimary</key>
  <integer>0</integer>
  </dict>
  <key>Proxies</key>
  <dict>
  <key>HTTPEnable</key>
  <integer>0</integer>
  <key>HTTPSEnable</key>
  <integer>0</integer>
  </dict>
  <key>VPN</key>
  <dict>
  <key>AuthName</key>
  <string>xxxx</string>
  <key>AuthPassword</key>
  <string>yyyy</string>
  <key>AuthenticationMethod</key>
  <string>Password</string>
  <key>ProviderBundleIdentifier</key>
  <string>zzzz</string>
  <key>RemoteAddress</key>
  <string>abc.co.jp</string>
  </dict>
  </dict>
  </array>
  <key>PayloadDisplayName</key>
  <string>Name not set</string>
  <key>PayloadIdentifier</key>
  <string>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</string>
  <key>PayloadRemovalDisallowed</key>
  <false/>
  <key>PayloadType</key>
  <string>Configuration</string>
  <key>PayloadUUID</key>
  <string>88D93328-F0AE-4AC6-9AE5-FFA6A4B5BCBF</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
</dict>
</plist>


The contents of the source code

The following source code
is already described the import NetworkExtension.


    func connectvpn(){
        let serverAddress = "abc.co.jp"
        let username = "xxxx"
        let tpm = NETunnelProviderManager()
        tpm.loadFromPreferences { error in
            if (error != nil) {
                return
            }
            let tpp = NETunnelProviderProtocol()
            tpp.username = username
            tpp.serverAddress = serverAddress
            tpp.disconnectOnSleep = false
            tpm.protocolConfiguration = tpp
            tpm.localizedDescription = "VPN_CONFIG"
            tpm.isEnabled = true
            tpm.saveToPreferences(completionHandler: { err in
                if(err != nil){
                    return
                }
                else{
                    do{
                        try tpm.connection.startVPNTunnel()
                    }
                    catch{
                        print("connectfaild:\(error.localizedDescription)")
                    }
                }
            })
        }
    }


Supplementary information

  • In already started for the L2TP The VPN server, it has confirmed it can be connected from the iOS VPN.
  • After installing this profile to the terminal, it has confirmed that APP-specific VPN field is created not connected to the VPN configuration of the OS.
  • When you run this source code, VPN_CONFIG cell is added to the VPN settings of the OS, [application name - you need to update. ] Confirmed that is displayed.

Questions

Although the type of VPN servers there is information that L2TP is not supported in the case of "Personal VPN", "Per-App VPN" does not depend on the type (it can be connected L2TP) or is unknown.

I don’t think you’ll be able to get this working. To start, I’m skeptical as to whether L2TP even supports per-app VPN. However, even if it does, trying to configure it using

NETestAppMapping
is not going to work. That support was intended for folks developing their own per-app VPN transports using NetworkExtension providers (app proxy and packet tunnel). I can’t imagine it working for the built-in VPN transports. Those should be configured using the standard mechanism, which on iOS means that the target app must be installed via MDM.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Testing Per-App VPN
 
 
Q