Connect to VPN programmatically in iOS 8

Since the release of iOS 8 beta, I found a Network Extension framework in its bundle which is going to let developers configure and connect to VPN servers programmatically and without any profile installation.

The framework contains a major class called NEVPNManager. This class also has 3 main methods that let me save, load or remove VPN preferences. I’ve written a piece of code in viewDidLoad method as following:

  • IOS cannot set VPN programmatically
  • how to detect iphone's VPN connectivity?
  • iOS 7 programatically per app VPN
  • Mac OS VPN Connection Programetically
  • NetworkExtension connectOnDemand rules doesn't work
  • “Error Domain=NEVPNErrorDomain Code=1 \”(null)\“” While connecting VPN server
  • NEVPNManager *manager = [NEVPNManager sharedManager];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(vpnConnectionStatusChanged) name:NEVPNStatusDidChangeNotification object:nil];
    [manager loadFromPreferencesWithCompletionHandler:^(NSError *error) {
        if(error) {
            NSLog(@"Load error: %@", error);
        }}];
    NEVPNProtocolIPSec *p = [[NEVPNProtocolIPSec alloc] init];
    p.username = @“[My username]”;
    p.passwordReference = [KeyChainAccess loadDataForServiceNamed:@"VIT"];
    p.serverAddress = @“[My Server Address]“;
    p.authenticationMethod = NEVPNIKEAuthenticationMethodCertificate;
    p.localIdentifier = @“[My Local identifier]”;
    p.remoteIdentifier = @“[My Remote identifier]”;
    p.useExtendedAuthentication = NO;
    p.identityData = [My VPN certification private key];
    p.disconnectOnSleep = NO;
    [manager setProtocol:p];
    [manager setOnDemandEnabled:NO];
    [manager setLocalizedDescription:@"VIT VPN"];
    NSArray *array = [NSArray new];
    [manager setOnDemandRules: array];
    NSLog(@"Connection desciption: %@", manager.localizedDescription);
    NSLog(@"VPN status:  %i", manager.connection.status);
    [manager saveToPreferencesWithCompletionHandler:^(NSError *error) {
       if(error) {
          NSLog(@"Save error: %@", error);
       }
    }];
    

    I also placed a button in my view and set its TouchUpInside action to the method below:

    - (IBAction)buttonPressed:(id)sender {
       NSError *startError;
       [[NEVPNManager sharedManager].connection startVPNTunnelAndReturnError:&startError];
       if(startError) {
          NSLog(@"Start error: %@", startError.localizedDescription);
       }
    }
    

    There are two problems here:

    1) When I try to save the preferences, the following error will be thrown: 
Save error: Error Domain=NEVPNErrorDomain Code=4 “The operation couldn’t be completed. (NEVPNErrorDomain error 4.)”
What is this error? How can I solve this issue?

    2) [[NEVPNManager sharedManager].connection startVPNTunnelAndReturnError:&startError]; method doesn’t return any error when I call it but the connection status changes from Disconnected to Connecting for just a moment and then it gets back to Disconnected state.

    Any help will be appreciated 🙂

    2 Solutions Collect From Internet About “Connect to VPN programmatically in iOS 8”

    The problem is the error you are getting when saving:
    Save error: Error Domain=NEVPNErrorDomain Code=4

    If you look in the NEVPNManager.h header file, you will see that error code 4 is “NEVPNErrorConfigurationStale”. The configuration is stale and needs to be loaded.
    You should call loadFromPreferencesWithCompletionHandler: and in the completion handler modify the values you want to modify, and then call saveToPreferencesWithCompletionHandler:. The example in your question is modifying the configuration before the loading is completed, which is why you are getting this error.

    More like this:

    [manager loadFromPreferencesWithCompletionHandler:^(NSError *error) {
         // do config stuff
         [manager saveToPreferencesWithCompletionHandler:^(NSError *error) {
         }];
    }];
    

    I’ve published a blog post regarding this post. It’s a complete tutorial about VPN connection management in iOS 8 which can be found here