Search code examples
iosswiftswift3networkextensionnevpnmanager

Negotiation with the VPN server has failed (NEVPNProtocolIPSec, Swift 3.0.2)


guys.

I'm trying to setup a VPN connection to my server, but something goes wrong.

I've tried setting it up manually and it works.

Here's my configuration code. The server object has a name and a correct host for sure and i tried disabling extended authentication. Afaik remote and local identifiers are just random strings, so i have no idea what i could have done wrong.

fileprivate func updateCurrentVPN(withServer server: Server, completion: ((Bool) -> Void)?) {

    let passwordRef = KeychainWrapper.standard.dataRef(forKey: self.account.username)
    let secretRef = KeychainWrapper.standard.dataRef(forKey: API.ipsecSecretKey())

    // checking if the strings are correct in a debugger
    let password = KeychainWrapper.standard.string(forKey: self.account.username)
    let secret = KeychainWrapper.standard.string(forKey: API.ipsecSecretKey())

    // VPN
    let manager = NEVPNManager.shared()
    manager.loadFromPreferences { (error) in
        if (error != nil)
        {
            print("Error: ", error.debugDescription)
            completion?(false)
        }
        else
        {
            let prtcl = NEVPNProtocolIPSec()
            prtcl.username = self.account.username
            prtcl.passwordReference = passwordRef
            prtcl.serverAddress = server.host
            prtcl.authenticationMethod = NEVPNIKEAuthenticationMethod.sharedSecret
            prtcl.sharedSecretReference = secretRef
            prtcl.localIdentifier = "Test iOS device"
            prtcl.remoteIdentifier = server.name
            prtcl.useExtendedAuthentication = true
            prtcl.disconnectOnSleep = false

            manager.isEnabled = true
            manager.protocolConfiguration = prtcl
            manager.isOnDemandEnabled = false
            manager.localizedDescription = "MyVPN Configuration"
            manager.saveToPreferences(completionHandler: { (error) in
                if (error != nil)
                {
                    print("Error: ", error.debugDescription)
                    completion?(false)
                }
                else
                {
                    self.serverButton.setTitle(server.name, for: UIControlState.normal)
                    print("VPN prefs saved")
                    completion?(true)
                }
            })
        }
    }

After config is saved i do:

 let manager = NEVPNManager.shared()
 do {
    try manager.connection.startVPNTunnel()
 } catch {
    print(error.localizedDescription)
    connectButton.setTitle("da failure :(", for: UIControlState.normal)
 }

But it never throws an error, just prompts me with "Negotiation with the VPN server has failed" in a system alert. Btw, is it possible to catch this kind of errors?


Solution

  • Apparently, there's a bug is iOS SDK, according to this answer. Afaik the SDK treats local identifier as a group name and when it's set, the client initiating a Aggressive Mode IKE_SA. Turned out even if you permit aggressive mode on a backend it won't change much (in my case it didnt).

    Removing lines

    prtcl.localIdentifier = "Test iOS device"
    prtcl.remoteIdentifier = server.name
    

    fixes the issue.