ATS fails when going through F5's

I have an enterprise app that I am working on that hits a web API.


I am getting a 9802 error when trying to hit the API.


I am able to hit the API properly when it is just my App and the Server... However, we have an F5 that load-balances our servers - and when we try to go through the F5, I get the 9802 errors.


I've tried the TLSTool, and everything passes just fine with or without the F5.


I have also used NSCurl with the "ats-diagnostics" flag on, and from my iMac, it works perfectly... Here is the output:


Starting ATS Diagnostics
Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https:/
A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error.
================================================================================
Default ATS Secure Connection
---
ATS Default Connection
ATS Dictionary:
{
}
Result : PASS
---
================================================================================
Allowing Arbitrary Loads
---
Allow All Loads
ATS Dictionary:
{
    NSAllowsArbitraryLoads = true;
}
Result : PASS
---
================================================================================
Configuring TLS exceptions for apps-test.cticore.com
---
TLSv1.2
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.2";
        };
    };
}
Result : PASS
---
---
TLSv1.1
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.1";
        };
    };
}
Result : PASS
---
---
TLSv1.0
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.0";
        };
    };
}
Result : PASS
---
================================================================================
Configuring PFS exceptions for apps-test.cticore.com
---
Disabling Perfect Forward Secrecy
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---
================================================================================
Configuring PFS exceptions and allowing insecure HTTP for apps-test.cticore.com
---
Disabling Perfect Forward Secrecy and Allowing Insecure HTTP
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---
================================================================================
Configuring TLS exceptions with PFS disabled for apps-test.cticore.com
---
TLSv1.2 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.2";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---
---
TLSv1.1 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.1";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---
---
TLSv1.0 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.0";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---
================================================================================
Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for apps-test.cticore.com
---
TLSv1.2 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.2";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---
---
TLSv1.1 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.1";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---
---
TLSv1.0 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "apps-test.cticore.com" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.0";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---
================================================================================


When I try via my App, in iOS, I get the following in my logs:


Can't seem to list this data, every time I try to Post to the forum, it tells me "This message contains invalid characters"


In an earlier post, Eskimo had mentioned using the TLSTool code in an iOS app for testing. I tried that but found that the OSX and iOS Security frameworks are different and the code from TLSTool will not work on iOS.


I have to get this working in my app, and everything on the server side seems to be configured properly, and I can even verify that it all works with the TLSTool AND nscurl.


What is different in iOS that is causing this to fail? I am totally out of ideas and frustrated, so any/all help will be GREATLY appreciated.


Thanks!


Perlguy

Accepted Reply

GOT IT FIXED!


The 9813 error gave my networking team a better clue about what was failing.


Apparently, with our GoDaddy certs, there was one other cert in the chain that was on our F5's, but not our IIS boxes - and this seems to have been the issue.


Why it worked when using NSCurl and the ats-diagnostics, I have no idea, but it appears to be fixed, and I am a VERY happy camper.


🙂


Thank you, Quinn, for throwing me a few bones!


Perlguy

Replies

Error -9802 is

errSSLFatalAlert
. There’s a good summary of TLS alert semantics in the Alert protocol section of the Wikipedia page.

Normally I’d expect this error to be caused by a TLS fatal alert coming back from the server. However, just to rule out ATS entanglements I recommend that you disable ATS for your app entirely. You can do this by setting your ATS dictionary to a single value,

NSAllowsArbitraryLoads
. If the problem still occurs in that configuration, it’s very likely that the fatal alert is ‘real’.

In that case your next option would be to packet trace the working and non-working cases to a) confirm that the fatal alert is real, and b) work out when it’s being generated.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for the reply...

Here is one thing I noticed...


With NSAllowsArbitraryLoads True, I get a 9813 error:


Feb 25 06:43:17  SLLTest_Swift[10641] <Notice>: CFNetwork Diagnostics [3:27] 06:43:17.824 {
  Response Error
  Request: <CFURLRequest 0x12dda11e0 [0x1a11f2b68]> {url = https://apps-test.cticore.com/api/2.7/auth?DeviceId=CB229D0B-71E4-43D9-BAAB-5B43E6FE846E&LoginType=native&Password=test&Username=test, cs = 0x0}
   Error: Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=1, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x12de8ad10>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, kCFStreamPropertySSLPeerCertificates=<CFArray 0x12dda8730 [0x1a11f2b68]>{type = immutable, count = 1, values = (
          0 : <cert(0x12dda6740) s: *.cticore.com i: Go Daddy Secure Certificate Authority - G2>
          )}}
  } [3:27]


