-
-
Save zqqf16/cbcbd2254e6cb965f1a3 to your computer and use it in GitHub Desktop.
- (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; | |
} |
你好,想问下如果用ikev2,和ipsec区别大吗?不需要证书和共享密钥也可以吗?
在代码里需要哪些不一样的设置?
还有就是
p.identityData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]];
p.identityDataPassword = @"[Your certificate import password]"
这个文件应该是服务器中配置的文件吗?
我曾尝试买的ikev2账号,他给了两个描述文件安装,跟这个有关系吗?
只能拿到苹果的接口文件,很难深入去了解,help,please!
我也出现 VPN 服务器未响应,使用xcode自带的抓包发现没有发出验证请求,而我手动在iphone中配置l2tp连接时是成功的,并且抓包中成功发现VP验证请求,不知道是什么原因引起的
应该说不是没发出验证请求,而是发出的地址为空,也就是肯定没法到达,所以才出现“服务器未响应问题”
@Yiranfantexi 差别不大,具体参见这个 Gist
据我现在掌握的,在 iOS 中,IKEv2 的“设备鉴定”方式只能是证书和共享密钥二选一。
至于那两个描述文件,可以用 Apple Configurator 打开看看,能看见 VPN 的配置信息。
我试过买的账号,当p.authenticationMethod=NEVPNIKEAuthenticationMethodNone ,不要证书和密钥也是可以实现连接的!我也是用strong swan 搭建的服务器安卓的可以实现连接,但是苹果的ikev2不行 只有ipsec 可以!醉了!!
@Yiranfantexi IPSec IKE(v1/v2) 各个公司的实现方式都不一样,支持的加密算法什么的也是乱七八糟 😂
你好,我使用共享密钥来的方式连接,再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的话是必须要申请开发权限吗?
请问一下,从keychain 中获取密码 。没有设置密码,怎么能获取到呢?还是预先在哪里设置加载的密码到keychain里面?