IKEv2 certificate authentication on iOS

Recently I've been trying to set up IKEv2 EAP-TLS authentication with StrongSwan. I've managed to set everything up so that my Android client connects successfully, but ran into some trouble with iOS. The internal client just doesn't like something about my server configuration or it's certificate and sends TLS close notify message in the middle of IKE_AUTH exchange and shows User authentication error to the user. At the same time, EAP-MSCHAPv2 method with the same server certificate is ok for some reason.

The server certificate has it's server_Auth and IKEIntermediate flags, as iOS requires, keys are 4096 bit. I've been searching for a while now and I'm out of ideas. Please help me out.

iOS 15.6.1 Release.

Connection log:

Aug 28 20:08:20 debian ipsec[1334]: 02[IKE] initiating EAP_TLS method (id 0x84)
Aug 28 20:08:20 debian ipsec[1334]: 02[IKE] received ESP_TFC_PADDING_NOT_SUPPORTED, not using ESPv3 TFC padding
Aug 28 20:08:20 debian ipsec[1334]: 02[IKE] peer supports MOBIKE
Aug 28 20:08:20 debian ipsec[1334]: 02[IKE] authentication of '192.168.50.60' (myself) with RSA signature successful
Aug 28 20:08:20 debian ipsec[1334]: 02[IKE] sending end entity cert "CN=192.168.50.60"
Aug 28 20:08:20 debian ipsec[1334]: 02[ENC] generating IKE_AUTH response 1 [ IDr CERT AUTH EAP/REQ/TLS ]
Aug 28 20:08:20 debian ipsec[1334]: 02[ENC] splitting IKE message (1916 bytes) into 2 fragments
Aug 28 20:08:20 debian ipsec[1334]: 02[ENC] generating IKE_AUTH response 1 [ EF(1/2) ]
Aug 28 20:08:20 debian ipsec[1334]: 02[ENC] generating IKE_AUTH response 1 [ EF(2/2) ]
Aug 28 20:08:20 debian ipsec[1334]: 02[NET] sending packet: from 192.168.50.60[4500] to 192.168.50.50[4500] (1248 bytes)
Aug 28 20:08:20 debian ipsec[1334]: 02[NET] sending packet: from 192.168.50.60[4500] to 192.168.50.50[4500] (736 bytes)
Aug 28 20:08:20 debian ipsec[1334]: 06[NET] received packet: from 192.168.50.50[4500] to 192.168.50.60[4500] (236 bytes)
Aug 28 20:08:20 debian ipsec[1334]: 06[ENC] parsed IKE_AUTH request 2 [ EAP/RES/TLS ]
Aug 28 20:08:20 debian ipsec[1334]: 06[TLS] negotiated TLS 1.2 using suite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
Aug 28 20:08:20 debian ipsec[1334]: 06[TLS] sending TLS server certificate 'CN=192.168.50.60'
Aug 28 20:08:20 debian ipsec[1334]: 06[TLS] sending TLS cert request for 'CN=test Root CA'
Aug 28 20:08:20 debian ipsec[1334]: 06[ENC] generating IKE_AUTH response 2 [ EAP/REQ/TLS ]
Aug 28 20:08:20 debian ipsec[1334]: 06[NET] sending packet: from 192.168.50.60[4500] to 192.168.50.50[4500] (1100 bytes)
Aug 28 20:08:20 debian ipsec[1334]: 05[NET] received packet: from 192.168.50.50[4500] to 192.168.50.60[4500] (76 bytes)
Aug 28 20:08:20 debian ipsec[1334]: 05[ENC] parsed IKE_AUTH request 3 [ EAP/RES/TLS ]
Aug 28 20:08:20 debian charon: 05[NET] sending packet: from 192.168.50.60[4500] to 192.168.50.50[4500] (1100 bytes)
Aug 28 20:08:20 debian ipsec[1334]: 05[ENC] generating IKE_AUTH response 3 [ EAP/REQ/TLS ]
Aug 28 20:08:20 debian charon: 07[NET] received packet: from 192.168.50.50[4500] to 192.168.50.60[4500] (92 bytes)
Aug 28 20:08:20 debian charon: 07[ENC] parsed IKE_AUTH request 4 [ EAP/RES/TLS ]
Aug 28 20:08:20 debian charon: 07[TLS] received TLS close notify
Aug 28 20:08:20 debian charon: 07[TLS] sending TLS close notify
Aug 28 20:08:20 debian charon: 07[ENC] generating IKE_AUTH response 4 [ EAP/REQ/TLS ]
Aug 28 20:08:20 debian charon: 07[NET] sending packet: from 192.168.50.60[4500] to 192.168.50.50[4500] (92 bytes)
Aug 28 20:08:50 debian charon: 13[JOB] deleting half open IKE_SA with 192.168.50.50 after timeout
Aug 28 20:08:50 debian charon: 14[JOB] deleting half open IKE_SA with 192.168.50.50 after timeout

