NEVPNManager can't establish IPv6 connection on iPhoneX

Hello,

In the code I have utilised the NEVPNManager to establish an IKEv2 connection to my StrongSwan server. I have disabled IPv4 on the server to focus only on the IPv6 issues.

When I run the app under MacOS, it works perfectly fine. When I run the app under iPad (iOS) it also works perfectly fine. Both obtain an IPv6 from the server.

But when I run the app under my iPhone X, the IPv6 connection can't be established. I have updated the OS to iOS 15.1, but it didn't help. I have restarted the phone several times and made sure the DNS settings in Wifi connection is set to automatic.

When I do a sudo tcpdump icmp6 on the server I get this for iPad:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes

08:46:45.036393 IP6 fe80::9400:ff:fef1:6bcb > fe80::1: ICMP6, neighbor solicitation, who has fe80::1, length 32

08:46:45.037036 IP6 fe80::1 > fe80::9400:ff:fef1:6bcb: ICMP6, neighbor advertisement, tgt is fe80::1, length 24

But when I run it under my iPhone X I get errors on tcpdump:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes

08:49:36.594341 IP6 2a01:4f8:c17:1f2d::1 > one.one.one.one: ICMP6, destination unreachable, unreachable port, 2a01:4f8:c17:1f2d::1 udp port 61921, length 121

08:49:36.594693 IP6 2a01:4f8:c17:1f2d::1 > one.one.one.one: ICMP6, destination unreachable, unreachable port, 2a01:4f8:c17:1f2d::1 udp port 49461, length 155

08:49:36.605300 IP6 2a01:4f8:c17:1f2d::1 > one.one.one.one: ICMP6, destination unreachable, unreachable port, 2a01:4f8:c17:1f2d::1 udp port 63572, length 152
...

Does the iPhone has some sort of firewall enabled?

Below is my code. Why is the iPhone X affected, but not the iPad?

func connectIKEv2VPN() {
   self.vpnManager.loadFromPreferences(completionHandler: vpnLoadHandler)
}

func vpnLoadHandler(error: (Error?)) -> Void {
        let tkcs = MyKeychainService()
        let deviceService = DeviceService.shared
        var protcol: NEVPNProtocol
        let ikev2 = NEVPNProtocolIKEv2()
        ikev2.useExtendedAuthentication = true
        ikev2.localIdentifier = "My VPN"
        ikev2.remoteIdentifier = EnvFabric.shared.getUrlForCode(DeviceService.shared.getRetrievedServerCode())
        ikev2.authenticationMethod = NEVPNIKEAuthenticationMethod.none
        ikev2.deadPeerDetectionRate = NEVPNIKEv2DeadPeerDetectionRate.medium
        ikev2.ikeSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256GCM
        ikev2.ikeSecurityAssociationParameters.integrityAlgorithm = .SHA256
        ikev2.ikeSecurityAssociationParameters.diffieHellmanGroup = .group19
        ikev2.ikeSecurityAssociationParameters.lifetimeMinutes = 1440
        ikev2.childSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256GCM
        ikev2.childSecurityAssociationParameters.integrityAlgorithm = .SHA256
        ikev2.childSecurityAssociationParameters.diffieHellmanGroup = .group19
        ikev2.childSecurityAssociationParameters.lifetimeMinutes = 1440
        ikev2.disableMOBIKE = false
        protcol = ikev2
        protcol.disconnectOnSleep = false
        protcol.serverAddress = EnvFabric.shared.getUrlForCode(DeviceService.shared.getRetrievedServerCode())
        self.vpnManager.localizedDescription = DeviceService.shared.getRetrievedServerName()
        protcol.username = deviceService.getDeviceId()
        tkcs.save(key: "DEVICE_TOKEN", value: deviceService.getDeviceToken())
        protcol.passwordReference = tkcs.load(key: "DEVICE_TOKEN")
        self.vpnManager.protocolConfiguration = protcol
        self.vpnManager.onDemandRules = nil
        self.vpnManager.isOnDemandEnabled = false
        self.vpnManager.isEnabled = true   
        self.vpnManager.saveToPreferences(completionHandler: vpnSaveHandler)
}

func vpnSaveHandler(error: (Error?)) -> Void {
        if let error = error {
            if ((error as NSError).code == 4) {
                return
            }
        } else {
            do {
                    try self.vpnManager.connection.startVPNTunnel()
                }
            } catch let error {
                SwiftyBeaver.warning("Error starting VPN Connection", error.localizedDescription)
            }
        }
    }

Replies

In the code I have utilised the NEVPNManager to establish an IKEv2 connection to my StrongSwan server.

Try this:

  1. Delete your app from all your devices.

  2. Use Apple Configurator to create a configuration profile for your VPN server.

  3. Install it on a device that should work. Tweak the configuration profile until it does actually work.

  4. Now install this working configuration profile on the device that previously failed. Does it work?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"