I'm trying to make a custom TunnelProvider network extension by starting with the XCode template for the TunnelProvider and then adding the code to the host app in order to configure it and start it.
I am using an instance of NETunnelProviderManager to configure it, and when I call saveToPreferencesWithCompletionHandler: I get success (error = 0). However, when I call startVPNTunnelAndReturnError: on the (non-zero) connection I always get the below error:
Error Domain=NEVPNErrorDomain Code=1 "(null)"
I have read through all of the related Apple documentation as well as tried to make my program look as close as possible to the SimpleTunnel test program, however I cannot determine why I am getting this "1" (which seems to indicate a configuration issue).
I've seen a few other people with this same problem in posts around the net, but no solutions.
I have the special entitlements required and I know that is not the issue since after using the proper provisioning profile I was able to see the popup confirming I want to add a VPN when I run the app, and then it get's added in Settings under VPN.
Here is my code in case it is relevant:
NETunnelProviderManager * man = [[NETunnelProviderManager alloc] init];
NETunnelProviderProtocol *protocol = [[NETunnelProviderProtocol alloc] init];
[protocol setServerAddress:@"aaa.bbb.ccc.ddd"]; // not actual value
[protocol setUsername:@"testuser"];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
NSData *data = [[NSData alloc] init];
[dictionary setObject:@"UUID" forKey:(id)kSecAttrService];
[dictionary setObject:data forKey:(id)kSecValueData];
[dictionary setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(id)kSecAttrAccessible];
[dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(id)kSecClass];
[dictionary setObject:(__bridge id)kCFBooleanTrue forKey:(id)kSecReturnPersistentRef];
CFTypeRef passwordRef = nil;
OSStatus delStatus = SecItemDelete((__bridge CFDictionaryRef)dictionary);
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dictionary, &passwordRef);
[protocol setPasswordReference:(__bridge NSData * _Nullable)(passwordRef)];
man.protocolConfiguration = protocol;
man.localizedDescription = @"My VPN";
man.onDemandEnabled = false;
man.enabled = true;
[man saveToPreferencesWithCompletionHandler:^(NSError *err) {
NSLog(@"saved preferences: error = %@", err);
[man.connection startVPNTunnelAndReturnError:&err];
NSLog(@"after start tunnel: error = %@", err);
}];