13 Replies
      Latest reply on Apr 24, 2019 12:07 AM by eskimo
      sticl Level 1 Level 1 (0 points)

        i am using the network extension to connecting my ikev2 server

         

        but it always disconnect from server after I call the startVPNTunnal function , and the last connection error information shows like below

         

        _lastDisconnectError NSError * domain: NEVPNConnectionErrorDomainPlugin- code: 7 0x0000000283a5da70

         

        my code is like this

         

         

        fileprivatefunc connect() {
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(1 * NSEC_PER_SEC)) / Double(NSEC_PER_SEC)) {
                    self.vpnManager.loadFromPreferences { (error) in
              
                        if let error = error {
                            print(error.localizedDescription)
                            self.delegate?.vpnConnectionStatusDidChanged(manager: self, status: .invalid)
                            return
                        }
              
                        do {
                            try self.vpnManager.connection.startVPNTunnel()
                            print("success")
                        } catch let error{
                            print("failed: " + error.localizedDescription)
                            self.delegate?.vpnConnectionStatusDidChanged(manager: self, status: .disconnected)
                        }
              
                    }
                }
            }
        
        
        func savePassword(_ password: String, inKeychainItem: Data?) -> Data? {
                guard let passwordData = password.data(using: String.Encoding.utf8, allowLossyConversion: false) else { return nil }
                var status = errSecSuccess
          
                if let persistentReference = inKeychainItem {
                    // A persistent reference was given, update the corresponding keychain item.
                    let query: [NSObject: AnyObject] = [
                        kSecValuePersistentRef : persistentReference as AnyObject,
                        kSecReturnAttributes : kCFBooleanTrue
                    ]
                    var result: AnyObject?
              
                    // Get the current attributes for the item.
                    status = SecItemCopyMatching(query as CFDictionary, &result)
              
                    if let attributes = result as? [NSObject: AnyObject] , status == errSecSuccess {
                        // Update the attributes with the new data.
                        var updateQuery = [NSObject: AnyObject]()
                        updateQuery[kSecClass] = kSecClassGenericPassword
                        updateQuery[kSecAttrService] = attributes[kSecAttrService]
                  
                        var newAttributes = attributes
                        newAttributes[kSecValueData] = passwordData as AnyObject?
                  
                        status = SecItemUpdate(updateQuery as CFDictionary, newAttributes as CFDictionary)
                        if status == errSecSuccess {
                            return persistentReference
                        }
                    }
                }
          
                if inKeychainItem == nil || status != errSecSuccess {
                    // No persistent reference was provided, or the update failed. Add a new keychain item.
              
                    let attributes: [NSObject: AnyObject] = [
                        kSecAttrService : UUID().uuidString as AnyObject,
                        kSecValueData : passwordData as AnyObject,
                        kSecAttrAccessible : kSecAttrAccessibleAlways,
                        kSecClass : kSecClassGenericPassword,
                        kSecReturnPersistentRef : kCFBooleanTrue
                    ]
              
                    var result: AnyObject?
                    status = SecItemAdd(attributes as CFDictionary, &result)
              
                    if let newPersistentReference = result as? Data , status == errSecSuccess {
                        return newPersistentReference
                    }
                }
                return nil
            }
        
        
        func connect(vpn_protocol:SGVPNProtocol, ip: String, username: String, password: String, psk: String) {
            
                vpnManager.loadFromPreferences { (error) in
                
                    if error != nil {
                        print("Load error: \(error?.localizedDescription as String?)")
                        return
                    } else {
        
                        let configuration = NEVPNProtocolIKEv2()
                    
                        configuration.username = username
                        configuration.passwordReference =  self.savePassword(password, inKeychainItem: nil)
                        configuration.authenticationMethod = .none
                        configuration.useExtendedAuthentication = true
                        configuration.disconnectOnSleep = false
                   
                        configuration.serverAddress = ip
                        configuration.remoteIdentifier = ip
                        configuration.localIdentifier = ""
        
                        self.vpnManager.protocolConfiguration = configuration
                        self.vpnManager.localizedDescription = "xxxx"
                        self.vpnManager.isEnabled = true
                        self.vpnManager.isOnDemandEnabled = false
        
                        self.vpnManager.saveToPreferences(completionHandler: { (error) in
                            if error != nil {
                                print(error!.localizedDescription)
                                self.delegate?.vpnConnectionStatusDidChanged(manager: self, status: SGVPNStatus.invalid)
                                return
                            }
                        
                            self.vpnManager.loadFromPreferences(completionHandler: { error in
                                self.connect()
                            })
                        })
                    
                    }
                }
            }

         

        error information:

         

         

        Printing description of self.vpnManager._connection->_lastDisconnectError:

        Error Domain=NEVPNConnectionErrorDomainPlugin Code=7 "The VPN session failed because an internal error occurred." UserInfo={NSLocalizedDescription=The VPN session failed because an internal error occurred.}

        (lldb)

         

         

         

        i have done the capacities setting for Personer VPN and Network Extension

        • Re: NEVPNConnectionErrorDomainPlugin error code 7
          eskimo Apple Staff Apple Staff (11,325 points)

          i am using the network extension to connecting my ikev2 server but it always disconnect from server after I call the startVPNTunnal function

          First things first, if you set up this VPN configuration via a configuration profile, does that work?

          You can use Apple Configurator to create and install such a profile.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

          • Re: NEVPNConnectionErrorDomainPlugin error code 7
            eskimo Apple Staff Apple Staff (11,325 points)

            the vpn connection works fine in this way

            Excellent news.

            Did you use just a VPN payload (com.apple.vpn.managed)?  Or did you need to add some other payload type?  Like perhaps com.apple.security.root?

            If you only used a VPN payload, you should be able to create an equivalent configuration programmatically using NEVPNManager.  If you post the VPN payload (make sure to redact the password), I’ll reply back with some advice on how to set that up.

            Share and Enjoy

            Quinn “The Eskimo!”
            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
            let myEmail = "eskimo" + "1" + "@apple.com"

              • Re: NEVPNConnectionErrorDomainPlugin error code 7
                sticl Level 1 Level 1 (0 points)

                I posted all the code for my connection configuration above

                 

                i am using the vnp manager provicded by ios to build the connection configuration, and use manager.startVPNTunnal() to start the connection.

                 

                the problem is I always go discconnecting notification after I call startvontunnal(), and also there is an internal error

                 

                Printing description of self.vpnManager._connection->_lastDisconnectError:

                Error Domain=NEVPNConnectionErrorDomainPlugin Code=7 "The VPN session failed because an internal error occurred." UserInfo={NSLocalizedDescription=The VPN session failed because an internal error occurred.}

                  • Re: NEVPNConnectionErrorDomainPlugin error code 7
                    eskimo Apple Staff Apple Staff (11,325 points)

                    I posted all the code for my connection configuration above

                    Right.  I was hoping you’d be be able to post the configuration profile here (it’s a bunch of XML), because then I can check your code (which doesn’t work) against your profile (which does).

                    Share and Enjoy

                    Quinn “The Eskimo!”
                    Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                    let myEmail = "eskimo" + "1" + "@apple.com"

                      • Re: NEVPNConnectionErrorDomainPlugin error code 7
                        sticl Level 1 Level 1 (0 points)

                        sure

                         

                         

                         

                        <plist version=1.0>

                        <dict>

                        <key>PayloadContent</key>

                        <array>

                        <dict>

                        <key>IKEv2</key>

                        <dict>

                        <key>AuthName</key>

                        <string>vpn77</string>

                        <key>AuthPassword</key>

                        <string>a123456</string>

                        <key>AuthenticationMethod</key>

                        <string>None</string>

                        <key>ChildSecurityAssociationParameters</key>

                        <dict>

                        <key>DiffieHellmanGroup</key>

                        <integer>14</integer>

                        <key>EncryptionAlgorithm</key>

                        <string>AES-256</string>

                        <key>IntegrityAlgorithm</key>

                        <string>SHA2-256</string>

                        <key>LifeTimeInMinutes</key>

                        <integer>1440</integer>

                        </dict>

                        <key>DeadPeerDetectionRate</key>

                        <string>Medium</string>

                        <key>DisableMOBIKE</key>

                        <false/>

                        <key>DisableRedirect</key>

                        <false/>

                        <key>EnableCertificateRevocationCheck</key>

                        <false/>

                        <key>EnablePFS</key>

                        <false/>

                        <key>ExtendedAuthEnabled</key>

                        <true/>

                        <key>IKESecurityAssociationParameters</key>

                        <dict>

                        <key>DiffieHellmanGroup</key>

                        <integer>14</integer>

                        <key>EncryptionAlgorithm</key>

                        <string>AES-256</string>

                        <key>IntegrityAlgorithm</key>

                        <string>SHA2-256</string>

                        <key>LifeTimeInMinutes</key>

                        <integer>1440</integer>

                        </dict>

                        <key>LocalIdentifier</key>

                        <string>test.xxxx.cc</string>

                        <key>RemoteAddress</key>

                        <string>test.xxxx.cc</string>

                        <key>RemoteIdentifier</key>

                        <string>test.xxxx.cc</string>

                        <key>UseConfigurationAttributeInternalIPSubnet</key>

                        <false/>

                        </dict>

                        <key>IPv4</key>

                        <dict>

                        <key>OverridePrimary</key>

                        <integer>0</integer>

                        </dict>

                        <key>PayloadDescription</key>

                        <string>xx VPN xx</string>

                        <key>PayloadDisplayName</key>

                        <string>VPN</string>

                        <key>PayloadIdentifier</key>

                        <string>com.apple.vpn.managed.CA518586-9AFF-44D1-9E87-F3F0F29C7B8E</string>

                        <key>PayloadType</key>

                        <string>com.apple.vpn.managed</string>

                        <key>PayloadUUID</key>

                        <string>CA518586-9AFF-44D1-9E87-F3F0F29C7B8E</string>

                        <key>PayloadVersion</key>

                        <integer>1</integer>

                        <key>Proxies</key>

                        <dict>

                        <key>HTTPEnable</key>

                        <integer>0</integer>

                        <key>HTTPSEnable</key>

                        <integer>0</integer>

                        </dict>

                        <key>UserDefinedName</key>

                        <string>yyyy</string>

                        <key>VPNType</key>

                        <string>IKEv2</string>

                        </dict>

                        </array>

                        <key>PayloadDisplayName</key>

                        <string>vpnxxx</string>

                        <key>PayloadIdentifier</key>

                        <string>yangdeMac-mini.7BF5D337-3CE4-4A1D-A7EB-1B927B9E5C86</string>

                        <key>PayloadRemovalDisallowed</key>

                        <false/>

                        <key>PayloadType</key>

                        <string>Configuration</string>

                        <key>PayloadUUID</key>

                        <string>45F439D6-BEA8-4227-BF1D-6C2CC41E680A</string>

                        <key>PayloadVersion</key>

                        <integer>1</integer>

                        <key>RemovalDate</key>

                        <date>2019-07-17T03:16:10Z</date>

                        </dict>

                        </plist>

                          • Re: NEVPNConnectionErrorDomainPlugin error code 7
                            eskimo Apple Staff Apple Staff (11,325 points)

                            Thanks for the profile.  Here’s how those settings map to NEVPNManager properties:

                            NEVPNManager
                              localizedDescription: 'yyyy'
                              isEnabled: true
                              isOnDemandEnabled: false
                              onDemandRules.count: nil
                            NEVPNProtocol
                              serverAddress: 'vpn.example.com'
                              username: 'vpn77'
                              passwordReference: 'a123456'
                              identityReference: nil
                              identityData: nil
                              identityDataPassword: nil
                              disconnectOnSleep: false
                              proxySettings: nil
                            NEVPNProtocolIPSec
                              authenticationMethod: .none
                              useExtendedAuthentication: true
                              sharedSecretReference: nil
                              localIdentifier: 'vpn.example.com'
                              remoteIdentifier: 'vpn.example.com'
                            NEVPNProtocolIKEv2
                              deadPeerDetectionRate: .medium
                              serverCertificateIssuerCommonName: nil
                              serverCertificateCommonName: nil
                              certificateType: .RSA
                              useConfigurationAttributeInternalIPSubnet: false
                              IKESecurityAssociationParameters: AES256, SHA256, group14, 1440
                              childSecurityAssociationParameters: AES256, SHA256, group14, 1440
                              disableMOBIKE: false
                              disableRedirect: false
                              enablePFS: false
                              enableRevocationCheck: false
                              strictRevocationCheck: false

                            Note Many of these are default values, so you can simplify things by checking the initial value of a property before you add extra code to explicit set it.

                            One possible gotcha here is the credential, in this case your password.  This requires that you pass in a persistent reference to a keychain item, and lots of folks run into problems doing that.  For a simple example of how to do it right, check out the code in this post.

                            Share and Enjoy

                            Quinn “The Eskimo!”
                            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                            let myEmail = "eskimo" + "1" + "@apple.com"

                              • Re: NEVPNConnectionErrorDomainPlugin error code 7
                                sticl Level 1 Level 1 (0 points)

                                hi

                                thanks so much, could u remove the server and username password from your reply. thats was my bad

                                 

                                 

                                 

                                I modified these code, but the unknow error still occured

                                 

                                 

                                 

                                import Foundation

                                import NetworkExtension//import SGVPN

                                import Security

                                import KeychainAccess

                                //import vpnStatusChange

                                 

                                public class SGVPNManager: NSObject {

                                 

                                    static let shared = SGVPNManager()

                                    private var vpnManager = NEVPNManager.shared()

                                    weak var delegate: SGVPNManagerDelegate?

                                 

                                    override init() {

                                        super.init()

                                   

                                        NotificationCenter.default.addObserver(self, selector: #selector(vpnConfigurationDidChanged(notification:)), name: .NEVPNConfigurationChange, object: nil)

                                        NotificationCenter.default.addObserver(self, selector: #selector(vpnStatusDidChanged(notification:)), name: .NEVPNStatusDidChange, object: nil)

                                    }

                                 

                                    @objc

                                    public func vpnConfigurationDidChanged(notification: Notification) {

                                        self.connect()

                                    }

                                 

                                    @objc

                                    func vpnStatusDidChanged(notification: Notification) {

                                        let status = SGVPNStatus(rawValue: vpnManager.connection.status.rawValue)!

                                        delegate?.vpnConnectionStatusDidChanged(manager: self, status: status)

                                    }

                                 

                                    fileprivate func connect() {

                                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(1 * NSEC_PER_SEC)) / Double(NSEC_PER_SEC)) {

                                            self.vpnManager.loadFromPreferences { (error) in

                                                self.vpnManager.loadFromPreferences { (error) in

                                                    if error != nil {

                                                        print(error?.localizedDescription)

                                                        self.delegate?.vpnConnectionStatusDidChanged(manager: self, status: .invalid)

                                                        return

                                                    }

                                                 

                                                    do{

                                                        try self.vpnManager.connection.startVPNTunnel()

                                                    }catch let error{

                                                        print("vpn failed" + error.localizedDescription)

                                                        self.delegate?.vpnConnectionStatusDidChanged(manager: self, status: .disconnected)

                                                    }

                                                }

                                            }

                                        }

                                    }

                                 

                                    var isConnected: Bool {

                                        get {

                                            return vpnManager.connection.status == .connected

                                        }

                                    }

                                    var isConnecting: Bool {

                                        get {

                                            return vpnManager.connection.status == .connecting

                                        }

                                    }

                                    var isDisconnected: Bool {

                                        get {

                                            return vpnManager.connection.status == .disconnected

                                        }

                                    }

                                    var isDisconnecting: Bool {

                                        get {

                                            return vpnManager.connection.status == .disconnecting

                                        }

                                    }

                                 

                                    func preLoadPreferences() {

                                        vpnManager.loadFromPreferences { (error) in

                                            if let error = error {

                                                print(error.localizedDescription)

                                                return

                                            }

                                        }

                                    }

                                 

                                 

                                    /// Save a password in the keychain.

                                    func savePassword(_ password: String, inKeychainItem: Data?) -> Data? {

                                        guard let passwordData = password.data(using: String.Encoding.utf8, allowLossyConversion: false) else { return nil }

                                        var status = errSecSuccess

                                     

                                        if let persistentReference = inKeychainItem {

                                            // A persistent reference was given, update the corresponding keychain item.

                                            let query: [NSObject: AnyObject] = [

                                                kSecValuePersistentRef : persistentReference as AnyObject,

                                                kSecReturnAttributes : kCFBooleanTrue

                                            ]

                                            var result: AnyObject?

                                         

                                            // Get the current attributes for the item.

                                            status = SecItemCopyMatching(query as CFDictionary, &result)

                                         

                                            if let attributes = result as? [NSObject: AnyObject] , status == errSecSuccess {

                                                // Update the attributes with the new data.

                                                var updateQuery = [NSObject: AnyObject]()

                                                updateQuery[kSecClass] = kSecClassGenericPassword

                                                updateQuery[kSecAttrService] = attributes[kSecAttrService]

                                             

                                                var newAttributes = attributes

                                                newAttributes[kSecValueData] = passwordData as AnyObject?

                                             

                                                status = SecItemUpdate(updateQuery as CFDictionary, newAttributes as CFDictionary)

                                                if status == errSecSuccess {

                                                    return persistentReference

                                                }

                                            }

                                        }

                                     

                                        if inKeychainItem == nil || status != errSecSuccess {

                                            // No persistent reference was provided, or the update failed. Add a new keychain item.

                                         

                                            let attributes: [NSObject: AnyObject] = [

                                                kSecAttrService : UUID().uuidString as AnyObject,

                                                kSecValueData : passwordData as AnyObject,

                                                kSecAttrAccessible : kSecAttrAccessibleAlways,

                                                kSecClass : kSecClassGenericPassword,

                                                kSecReturnPersistentRef : kCFBooleanTrue

                                            ]

                                         

                                            var result: AnyObject?

                                            status = SecItemAdd(attributes as CFDictionary, &result)

                                         

                                            if let newPersistentReference = result as? Data , status == errSecSuccess {

                                                return newPersistentReference

                                            }

                                        }

                                        return nil

                                    }

                                 

                                    func connect(vpn_protocol:SGVPNProtocol, ip: String, username: String, password: String, psk: String) {

                                 

                                        self.vpnManager.loadFromPreferences { (error) in

                                         

                                            if error != nil {

                                                print("Load error: \(error?.localizedDescription as String?)")

                                                return

                                            } else {          

                                                let configuration = NEVPNProtocolIKEv2()

                                             

                                                configuration.serverAddress = ip

                                                configuration.remoteIdentifier = ip

                                                configuration.username = username

                                                do {

                                                    try configuration.passwordReference = VPNKeychain.persistentReferenceFor(service: "com.xcom.flashspeedup", account: "com.xcom.flashspeedup", password: password.data(using: .ascii)!) //self.savePassword("a123456", inKeychainItem: nil)

                                                }catch(let e){

                                                    print("persitant password error: \(e)")

                                                }

                                             

                                                configuration.authenticationMethod = .none

                                                configuration.useExtendedAuthentication = true

                                                configuration.sharedSecretReference = nil

                                                configuration.localIdentifier = ip

                                                configuration.remoteIdentifier = ip

                                             

                                                configuration.identityReference = nil

                                                configuration.identityData = nil

                                                configuration.identityDataPassword = nil

                                                configuration.disconnectOnSleep = false

                                                configuration.proxySettings = nil

                                                configuration.deadPeerDetectionRate = .medium

                                                configuration.serverCertificateIssuerCommonName = nil

                                                configuration.serverCertificateCommonName = nil

                                                configuration.certificateType = .RSA

                                                configuration.useConfigurationAttributeInternalIPSubnet = false

                                                //configuration.ikeSecurityAssociationParameters = AES256, SHA256, group14, 1440

                                                //configuration.childSecurityAssociationParameters = AES256, SHA256, group14, 1440

                                                configuration.disableMOBIKE = false

                                                configuration.disableRedirect = false

                                                configuration.enablePFS = false

                                                configuration.enableRevocationCheck = false

                                                configuration.strictRevocationCheck = false

                                             

                                                self.vpnManager.protocolConfiguration = configuration

                                                self.vpnManager.localizedDescription = "speedup"

                                                self.vpnManager.isEnabled = true

                                                self.vpnManager.isOnDemandEnabled = false

                                             

                                                self.vpnManager.connection.stopVPNTunnel()// = NEVPNConnection()

                                             

                                                self.vpnManager.saveToPreferences(completionHandler: { (error) in  // saveToPreferences

                                                    if error != nil {

                                                        print(error!.localizedDescription)

                                                        self.delegate?.vpnConnectionStatusDidChanged(manager: self, status: SGVPNStatus.invalid)

                                                        return

                                                    }

                                                })

                                            }

                                        }

                                    }

                                 

                                    func disconnect() {

                                     

                                        self.vpnManager.connection.stopVPNTunnel()

                                     

                                        self.remove()

                                    }

                                 

                                 

                                    func remove() {

                                        self.vpnManager.removeFromPreferences { (error) in

                                            if let error = error {

                                                print(error.localizedDescription)

                                                return

                                            }

                                 

                                            if UserDefaults.standard.bool(forKey: "FIST_CONNECT_VPN") {

                                                UserDefaults.standard.set(false, forKey: "FIST_CONNECT_VPN")

                                            }

                                        }

                                    }

                                }

                                 

                                 

                                I am not sure it this the correct way to use your keychain function,

                                 

                                let password = "123456"
                                do {
                                     try configuration.passwordReference = VPNKeychain.persistentReferenceFor(service: "password", account: "password", password: password.data(using: .utf8)!)
                                }catch(let e){
                                      print("persitant password error: \(e)")
                                }

                                 

                                 

                                The problem is on the configuration because I cant build connection for this configuration in the setting page after saveToPreference

                                  • Re: NEVPNConnectionErrorDomainPlugin error code 7
                                    eskimo Apple Staff Apple Staff (11,325 points)

                                    could u remove the server and username password from your reply.

                                    I have done so, replacing it with vpn.example.com.

                                    IMPORTANT Your Apr 22 post has the server name in it as well, so you’ll want to edit that.

                                    I modified these code, but the unknow error still occured

                                    OK, I’m out of ideas, or at least ideas that I can try here on DevForums.  My recommendation is that open a DTS tech support incident and we can discuss this in private.

                                    In your initial request, please:

                                    • Reference this DevForums thread

                                    • Emphasise that you have a configuration profile that works

                                    Then, when you get the auto ACK, reply to that with an email that has your configuration profile attached.  Make sure it’s a profile that I can install and test, not the redacted one that you posted here.

                                    Share and Enjoy

                                    Quinn “The Eskimo!”
                                    Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                                    let myEmail = "eskimo" + "1" + "@apple.com"

                                      • Re: NEVPNConnectionErrorDomainPlugin error code 7
                                        sticl Level 1 Level 1 (0 points)

                                        yeah   that was my bad

                                         

                                        how much we should pay for the DTS support? or its free?

                                         

                                        why we cant post image here ...... I have screenshot for the iphone log which said there is an internal error

                                          • Re: NEVPNConnectionErrorDomainPlugin error code 7
                                            eskimo Apple Staff Apple Staff (11,325 points)

                                            how much we should pay for the DTS support? or its free?

                                            You can find that information on the page I linked to in my previous post.

                                            why we cant post image here

                                            *sigh*  I wish I had a good answer for that.

                                            Having said that…

                                            I have screenshot for the iphone log which said there is an internal error

                                            posting screen shots of log messages is generally a bad idea because it means that folks reading your post have to type in the log message if, say, they want to quote your message, or search the headers for matching values, or whatever.  It’s much better to post log messages as text.

                                            Share and Enjoy

                                            Quinn “The Eskimo!”
                                            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                                            let myEmail = "eskimo" + "1" + "@apple.com"