Last active
May 29, 2020 08:11
-
-
Save zqqf16/cbcbd2254e6cb965f1a3 to your computer and use it in GitHub Desktop.
Start IPSec programmatically in iOS 8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
// init VPN manager | |
self.vpnManager = [NEVPNManager sharedManager]; | |
// load config from perference | |
[_vpnManager loadFromPreferencesWithCompletionHandler:^(NSError *error) { | |
if (error) { | |
NSLog(@"Load config failed [%@]", error.localizedDescription); | |
return; | |
} | |
NEVPNProtocolIPSec *p = _vpnManager.protocol; | |
if (p) { | |
// Protocol exists. | |
// If you don't want to edit it, just return here. | |
} else { | |
// create a new one. | |
p = [[NEVPNProtocolIPSec alloc] init]; | |
} | |
// config IPSec protocol | |
p.username = @"[Your username]"; | |
p.serverAddress = @"[Your server address]";; | |
// Get password persistent reference from keychain | |
// If password doesn't exist in keychain, should create it beforehand. | |
// [self createKeychainValue:@"your_password" forIdentifier:@"VPN_PASSWORD"]; | |
p.passwordReference = [self searchKeychainCopyMatching:@"VPN_PASSWORD"]; | |
// PSK | |
p.authenticationMethod = NEVPNIKEAuthenticationMethodSharedSecret; | |
// [self createKeychainValue:@"your_psk" forIdentifier:@"PSK"]; | |
p.sharedSecretReference = [self searchKeychainCopyMatching:@"PSK"]; | |
/* | |
// certificate | |
p.identityData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]]; | |
p.identityDataPassword = @"[Your certificate import password]"; | |
*/ | |
p.localIdentifier = @"[VPN local identifier]"; | |
p.remoteIdentifier = @"[VPN remote identifier]"; | |
p.useExtendedAuthentication = YES; | |
p.disconnectOnSleep = NO; | |
_vpnManager.protocol = p; | |
_vpnManager.localizedDescription = @"IPSec Demo"; | |
[_vpnManager saveToPreferencesWithCompletionHandler:^(NSError *error) { | |
if (error) { | |
NSLog(@"Save config failed [%@]", error.localizedDescription); | |
} | |
}]; | |
}]; | |
} | |
- (IBAction)startVPNConnection:(id)sender { | |
//[[VodManager sharedManager] installVPNProfile]; | |
NSError *startError; | |
[_vpnManager.connection startVPNTunnelAndReturnError:&startError]; | |
if (startError) { | |
NSLog(@"Start VPN failed: [%@]", startError.localizedDescription); | |
} | |
} | |
#pragma mark - KeyChain | |
static NSString * const serviceName = @"im.zorro.ipsec_demo.vpn_config"; | |
- (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier { | |
NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init]; | |
[searchDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; | |
NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding]; | |
[searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrGeneric]; | |
[searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrAccount]; | |
[searchDictionary setObject:serviceName forKey:(__bridge id)kSecAttrService]; | |
return searchDictionary; | |
} | |
- (NSData *)searchKeychainCopyMatching:(NSString *)identifier { | |
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier]; | |
// Add search attributes | |
[searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; | |
// Add search return types | |
// Must be persistent ref !!!! | |
[searchDictionary setObject:@YES forKey:(__bridge id)kSecReturnPersistentRef]; | |
CFTypeRef result = NULL; | |
SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, &result); | |
return (__bridge_transfer NSData *)result; | |
} | |
- (BOOL)createKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier { | |
NSMutableDictionary *dictionary = [self newSearchDictionary:identifier]; | |
OSStatus status = SecItemDelete((__bridge CFDictionaryRef)dictionary); | |
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; | |
[dictionary setObject:passwordData forKey:(__bridge id)kSecValueData]; | |
status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL); | |
if (status == errSecSuccess) { | |
return YES; | |
} | |
return NO; | |
} |
你好,我使用共享密钥来的方式连接,再ios9的时候没有问题,但是ios8再安装描述文件的时候也出现了上边的描述文件未签名,还会出现闪退,有什么解决的办法吗
@lhs71173717你好我问一下 你那个ios8 描述文件的问题有解决办法吗 ?
@Cutezhao,你好,请问你的描述文件会不会提示 Save config faild[(null),我的会提示,请问你现在解决了吗?
How to use the above demo if .ovpn file is provided?
点击按钮的时候 提示“Start VPN failed: [The operation couldn’t be completed. (NEVPNErrorDomain error 1.)]” 这怎么回事啊
Just call loadFromPreferencesWithCompletionHandler right before startVPNTunnelAndReturnError.
It should helps you. @duoduoyi
Out of curiosity, is it possible to ignore local and remote identifier? or are they both mandatory?
请问想要开发VPN的话是必须要申请开发权限吗?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Yiranfantexi IPSec IKE(v1/v2) 各个公司的实现方式都不一样,支持的加密算法什么的也是乱七八糟 😂