【问题标题】:How can we update NEVPNProtocol params like serverAddress and username?我们如何更新像 serverAddress 和 username 这样的 NEVPNProtocol 参数?
【发布时间】:2017-02-14 12:01:25
【问题描述】:

我的应用程序充当 IPSec VPN 服务器 (strongSwan) 的 VPN 客户端。 我已经使用 NEVPNManager 来设置 VPN 配置文件。代码是这样的:

#define KEY_PASSWORD @"password"
#define PASSWORD @"password"
#define VPN_SERVER @"10.1.1.1"
#define KEY_USERNAME @"username"
#define USERNAME @"myusername"
#define KEY_SHARED_SECRET @"sharedSecret"
#define SHARED_SECRET @"thisisthesecretekey"
#define LOCAL_IDENTIFIER @"myserver.com.client"
#define REMOTE_IDENTIFIER @"myserver.com.server"

-(void) setupVPNProfile {    
    NEVPNProtocolIKEv2 *protocol = [[NEVPNProtocolIKEv2 alloc] init];
    protocol.username = USERNAME;
    NSData *passwdRef = [self getData:KEY_PASSWORD];
    if (passwdRef == nil) {
        [self storeData:KEY_PASSWORD data:[PASSWORD dataUsingEncoding:NSUTF8StringEncoding]];
        passwdRef = [self getData:PASSWORD];
        NSLog(@"passwdRef: %@", [[NSString alloc] initWithData:passwdRef encoding:NSUTF8StringEncoding]);
    }
    protocol.passwordReference = passwdRef;

    protocol.serverAddress = VPN_SERVER;

    protocol.authenticationMethod = NEVPNIKEAuthenticationMethodSharedSecret;
    NSData *sharedSecretRef = [self getData:KEY_SHARED_SECRET];
    if (sharedSecretRef == nil) {
        [self storeData:KEY_SHARED_SECRET data:[SHARED_SECRET dataUsingEncoding:NSUTF8StringEncoding]];
        sharedSecretRef = [self getData:KEY_SHARED_SECRET];
        NSLog(@"sharedSecretRef: %@", [[NSString alloc] initWithData:sharedSecretRef encoding:NSUTF8StringEncoding]);

    }
    protocol.sharedSecretReference = sharedSecretRef;

    protocol.localIdentifier = LOCAL_IDENTIFIER;
    protocol.remoteIdentifier = REMOTE_IDENTIFIER;

    protocol.useExtendedAuthentication = YES;

    protocol.disconnectOnSleep = NO;

    self.manager.protocolConfiguration = protocol;

    self.manager.enabled = YES;
}

#pragma mark - Keychain methods

- (void) storeData: (NSString * )key data:(NSData *)data {
    NSLog(@"Store Data");
    NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
    [dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
    NSData *encodedKey = [key dataUsingEncoding:NSUTF8StringEncoding];
    [dict setObject:encodedKey forKey:(__bridge id)kSecAttrGeneric];
    [dict setObject:encodedKey forKey:(__bridge id)kSecAttrAccount];
    [dict setObject:@"VPN" forKey:(__bridge id)kSecAttrService];
    [dict setObject:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];
    [dict setObject:data forKey:(__bridge id)kSecValueData];

    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
    if(errSecSuccess != status) {
        NSLog(@"Unable add item with key =%@ error:%d",key,(int)status);
    }
}

- (NSData *) getData: (NSString *)key {
    NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
    [dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
    NSData *encodedKey = [key dataUsingEncoding:NSUTF8StringEncoding];
    [dict setObject:encodedKey forKey:(__bridge id)kSecAttrGeneric];
    [dict setObject:encodedKey forKey:(__bridge id)kSecAttrAccount];
    [dict setObject:@"VPN" forKey:(__bridge id)kSecAttrService];
    [dict setObject:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];
    [dict setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    [dict setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnPersistentRef];

    CFTypeRef result = NULL;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)dict,&result);

    if( status != errSecSuccess) {
        NSLog(@"Unable to fetch item for key %@ with error:%d",key,(int)status);
        return nil;
    }

    NSData *resultData = (__bridge NSData *)result;
   return resultData;
}

- (BOOL) removeData: (NSString *) key {
    NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
    [dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
    NSData *encodedKey = [key dataUsingEncoding:NSUTF8StringEncoding];
    [dict setObject:encodedKey forKey:(__bridge id)kSecAttrGeneric];
    [dict setObject:encodedKey forKey:(__bridge id)kSecAttrAccount];
    [dict setObject:@"VPN" forKey:(__bridge id)kSecAttrService];
    [dict setObject:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];

    OSStatus status = SecItemDelete((__bridge CFDictionaryRef)dict);

    if( status != errSecSuccess) {
        NSLog(@"Unable to fetch item for key %@ with error:%d",key,(int)status);
        return NO;
    }

    return YES;
}

这里的用户名、密码服务器地址等值存储在上面定义的 MACROS 中。根据所需的设计,密码和 sharedSecret 将存储为 Persistent KeyChain 项。 在此设置中,如何优雅地更改用户名、密码、serverAddress、sharedSecret 等值?

到目前为止我所尝试的:

  1. 我更改了代码中的服务器地址、用户名等值。一世 使用 storeData 函数覆盖密码和 sharedSecret 持久的钥匙串项目。但是,当我在制作后运行应用程序时 这些更改我无法连接到新的 VPN 服务器。请 请注意,我没有对我必须使用的新值犯任何错误 采用。我在更新前仔细检查了。另请注意,我是 创建 .mobileconfig 文件时能够连接到 VPN 服务器 从那些新参数中。只是我的 VPN 客户端应用程序不是 能够连接到服务器了。它会尝试连接并且会 再次断开连接。卸载应用程序也没有效果。

  2. 设置 manager.protocolConfiguration = nil。这样做没有任何效果。已安装的 protocolConfiguration 保持不变。

我不想通过调用管理器 removePreferencesWithCompletionHandler:] 来删除 VPN 配置文件,因为用户在尝试连接到 VPN 服务器时会再次看到与 VPN 相关的弹出窗口。 如果有人以前这样做过,请提供帮助。 谢谢。

【问题讨论】:

    标签: ios networkextension nevpnmanager


    【解决方案1】:

    要更改 VPN 帐户,您应该能够简单地更改 VPN 帐户参数,然后使用新值启动 VPNManager。您不需要停止当前正在运行的 VPN 会话,当然也不需要删除配置文件,只需调用 NEVPNManager.shared.locadFromPreferences,进行更改,然后正常运行 .saveToPreferences 和 startVPNTunnel。

    由于即使使用已知的良好凭据使用变量而不是宏,您也无法启动 VPN 隧道,因此您可能从钥匙串中错误地传递了值,或者不是您所期望的。我会使用打印语句比较每个参数,首先与您当前使用宏的工作解决方案,然后与非工作钥匙串代码。

    【讨论】:

    • 谢谢。我会试试这个,让你知道会发生什么。看起来我至少必须停止当前的连接。只有这样我才能调用 startVPNTunnel 才有意义。但是,我可以忍受。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多