2

First of all, I know there are a ton of similar questions, but none that I've seen seems to address my setup (nor any solution I found works). So bear with me...

  • My server host name is an IP address, not a domain name (i.e., URL looks like: https://XXX.YYY.ZZZ.WWW:9443/etc...).
  • My server has a real certificate (i.e., not self signed).
  • My app's plist entry NSAppTransportSecurity dictionary is empty (no exceptions whatsoever - factory settings ATS).
  • This is production code and I can not disable ATS (nor do I think I could, given that exceptions only work with explicit domain names, not IP addresses).

(Testing on iOS 9, deployment target is iOS 8.x)

I am getting this error when I try to connect:

CFNetwork SSLHandshake failed (-9806) NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806) Error: An SSL error has occurred and a secure connection to the server cannot be made.

(Device and Simulator)

I tried to command line tool nscurl described here. I get:

  • Default ATS Secure Connection: CFNetwork SSLHandshake failed (-9806)
  • Allowing Arbitrary Loads: NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813) ("The certificate for this server is invalid. You might be connecting to a server that is pretending to be “XXX.YYY.ZZZ.WWW” which could put your confidential information at risk.")
  • Configuring TLS exceptions for XXX.YYY.ZZZ.WWW: (TLS 1.2, 1.1 and 1.0) CFNetwork SSLHandshake failed (-9806)

  • Disabling Perfect Forward Secrecy: CFNetwork SSLHandshake failed (-9801)

  • Disabling Perfect Forward Secrecy and Allowing Insecure HTTP: CFNetwork SSLHandshake failed (-9801)

  • TLSv1.2 with PFS disabled: CFNetwork SSLHandshake failed (-9801)

  • TLSv1.1 with PFS disabled: CFNetwork SSLHandshake failed (-9801)

  • TLSv1.0 with PFS disabled: NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

  • TLSv1.2 with PFS disabled and insecure HTTP allowed: CFNetwork SSLHandshake failed (-9801)

...you get the drill.

I am having checked which TLS version the server supports (that is the biggest suspect, as far as I've researched), but perhaps there is something else I need to fix/check on the client side?

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
  • have you tried handling authentication challenges in connection delegates ? – vishnuvarthan Jun 16 '16 at 07:47
  • I have implemented all delegate methods of `NSURLSession`. I set breakpoints in `URLSession:task:didReceiveChallenge:completionHandler:` and `URLSession:didReceiveChallenge:completionHandler:`, but they aren't hit. – Nicolas Miari Jun 16 '16 at 07:53
  • I'm suspecting the server's TLS version might be too low, but I can't tell yet. Perhaps I'm missing something else... – Nicolas Miari Jun 16 '16 at 07:54
  • have you tried [this](http://stackoverflow.com/a/30720929/653513)? – Rok Jarc Jun 16 '16 at 07:57
  • @rokjarc have you read my question? I can not disable ATS. I need to solve this for production code, and transmit confidential customer data; there is no temporary workaround. Also, my server does not have a domain name (only an IP address), and ATS only allows for domain exceptions. – Nicolas Miari Jun 16 '16 at 08:00
  • Can you post your code where you send request – vishnuvarthan Jun 16 '16 at 12:38
  • No that is not true. You can disable ATS fully for all sites, by that way your IP will also work if you prefer that option. – vishnuvarthan Jun 16 '16 at 12:40
  • I was refering to set a SINGLE exception for my IP address. I will NOT disable ATS for good. – Nicolas Miari Jun 16 '16 at 12:53
  • BTW, you can add exceptions by IP address using a xip.io - basically you put the IP.xp.io and it should work (e.g. 10.0.0.1.xp.io will allow you to connect to 10.0.0.1) – wottle Jul 09 '16 at 02:01
  • Also, can you confirm it is an ATS issue by disabling all ATS just to confirm. If it is ATS, you can try disabling the TLS 1.2 requirement, forward secrecy, or both. I suppose there is no way you can provide the IP address so we can look at the server cert? – wottle Jul 09 '16 at 02:07

1 Answers1

2

I think you need to inspect the cert on your server. You should be able to use the openssl client to investigate your certificate and get your server's ssl config:

openssl s_client  -connect XXX.YYY.ZZZ.WWW:9443 

You should get some details about the cert

SSL-Session: Protocol : TLSv1 Cipher : AES256-SHA Session-ID: // Session-ID-ctx: Master-Key: // Key-Arg : None Start Time: 1449693038 Timeout : 300 (sec) Verify return code: 0 (ok)

Or, you can use a website like symantec to query the cert and see if you have met the requirements of TLS1.2, a strong enough key, and forward secrecy.

Also, you could try turning on CFNetwork Diagnostic Logging. Edit the Xcode scheme and add the CFNETWORK_DIAGNOSTICS environment variable. Set the logging level to 3 which is the most verbose:

The Xcode console shows the location of the log file:

CFNetwork diagnostics log file created at: /private/var/mobile/Containers/
Data/Application/A3421F00-451A-CD70-1B82-B163D1A3BB0F/Library/Logs/
CrashReporter/CFNetwork_com.sample.app_118.nwlrb.log

You could look into those logs to see if there is any more information as to why the network calls are failing.

wottle
  • 13,095
  • 4
  • 27
  • 68