ipsec.conf:

config setup
    charondebug="ike 1, knl 1, cfg 0"
    uniqueids=no

conn ikev2-vpn
    auto=add
    compress=no
    type=tunnel
    keyexchange=ikev2
    fragmentation=yes
    forceencaps=yes
    dpdaction=clear
    dpddelay=300s
    rekey=no
    left=%any
    leftid=192.168.50.60
    leftcert=server-cert.pem
    leftsendcert=always
    leftsubnet=0.0.0.0/0
    right=%any
    rightid=%any
    rightauth=eap-tls
    rightsendcert=always
    rightsourceip=10.10.10.0/24
    rightdns=8.8.8.8,8.8.4.4
    ike=chacha20poly1305-sha512-curve25519-prfsha512,aes256gcm16-sha384-prfsha384-ecp384,aes256-sha1-modp1024,aes256-sha256-modp2048,3des-sha1-modp1024!
    esp=chacha20poly1305-sha512,aes256gcm16-ecp384,aes256-sha256,aes256-sha1,3des-sha1!

Server certificate:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 5326615466311432545 (0x49ebf08b84983961)
        Signature Algorithm: sha384WithRSAEncryption
        Issuer: CN = test Root CA
        Validity
            Not Before: Aug 25 20:20:04 2022 GMT
            Not After : Aug 24 20:20:04 2027 GMT
        Subject: CN = 192.168.50.60
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (4096 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier:
                keyid:30:CA:E4:2A:DF:42:9D:77:E0:57:FB:8F:DE:EE:12:FA:02:EF:4B:3C

            X509v3 Subject Alternative Name:
                DNS:192.168.50.60, IP Address:192.168.50.60
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, 1.3.6.1.5.5.8.2.2
    Signature Algorithm: sha384WithRSAEncryption
         ...
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
Answered by varzonix in 727527022

Found a workaround

Most people wouldn't even encounter this issue as everyone nowadays can buy a cheap domain name and use it in Common Name and SubjectAlternativeName of the server certificate. iOS client requires the DNS name of the TLS server to be in SANs. Remote ID setting of my client was set to server's IP address (192.168.50.60). iOS sent it as IP of course, server decided it was perfectly okay as it's leftid was set to 192.168.50.60 and proceeded with the authentication. At this moment iOS client checked whether DNS name of the server was amongst the SANs of the server certificate. And it was not. The server didn't even have a DNS name, it had a workaround with an IP address being interpreted as DNS name. I think it tried to match Remote ID to DNS SAN DNS:192.168.50.60 and got confused. I'm not sure why it doesn't do that when not using certificate client authentication.

I added a fake DNS name testvpn.xyz to the server cert's SANs, set it as leftid in ipsec.conf and set it as Remote ID of the client. And it worked, iOS client establishes connection. It would be much easier to buy a domain name from the beginning. Oh well.

Server certificate:

...
 X509v3 Subject Alternative Name:
                IP Address:192.168.50.60, DNS:192.168.50.60, DNS:testvpn.xyz
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, 1.3.6.1.5.5.8.2.2
...

ipsec.conf:

conn ikev2-vpn
    ...
    left=%any
    leftid=testvpn.xyz
    leftcert=server-cert.pem
    leftsendcert=always
    ...

Are you seeing anything in the client side iOS logs that indicates a failure code or message as to what is going on?

Accepted Answer

Found a workaround

Most people wouldn't even encounter this issue as everyone nowadays can buy a cheap domain name and use it in Common Name and SubjectAlternativeName of the server certificate. iOS client requires the DNS name of the TLS server to be in SANs. Remote ID setting of my client was set to server's IP address (192.168.50.60). iOS sent it as IP of course, server decided it was perfectly okay as it's leftid was set to 192.168.50.60 and proceeded with the authentication. At this moment iOS client checked whether DNS name of the server was amongst the SANs of the server certificate. And it was not. The server didn't even have a DNS name, it had a workaround with an IP address being interpreted as DNS name. I think it tried to match Remote ID to DNS SAN DNS:192.168.50.60 and got confused. I'm not sure why it doesn't do that when not using certificate client authentication.

I added a fake DNS name testvpn.xyz to the server cert's SANs, set it as leftid in ipsec.conf and set it as Remote ID of the client. And it worked, iOS client establishes connection. It would be much easier to buy a domain name from the beginning. Oh well.

Server certificate:

...
 X509v3 Subject Alternative Name:
                IP Address:192.168.50.60, DNS:192.168.50.60, DNS:testvpn.xyz
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, 1.3.6.1.5.5.8.2.2
...

ipsec.conf:

conn ikev2-vpn
    ...
    left=%any
    leftid=testvpn.xyz
    leftcert=server-cert.pem
    leftsendcert=always
    ...
IKEv2 certificate authentication on iOS
 
 
Q