Apple iOS SDK

Integrate VPN into your apple iOS application

1. Preparing

Before integrating Apple provisioning profiles for Application and Network Extension target should be created.

To do this visit Apple developer portal->Certificates, Identifiers & Profiles->Identifiers and add new identifier for your application target and enable next capabilities:

  • App Groups

  • Keychain sharing

  • Network Extensions

  • Personal VPN

Create another identifier for Network Extension target using the same capabilities as for Application.

2. Integration

2.1. Linking

  • Application

To integrate SDK to application target, copy FendSDK.framework to desired location in your project folder, then add it to Frameworks, Libraries, and Embedded content application project section and make sure that Embed option is set to Embed & Sign

  • Network Extension

For extension, target perform the same steps as for Application target with FendTunnelProvider.framework

2.2. Configuring capabilities

For both targets Signing capabilities should be configured:

2.3. App Groups

Create group name started with group. and use the same name for Application and Network extension target (ex. group.fend.testapp)

2.4. Keychain sharing

Create keychain group name and use the same and for Application and Network extension target.

2.5. Network extension

Select Packet Tunnel option for both targets.

2.6. Personal VPN

Make sure that Personal VPN capability is added.

2.7. Setup Network Extension target

Change NSExtensionPrincipalClass value to FDTunnelProvider in NSExtension dictionary of Network Extension target Info.plist

3. Start using FendSDK

3.1. Configure FendSDK

To start using the SDK, you need to import import FendSDK to your class under the application target.

Initialize FendSDK with Configuration:

import FendSDK    

    let configuration = Configuration(project: ##Project Name##,
                                          url: ##URL##,
                                      groupID: ##Group ID that you used in Integration step##,
                             providerBundleID: ##Bundle identifier for Network Extension target##,
                            isOnDemandEnabled: true)

    let sdk = FendSDK(configuration: configuration)

After SDK is initialized, you need to login to be able to start VPN. Login example with anonymous authorization:

import FendSDK
// ...

let sdk: FendSDK
// ...

       sdk.signIn(method: .anonymous()) { user, error in
            print("user = \(user)")
        }

3.2. Connecting VPN and obtaining status

To establish a VPN connection you need to select location to which you want to connect or pass nil and VPN location will be automatically selected.

import FendSDK
// ...

let sdk: FendSDK
// ...

        sdk.locations { locations, error in
            if let errror = error {
                print("Error has occured during loading locations: \(error)")
            } else {
                self.location = locations?.first
            }
        }

After choosing location use function connect(to location:completion:) to start VPN.

import FendSDK
// ...

let sdk: FendSDK
// ...

        sdk.connect(to: selectedLocation) { [unowned self] _, error in
            print(error ?? sdk.lastError)
        }

When VPN is started or an error occurred, completion handler will be called.

To get notifications about actual VPN state, subscribe to NEVPNStatusDidChange and get actual state from FendSDK.state variable.

import FendSDK
// ...

let sdk: FendSDK
private var stateCancellable: AnyCancellable?
// ...
        stateCancellable = NotificationCenter.default.publisher(for: .NEVPNStatusDidChange)
            .map { _ in () }
            .sink { [unowned self] in
                print("state = \(sdk.state)")
            }

3.3. Using On Demand mode

SDK provides functionality to restore VPN connection after:

  • Changing Wi-Fi/Celluar network

  • Wake up after sleep or reboot

Set parameter isOnDemandEnabled of Configuration to true to enable On Demand mode.

3.4. Tunnel provider delegate

To get vpn state callbacks in tunnel provider you need to create class with any name that conforms to FendTunnelProviderDelegate protocol and inherits from NSObject:

import FendSDK    
// ...

@objc
class ProviderDelegate: NSObject, FendTunnelProviderDelegate {
    func vpnWillStart() {
        print("vpnWillStart")
    }

    func vpnDidStart() {
        print("vpnDidStart")
    }

    func vpnWillStop() {
        print("vpnWillStop")
    }

    func didReceive(error: Error) {
        print("didReceive: \(error)")
    }
}
///

3.5. Error Handling

Most of the FendSDK calls are accepting completion blocks with errors. If an error occurs, you will receive non-nil Error object with an explanation.

Last updated