无法在 iOS 上使用 NE***Manager 创建 IPSEC 连接
Posted
技术标签:
【中文标题】无法在 iOS 上使用 NE***Manager 创建 IPSEC 连接【英文标题】:Can't create IPSEC connection using NE***Manager on iOS 【发布时间】:2014-12-14 16:35:07 【问题描述】:我正在尝试在我的 ios 应用中创建 IPSEC *** 连接。
我设置配置的代码如下所示:
-(void)setUpConfig
NE***Manager *manager = [NE***Manager sharedManager];
int status = manager.connection.status;
if (status == NE***StatusConnected)
manager.connection stop***Tunnel];
else
[manager loadFromPreferencesWithCompletionHandler:^(NSError *error)
NSError *startError;
if (error)
NSLog(@"Load config failed [%@]", error.localizedDescription);
return;
NE***ProtocolIPSec *p = (NE***ProtocolIPSec *)self.manager.protocol;
if (!p)
p = [[NE***ProtocolIPSec alloc] init];
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"base64_encoded_cert" ofType:@"txt"];
NSString *certBase64String = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
NSString *certPassword = @"cert_import_password";
NSString ****Username = @"myUsername";
NSString ****Password = @"myPassword";
NSString *url = @"my.server.address";
// This saves my credentials to the keychain and returns a persistent keychain reference
NSData *passRef = [self add***CredentialsToKeychain:***Username withPassword:***Password];
p.username = ***Username;
p.authenticationMethod = NE***IKEAuthenticationMethodCertificate;
p.serverAddress = url;
p.passwordReference = passRef;
p.identityData = [NSData dataWithBase64EncodedString:certBase64String];
p.identityDataPassword = certPassword;
p.disconnectOnSleep = NO;
p.useExtendedAuthentication = YES;
[manager setProtocol:p];
[manager setOnDemandEnabled:NO];
[manager setLocalizedDescription:@"My ***"];
[manager saveToPreferencesWithCompletionHandler:^(NSError *error)
if(error)
NSLog(@"Save error: %@", error);
else
NSLog(@"Saved!");
];
];
-(NSData*)add***CredentialsToKeychain:(NSString*)username withPassword:(NSString*)password
NSMutableDictionary *keychainItem = [NSMutableDictionary dictionary];
NSData *encodedIdentifier = [username dataUsingEncoding:NSUTF8StringEncoding];
keychainItem[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;
keychainItem[(__bridge id)kSecAttrDescription] = @"A password used to authenticate on a *** server";
keychainItem[(__bridge id)kSecAttrGeneric] = encodedIdentifier;
keychainItem[(__bridge id)kSecAttrAccount] = encodedIdentifier;
keychainItem[(__bridge id)kSecAttrService] = [[NSBundle mainBundle] bundleIdentifier];
keychainItem[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
keychainItem[(__bridge id)kSecReturnPersistentRef] = @YES;
CFTypeRef typeResult = nil;
OSStatus sts = SecItemCopyMatching((__bridge CFDictionaryRef)keychainItem, &typeResult);
NSLog(@"Error Code: %d", (int)sts);
if(sts == noErr)
NSData *theReference = (__bridge NSData *)typeResult;
return theReference;
else
keychainItem[(__bridge id)kSecValueData] = [password dataUsingEncoding:NSUTF8StringEncoding]; //Our password
OSStatus sts = SecItemAdd((__bridge CFDictionaryRef)keychainItem, &typeResult);
NSLog(@"Error Code: %d", (int)sts);
NSData *theReference = (__bridge NSData *)(typeResult);
return theReference;
return nil;
然后我尝试像这样打开一个 *** 连接:
-(void)connect
NE***Manager *manager = [NE***Manager sharedManager];
[manager loadFromPreferencesWithCompletionHandler:^(NSError *error)
NSError *startError;
[manager.connection start***TunnelAndReturnError:&startError];
if(startError)
NSLog(@"Start error: %@", startError.localizedDescription);
];
这确实在大多数情况下都有效。我遇到的问题是,在工厂恢复设备(当然是在 iOS 8 上)并尝试通过此设置和连接后,我的配置文件安装得很好,但 *** 无法连接。事实上,我的解释是它无法尝试连接。
在恢复设备并尝试使用我的方法连接后,设备日志中显示以下内容:
<Notice>: NESMLegacySession[My***:BB73C098-B22E-46D3-9491-2A6D9F559F8F]: Received a start command from ***App[256], but start was rejected
进入“设置”应用并尝试使用“蓝牙”下的开关手动切换 *** 会导致开关在瞬间打开,然后立即关闭。在这种情况下,会产生以下日志:
<Warning>: -[***BundleController _***NetworkingIsDisabled]: Airplane mode: 0, WiFi Enabled: 1
在这两种情况下,当 *** 无法开始连接时不会生成错误对话框 - 只是日志。
我可以通过导航到“设置”>“常规”>“***”来解决此问题。一旦刚刚进入到那个页面(即不在那里切换 ***),我就可以很好地控制 ***。即使在安装 *** 配置之前进入该页面,我也能够在安装配置后正常连接。
我的目标是能够启动 *** 连接,而无需先进入“设置”中的那个 *** 页面。任何人都可以阐明情况吗?在我看来,我似乎缺少首先启用 *** 连接的东西。
【问题讨论】:
【参考方案1】:这是因为 *** 配置默认保持 disabled
用于初始 *** 连接。
您必须在saveToPreferencesWithCompletionHandler
之前启用***。
[[NE***Manager sharedManager] setEnabled:YES];
示例:
[[NE***Manager sharedManager] loadFromPreferencesWithCompletionHandler: ^(NSError *error)
if (error)
NSLog(@"Load error: %@", error);
else
// No errors! The rest of your codes goes here...
NE***ProtocolIPSec *p = [[NE***ProtocolIPSec alloc] init];
p.serverAddress = @"*** SERVER ADDRESS";
p.authenticationMethod = NE***IKEAuthenticationMethodCertificate;
p.localIdentifier = @"Local identifier";
p.remoteIdentifier = @"Remote identifier";
p.useExtendedAuthentication = YES;
p.identityData = [NSData dataWithBase64EncodedString:certBase64String];;
p.identityDataPassword = @"identity password";
p.disconnectOnSleep = NO;
// Set protocol
[[NE***Manager sharedManager] setProtocol:p];
// Set on demand
NSMutableArray *rules = [[NSMutableArray alloc] init];
NEOnDemandRuleConnect *connectRule = [NEOnDemandRuleConnect new];
[rules addObject:connectRule];
[[NE***Manager sharedManager] setOnDemandRules:rules];
// Set localized description
[[NE***Manager sharedManager] setLocalizedDescription:@"Description"];
// Enable ***
[[NE***Manager sharedManager] setEnabled:YES];
// Save to preference
[[NE***Manager sharedManager] saveToPreferencesWithCompletionHandler: ^(NSError *error)
NSLog(@"Save *** to preference complete");
if (error)
NSLog(@"Save to preference error: %@", error);
];
];
【讨论】:
以上是关于无法在 iOS 上使用 NE***Manager 创建 IPSEC 连接的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 8 中使用 NE***Manager,如何以编程方式创建与自定义 *** 类型的 *** 连接? (例如思科任何连接)
NE***Manager 中使用的 Swift 中的钥匙串引用