5

我找不到关于如何做到这一点的明确答案,所以这就是我创建这个线程的原因。
我正在开发一个 Swift 应用程序 (Swift 2),我想在其中使用一个函数连接一个 VPN 服务器。所以我想创建一个

func connect() {
    //Handle the connection to the VPN 
}

我从制作 VPN 的开发人员那里收到了这个https://gist.github.com/matthijsotterloo/cedf256f7f1c2a9a8f624481b7083afd文件(当然我替换了证书、密钥、url 和登录名。现在我的问题是如何连接到这个 VPN 服务器功能?我已经发现我必须使用 NEVPNManager 但我真的不知道如何构建它。

希望有人可以帮助我。

谢谢!

4

1 回答 1

7

这有点令人困惑,但您使用所需参数设置配置,然后将该配置保存到 NEVPNManager。之后启动 VPN 隧道。

所以你会有类似的东西:

    NEVPNManager.sharedManager().loadFromPreferencesWithCompletionHandler { error in
        // setup the config:
        let password = vpnAccount!.vpnPassword          
        let vpnhost = vpnAccount!.vpnHost
        let p = NEVPNProtocolIKEv2()
        p.username = username
        p.localIdentifier = username
        p.serverAddress = vpnhost
        p.remoteIdentifier = vpnhost
        p.authenticationMethod = .None
        p.passwordReference = passwordRef
        p.useExtendedAuthentication = true
        p.serverCertificateIssuerCommonName = vpnhost
        p.disconnectOnSleep = false


        var rules = [NEOnDemandRule]()
        let rule = NEOnDemandRuleConnect()
        rule.interfaceTypeMatch = .Any
        rules.append(rule)

        NEVPNManager.sharedManager().localizedDescription = "My VPN"
        NEVPNManager.sharedManager().protocolConfiguration = p
        NEVPNManager.sharedManager().onDemandRules = rules
        NEVPNManager.sharedManager().onDemandEnabled = true
        NEVPNManager.sharedManager().enabled = true
        NEVPNManager.sharedManager().saveToPreferencesWithCompletionHandler { error in
            guard error == nil else {
                print("NEVPNManager.saveToPreferencesWithCompletionHandler failed: \(error!.localizedDescription)")
                return
            }
            VPNManager.sharedManager.startVPNTunnel()
        }
     }

正确嵌套完成处理程序也是不明显但很重要的:

    loadFromPreferencesWithCompletionHandler{ 
        ...
        saveToPreferencesWithCompletionHandler{ 
            startVPNTunnel 
        }
    }

密码参考是:

                let password = vpnAccount!.vpnPassword
                vpnAccount!.setPersistenRef(username, password: password!)
                let passwordRef = vpnAccount!.persistentRef

和 vpnAccount.persistentRef 是:

class func persistentRef(_ key: String) -> Data? {
    let query: [AnyHashable: Any] = [
        kSecClass as AnyHashable: kSecClassGenericPassword,
        kSecAttrGeneric as AnyHashable: key,
        kSecAttrAccount as AnyHashable: key,
        kSecAttrAccessible as AnyHashable: kSecAttrAccessibleAlways,
        kSecMatchLimit as AnyHashable: kSecMatchLimitOne,
        kSecAttrService as AnyHashable: Bundle.main.bundleIdentifier!,
        kSecReturnPersistentRef as AnyHashable: kCFBooleanTrue
    ]

    var secItem: AnyObject?
    let result = SecItemCopyMatching(query as CFDictionary, &secItem)
    if result != errSecSuccess {
        return nil
    }

    return secItem as? Data
}

我不记得细节,但似乎记得上面对于创建 NEVPNManager 正在寻找的 ref 非常重要。

于 2016-08-27T17:34:12.773 回答