Feb 25 06:43:17  SLLTest_Swift[10641] <Notice>: CFNetwork Diagnostics [3:28] 06:43:17.826 {
            Did Fail
              Loader: <CFMutableURLRequest 0x12de6e910 [0x1a11f2b68]> {url = https://apps-test.cticore.com/api/2.7/auth?DeviceId=CB229D0B-71E4-43D9-BAAB-5B43E6FE846E&LoginType=native&Password=test&Username=test, cs = 0x0}
               Error: Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=1, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x12de8ad10>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, kCFStreamPropertySSLPeerCertificates=<CFArray 0x12dda8730 [0x1a11f2b68]>{type = immutable, count = 1, values = (
                      0 : <cert(0x12dda6740) s: *.cticore.com i: Go Daddy Secure Certificate Authority - G2>
                      )}}
  init to origin load: 0.011467s
          total time: 8.73009s
         total bytes: 0
  } [3:28]




With NSAllowsArbitraryLoads False, I get a 9802 error:


Feb 25 06:44:19  SLLTest_Swift[10645] <Notice>: CFNetwork Diagnostics [3:27] 06:44:19.175 {
  Response Error
  Request: <CFURLRequest 0x13c6874c0 [0x1a11f2b68]> {url = https://apps-test.cticore.com/api/2.7/auth?DeviceId=CB229D0B-71E4-43D9-BAAB-5B43E6FE846E&LoginType=native&Password=test&Username=test, cs = 0x0}
   Error: Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=1, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x13c68f8d0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=<CFArray 0x13c690080 [0x1a11f2b68]>{type = immutable, count = 1, values = (
          0 : <cert(0x13c68e450) s: *.cticore.com i: Go Daddy Secure Certificate Authority - G2>
          )}}
  } [3:27]


Feb 25 06:44:19  SLLTest_Swift[10645] <Notice>: CFNetwork Diagnostics [3:28] 06:44:19.176 {
            Did Fail
              Loader: <CFMutableURLRequest 0x13c67fd60 [0x1a11f2b68]> {url = https://apps-test.cticore.com/api/2.7/auth?DeviceId=CB229D0B-71E4-43D9-BAAB-5B43E6FE846E&LoginType=native&Password=test&Username=test, cs = 0x0}
               Error: Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=1, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x13c68f8d0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=<CFArray 0x13c690080 [0x1a11f2b68]>{type = immutable, count = 1, values = (
                      0 : <cert(0x13c68e450) s: *.cticore.com i: Go Daddy Secure Certificate Authority - G2>
                      )}}
  init to origin load: 0.012155s
          total time: 0.350597s
         total bytes: 0
  } [3:28]



I am going through the wiki and trying to make sense of it all, but SSL is definitely not my strong point.


Any other bones you could throw my way would be great!


Also, any idea why this works just fine using TLSTool?


Thanks again,

Perlguy

GOT IT FIXED!


The 9813 error gave my networking team a better clue about what was failing.


Apparently, with our GoDaddy certs, there was one other cert in the chain that was on our F5's, but not our IIS boxes - and this seems to have been the issue.


Why it worked when using NSCurl and the ats-diagnostics, I have no idea, but it appears to be fixed, and I am a VERY happy camper.


🙂


Thank you, Quinn, for throwing me a few bones!


Perlguy

Also, any idea why this works just fine using TLSTool?

-9813 is

errSSLNoRootCert
, which is basically an HTTPS server trust evaluation failure. TLSTool does its trust evaluation using the OS X Security framework, which has different behaviours than iOS in various places. If you had managed to get the TLSTool core code running on iOS, it’s likely it would have pointed to the problem. But, as you noted, this isn’t trivial to do because of the sort of Security framework differences that caused the problem in the first place.

*sigh*

Anyway, I’m glad to here you have it sorted.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"