We are trying to load/install an IPSEC VPN through our app, and have not yet been successful. According to Eskimo (see https://forums.developer.apple.com/thread/70696), the preferred mechanism would be NEVPNManager, with other options being hosting on an external web server, or as a last resort a web server in the app.
We have a mobileconfig file from our VPN server that works if loaded manually, but have been unsuccessful using it with other mechanisms.
Web Server:
We do not have an external web server that would be a good place to host the mobileconfig files right now. However, we do have access to a cloud server data storage from which we can pull the mobileconfig file. We do use GCDWebServer in the app and spent some time trying to get that to work (ingesting and saving a mobileconfig, and then opening the URL), but we were unsuccessful in the short time that we tried. In reality, we’d rather not use that mechanism anyway because we don’t want to end up in a browser window outside of the app.
NEVPNManager and Personal VPN
We have ingested and parsed the mobileconfig file (from cloud server), setting values in NEVPNManager and NEVPNProtocolIKEv2 protocol object. But when we try to start the VPN, it is unsuccessful. Looking at console messages, it looks like the issue is related to the root CA. Some of the relevant console messages we are seeing are as follows:
remoteCertAuthorityArray missing from config
Certificate authentication data could not be verified
Failed to process IKE Auth packet (connect)
Originally the VPN server was using a mobileconfig with a self-signed root cert, but then after reading Eskimo’s responses (in https://forums.developer.apple.com/thread/84679 and https://forums.developer.apple.com/thread/114575 and https://forums.developer.apple.com/thread/108004 and https://forums.developer.apple.com/thread/76227), we were able use Let’s Encrypt to issue the certificate used in the mobileconfig. And yet we still are getting the exact same result, and same messages in Console.
A few additional details:
I read in the mobileconfig file as a dictionary and pulled the cert information from PayloadContent in its section in the mobileconfig. The mobileconfig has Base64 encoded pkcs12 certificate with a password (PayloadDescription for that section says "Adds a PKCS#12-formatted certificate”). The PayloadContent is a “data” type tag, so when I get it’s value it looks like it correctly reads it into the NSData object, and so I set the following on the NEVPNProtocolIKEv2 protocol object. Does this look correct?
protocol.identityDataPassword = [certDictionary valueForKey:@"Password"];
protocol.identityData = [certDictionary valueForKey:@"PayloadContent"];
There is also a 2nd cert section, with PayloadDescription of "Adds a CA root certificate”. There doesn’t seem to be a place for this in NEVPNManager, but I thought maybe with a valid cert, it would get that information from the VPN server?
if I run something like this against the mobileconfig file:
openssl pkcs7 -inform DER -print_certs -in test.mobileconfig > test.pem
openssl x509 -in test.pem -noout -text
It shows (along with all the other info):
Issuer: O=Digital Signature Trust Co., CN=DST Root CA X3
Subject: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
And yet the numerous other things I’ve tried, end up showing: Issuer: CN=***.***.***.*** (VPN server IP, which is also set as serverCertificateIssuerCommonName in the mobileconfig)
In spite of spending quite a bit of time looking at this, I’m wondering if I’m just still ignorant about how certs work.
Has anyone tried to parse the cert data out of a mobileconfig file to set up a VPN connection via NEVPNManager?