VPN L2TP/IPsec with NEVPNManager (Objective-c)

Hi Everyone,


I'm hoping someone can help me. I'm working on an interal project for my company when the people in the building use the app on the WiFi.

We want to add the ability for the commands send over the network to be sent via a VPN connection when the users device disconnects from the WiFi for any reason.


This is my code currently but I am not having any luck.


Creating the VPN Connection.

NEVPNManager *manager = [NEVPNManager sharedManager];

    [manager loadFromPreferencesWithCompletionHandler:^(NSError *error) {
        if(error) {
            NSMutableString *tempyMessage = [[NSMutableString alloc] init];
            [tempyMessage appendString:@"There was an error with NEVPNManager\n\n"];
            [tempyMessage appendString:[error localizedDescription]];
            NSLog(@"Load error: %@", error);
            [[[UIAlertView alloc] initWithTitle:@"VPN Check" message:tempyMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        } else {
            // No errors! The rest of your codes goes here...
            [[[UIAlertView alloc] initWithTitle:@"VPN Check" message:@"No error" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
            NSString *username = @"user";
            NSString *password = @"password";
            [KeyChainManager saveButtonPressed:username password:password];
          
            NSString *secret = @"secret";
            NSString *secretString = @"unique-secret";
            [KeyChainManager saveButtonPressed:secretString password:secret];
          
            NEVPNProtocolIPSec *p = [[NEVPNProtocolIPSec alloc] init];
            p.username = username;
            p.passwordReference = [KeyChainManager getPasswordData:username];
            p.serverAddress = @"vpn_server";
            p.authenticationMethod = NEVPNIKEAuthenticationMethodSharedSecret;
            p.sharedSecretReference = [KeyChainManager getPasswordData:secretString];
            p.localIdentifier = @"vpn";
            p.remoteIdentifier = @"vpn";
            p.useExtendedAuthentication = NO;
            p.disconnectOnSleep = YES;
          
            [manager setProtocol:p];
            [manager setOnDemandEnabled:p];
            [manager setLocalizedDescription:@"My_App_VPN"];
          
            [manager saveToPreferencesWithCompletionHandler:^(NSError *error2){
                if(error2) {
                    NSMutableString *tempyMessage = [[NSMutableString alloc] init];
                    [tempyMessage appendString:@"There was an error with NEVPNManager\n\n"];
                    [tempyMessage appendString:[error2 localizedDescription]];
                    NSLog(@"Load error: %@", error2);
                    [[[UIAlertView alloc] initWithTitle:@"Saving VPN..." message:tempyMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
                } else {
                    // No errors! The rest of your codes goes here...
                    [[[UIAlertView alloc] initWithTitle:@"Saving VPN..." message:@"Saved" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
                }    
            }];
        }
    }];
    manager = nil;



Code calling the VPN connection.

[[NEVPNManager sharedManager] setEnabled:true];
    [[NEVPNManager sharedManager] setOnDemandEnabled:true];
   
    NSError *startError;
    [[NEVPNManager sharedManager].connection startVPNTunnelAndReturnError:&startError];
    if(startError){
        NSMutableString *tempyMessage = [[NSMutableString alloc] init];
        [tempyMessage appendString:@"There was an error with NEVPNManager\n\n"];
        [tempyMessage appendString:[startError localizedDescription]];
        NSLog(@"Load error: %@", startError);
        [[[UIAlertView alloc] initWithTitle:@"No Connection" message:tempyMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
    }
    else{
        //Network call is made here.
        /*
          This is where the call to the server is not being processed either by not being sent to the server,
          as the server can only be access via VPN or due to issues in the above code.
        */
     }


Hopefully someone can help me or point me in the right direction.

Replies

We want to add the ability for the commands send over the network to be sent via a VPN connection when the users device disconnects from the WiFi for any reason.

It sounds like you’re trying to do clever stuff with VPN On Demand. I don’t know a lot about that personally, but I strongly recommend that you prototype your setup using a configuration profile rather than code. That’s for two reasons:

  • It’s much easier and faster to test stuff with configuration profiles than with building and running an app.

  • The Personal VPN facility you access via NEVPNManager represents a strict subset of the VPN features accessible via a configuration profile, so if you can’t get things working with a profile then there’s no way that NEVPNManager is going to work.

A good place to get started with configuration profiles is the Apple Configurator app. Beyond that, you need to dig into the Configuration Profile Reference.

Share and Enjoy

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

let myEmail = "eskimo" + "1" + "@apple.com"

WWDC runs Mon, 13 Jun through to Fri, 17 Jun. During that time all of DTS will be at the conference, helping folks out face-to-face. http://developer.apple.com/wwdc/

Awesome thank you for the feedback eskimo.


I'll look into that and hopefully come right.

Too bad that L2TP is NOT accessible through NEVPNManager class,
At least, according to another post of Eskimo!!

But there is also mentioned something like,
NEVPNManager supports third-party transports (beside the built-in IPsec and IKEv2 transports),
with the caveat that you have to develop the protocol yourself.