11 Replies
      Latest reply: Nov 30, 2016 2:03 PM by eskimo RSS
      fripp85_reply Level 1 Level 1 (0 points)

        Hi,

        I’m facing some problems in connecting in HTTPS to a local host of my LAN after enabling ATS in my app

        The doc of ATS states that “App Transport Security (ATS) applies only to connections made to public host names. The system does not provide ATS protection to connections made to: Internet protocol (IP) addresses.”

        However, if I try to invoke my service on https://192.168.1.2, an SSL error is raised.

        I tried to add NSAllowsLocalNetworking to my .plist, but nothing has changed.

        What should I do in order to solve the problem?

        Thanks in advance

        • Re: ATS and local IP addresses
          eskimo Apple Staff Apple Staff (6,470 points)

          Last I checked NSAllowsLocalNetworking works just fine.  Be aware, however, that this only disables the additional security checking done by ATS.  NSURLSession still does standard (RFC 2818) server trust evaluation on your HTTPS connections.  If the server you’re talking to presents a certificate that’s not trusted by default (very likely given that it’s hard to get a CA to issue a certificate for a 192.168/16 address), you must override HTTPS server trust evaluation as described in Technote 2232 HTTPS Server Trust Evaluation.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: ATS and local IP addresses
              jeremyyyc Level 1 Level 1 (0 points)

              On this topic, I found the documentation misleading on this page:

              https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html

               

              under the topic:

              "Availability of ATS for Remote and Local Connections"

               

              My reading implied that I didn't need any sort of exceptions in the Info.plist to talk to IP Addresses. That's not correct, I still need to set NSAllowsLocalNetworking to YES. I just filed this radar for it.

               

              rdar://29187969

                • Re: ATS and local IP addresses
                  eskimo Apple Staff Apple Staff (6,470 points)

                  That's not correct, I still need to set NSAllowsLocalNetworking to YES. I just filed this radar for it (r. 29187969).

                  By an amazing coincidence I’ve been researching this as part of a DTS incident.  As far as I can tell, iOS 10 works as documented (which is different from iOS 9).  That is, ATS protection does not apply for resources loaded via IP address.  Here’s how I tested this:

                  1. In Xcode 8.1 I created a new project from the Single View Application template.

                  2. I modified the view controller’s viewDidLoad() method, as shown below.  I did not modify the Info.plist, meaning it has no NSAppTransportSecurity dictionary.

                  3. I ran that app on a device running iOS 10.1.1.

                  4. On launch it prints success, indicating that ATS did not block the load.

                  5. I then ran the same app on an iOS 9.3 device (I had to lower the deployment target to make this work, of course).  On launch it prints error, and I get a nice message in the consoling confirm that ATS blocked the request.

                  I’m not sure why you’re seeing different behaviour.  Perhaps you could post more details about how you tested this.

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"

                  override func viewDidLoad() {
                      super.viewDidLoad()
                      // Do any additional setup after loading the view, typically from a nib.
                      var request = URLRequest(url: URL(string: "http://88.97.8.212")!)
                      request.cachePolicy = .reloadIgnoringLocalCacheData
                      URLSession.shared.dataTask(with: request) { (data, response, error) in
                          if let _ = error {
                              NSLog("error")
                          } else {
                              NSLog("success")
                          }
                      }.resume()
                  }
                  
                • Re: ATS and local IP addresses
                  fripp85_reply Level 1 Level 1 (0 points)

                  Thanks eskimo for your reply.

                  Although I've enabled NSAllowsLocalNetworking, my NSURLSession fails with the following error codes

                  _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorCodeKey=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamPropertySSLClientCertificateState=0}

                  The delegate methods that manage the authentication challenges are never called.

                  What does this mean? That the network component I'm trying to reach is not compliant with ATS at all?

                  Thanks

                    • Re: ATS and local IP addresses
                      eskimo Apple Staff Apple Staff (6,470 points)

                      Error -9824 is errSSLPeerHandshakeFail, which is a fairly general error.  However, given that you don’t get the NSURLAuthenticationMethodServerTrust authentication challenge it seems likely that the TLS handshake failed really early, before the client was presented with the server’s certificate, which is what generates that challenge.

                      I suspect that this is not an ATS issue but a general TLS issue.  If,  for diagnostic purposes only, you disable ATS completely (by setting the ATS dictionary to contain just one key, NSAllowsArbitraryLoads), what do you see?

                      Share and Enjoy

                      Quinn “The Eskimo!”
                      Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                      let myEmail = "eskimo" + "1" + "@apple.com"

                        • Re: ATS and local IP addresses
                          mfischer1502 Level 1 Level 1 (0 points)

                          Hi Eskimo,

                          so I think I have the same issue like fripp85_reply. Because fripp85_reply  hasn’t answered your question yet and before I start a new thread, it maybe makes sense that I answer your question with my experience . I hope this ok!

                           

                          I made a small sample App on XCode 8.1 with Base SDK 10.1. We are using  NSURLSessions to do some local communication with some older hardware with self signed certifcates on it.

                          1. - (void)startRequest{
                          2.     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"<<HTTPS_WITH_LOCAL_IP_ADDRESS>>"]];
                          3.     NSURLSessionDataTask *dataTask = [_session dataTaskWithRequest:request
                          4.                                                  completionHandler:^(NSData *data,
                          5.                                                                      NSURLResponse *response,
                          6.                                                                      NSError *error) {
                          7.                                                      if (error) {
                          8.                                                          _NSLog(@"FAIL");
                          9.                                                      } else {
                          10.                                                          _NSLog(@"SUCCESS");
                          11.                                                      }
                          12.                                                  }];
                          13.     [dataTask resume];
                          14. }
                          15. - (void)URLSession:(NSURLSession *)session
                          16.               task:(NSURLSessionTask *)task
                          17. didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
                          18. completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,
                          19.                              NSURLCredential *credential))completionHandler{
                          20.   … here we are some certificate checking stuff…
                          21.      completionHandler(NSURLSessionAuthChallengeUseCredential,[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]);
                          22. }

                           

                          When we are setting the NSAllowsArbitaryLoads to YES then all is working fine.

                            <key>NSAppTransportSecurity</key>

                            <dict>

                            <key>NSAllowsArbitraryLoads</key>

                            <true/>

                            </dict>

                           

                          The app is checking the certifcates for the NSURLAuthenticationMethodServerTrust authentication challenge and accept the Challenge by using the completionhandler.

                           

                          When we now add the NSAllowsLocalNetworking with YES

                            <key>NSAppTransportSecurity</key>

                            <dict>

                            <key>NSAllowsArbitraryLoads</key>

                            <true/>

                            <key>NSAllowsLocalNetworking</key>

                            <true/>

                            </dict>

                           

                          We are getting the followoing error :

                           

                           

                          NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)

                           

                          The problem is that the URLSession:task:didReceiveChallenge:completionHandler: will never get called when NSAllowsLocalNetworking is activated so we won’t have the chance to do accept it. Hope you have an idea how to solve this issue, and thank you in advance.

                           

                           

                          To give you maybe some more information here is the result from the ATS Diagnostic on the local URL:

                           

                          /usr/bin/nscurl --ats-diagnostics --verbose

                          Starting ATS Diagnostics

                           

                          Configuring ATS Info.plist keys and displaying the result of HTTPS loads to

                          A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error.

                          ================================================================================

                           

                          Default ATS Secure Connection

                          ---

                          ATS Default Connection

                          ATS Dictionary:

                          {

                          }

                          2016-11-28 14:12:17.328 nscurl[9140:297067] CFNetwork SSLHandshake failed (-9824)

                          2016-11-28 14:12:17.328 nscurl[9140:297067] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)

                          Result : FAIL

                          Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7ffc587246a0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=, NSErrorFailingURLStringKey= _kCFStreamErrorDomainKey=3}

                            • Re: ATS and local IP addresses
                              eskimo Apple Staff Apple Staff (6,470 points)

                              The problem is that the URLSession:task:didReceiveChallenge:completionHandler: will never get called …

                              OK, so I tried you test here in my office and, with the server I’m testing against, I always get the NSURLAuthenticationMethodServerTrust challenge in this case.  It’s clearly something specific about your server that’s triggering this ATS problem.

                              Try repeating your test on the latest 10.2 beta; we’ve made some fixes in this space in the 10.2 release.

                              Let me know how you get along because I have further suggestions if this doesn’t help.

                              ps You should be using  URLSession:didReceiveChallenge:completionHandler: for NSURLAuthenticationMethodServerTrust authentication challenges, because such challenges are related to the session’s connections and not to a specific task.  This isn’t required (if you don’t implement the session delegate callback, NSURLSession will route the challenge to the task-specific delegate callback, quoting the first task that used that connection) but it’s best practice to use the right delegate callback for the right challenge.  Moreover, in the reverse case (for task-specific challenges like NSURLAuthenticationMethodHTTPBasic) you have to use the task-specific delegate callback otherwise things work work.

                              Share and Enjoy

                              Quinn “The Eskimo!”
                              Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                              let myEmail = "eskimo" + "1" + "@apple.com"

                                • Re: ATS and local IP addresses
                                  mfischer1502 Level 1 Level 1 (0 points)

                                  Thanks for the advise. So I pressed very hard my thumbs and tried it with the XCode 8.2 beta 4 with 10.2 as BaseSDK but I have the same issue on the Simulator and on the real device.

                                   

                                  Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x170058690 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made. _kCFStreamErrorDomainKey=3}

                                    • Re: ATS and local IP addresses
                                      eskimo Apple Staff Apple Staff (6,470 points)

                                      [I] tried it with the XCode 8.2 beta 4 with 10.2 as BaseSDK but I have the same issue on the Simulator and on the real device.

                                      OK.  I think I know what’s going on here.  It seems that NSAllowsLocalNetworking does not disable all parts of ATS for local requests.  It removes ATS’s ‘server certificate must be issued by a trusted root’ requirement but it does not remove other ATS requirements.  For example, when I try to connect to a local server I see an outgoing Client Hello message listing these cypher suites.

                                      TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
                                      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
                                      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
                                      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
                                      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
                                      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
                                      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
                                      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
                                      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
                                      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
                                      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
                                      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
                                      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
                                      

                                      Note that they all use ECDHE, that is, they all require forward secrecy.  In contrast, if I remove NSAllowsLocalNetworking and set NSAllowsArbitraryLoads, I see this:

                                      … all of the above …
                                      TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
                                      TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
                                      TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
                                      TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
                                      TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
                                      TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
                                      

                                      That is, the client offers cypher suites that don’t require forward secrecy.

                                      If you have a server that does not support any forward secrecy cypher suites (which is pretty common for older servers) and the Client Hello only contains forward secrecy cypher suites, the TLS handshake will fail.

                                      I’ve filed a bug about this (r. 29418298).

                                      I believe that you’ll see a similar problem if the server doesn’t support TLS 1.2.  That is, the client will refuse to negotiate a lower TLS version because ATS is still partially enabled (r. 28586371).

                                      I recommend that you use a packet trace to look at the TLS handshake in the NSAllowsLocalNetworking and NSAllowsArbitraryLoads cases to confirm that the problem you’re seeing matches the symptoms I’ve described above.  If it does, your only option is to stick with NSAllowsArbitraryLoads.

                                      I don’t have any info as to when these problems will be fixed.

                                      Share and Enjoy

                                      Quinn “The Eskimo!”
                                      Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                                      let myEmail = "eskimo" + "1" + "@apple.com"

                                        • Re: ATS and local IP addresses
                                          mfischer1502 Level 1 Level 1 (0 points)

                                          I checked the TLS handshake and your assumption seems to be right. I see in the handshake that TLS 1.0 with a cipher suite TLS_RSA_WITH_AES_256_CBC_SHA is used.

                                           

                                          So we are planning to release a new version of our app in the beginning of the next year. We need to get in touch with appstore review team and ask if we are allowed to submit the app with NSAllowsArbitaryLoads instead of NSAllowsLocalNetworking  until the bug you reported is fixed. Is this the right approach to get sure that we can update the app next year ?

                                           

                                          Thanks for the great support!

                                            • Re: ATS and local IP addresses
                                              eskimo Apple Staff Apple Staff (6,470 points)

                                              I checked the TLS handshake and your assumption seems to be right.

                                              OK.

                                              Is this the right approach to get sure that we can update the app next year?

                                              Sorry, but I can’t really advise you on App Review issues.

                                              Share and Enjoy

                                              Quinn “The Eskimo!”
                                              Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                                              let myEmail = "eskimo" + "1" + "@apple.com"