How to setup forward secrecy in nginx so that iOS9 (Xcode7) app with default ATS settings can connect to the server?

iOS9's App Transport Security states that connections that do not meet certain requirements will fail. Below are the requirements quoted from Apple's document (https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/index.html)


* The server must support at least Transport Layer Security (TLS) protocol version 1.2.

* Connection ciphers are limited to those that provide forward secrecy (see the list of ciphers below.)

* Certificates must be signed using a SHA256 or greater signature hash algorithm, with either a 2048-bit or greater RSA key or a 256-bit or greater Elliptic-Curve (ECC) key.


I've checked that my server is indeed using a certificate with 2048-bit RSA key and signed using SHA256 hash algorithm. Anyhow, my Xcode7-built app failed to connect to my server with default ATS setting. After I set `NSExceptionRequiresForwardSecrecy` to `NO` in the app's `Info.plist`, however, the connection succeeded. So it looks like that my server isn't correctly configured with forward secrecy ciphers. Below is my current setting in nginx.conf:


    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers               'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';


I also regenerate a new DH group with the following command:

    openssl dhparam -out dhparams.pem 2048

and added it in my nginx configuration:

    ssl_dhparam dhparams.pem;


According to Apple's document, with default ATS settings, accepted ciphers include:


  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA


(It seems that my nginx's ssl_ciphers setting has these ciphers.)


And if `NSExceptionRequiresForwardSecrecy` is set to `NO` in the app's settings, following ciphers will also be accepted:


  • LS_RSA_WITH_AES_256_GCM_SHA384
  • TLS_RSA_WITH_AES_128_GCM_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA


With this set to `NO`, my app connects successfully to my server, though the reason remains unknown to me.

(Running `nsurl --ats-diagnostics` indicates the same thing.)


So my question is, how should I setup nginx for forward secrecy ciphers so that iOS9 (Xcode7) app with default ATS settings can connect successfully?


For diagnosis purpose, below is the **ssltest** result page screenshot of my server given by ssllabs:

http://i.stack.imgur.com/Dg6cL.png

Please use TLSTool to connect to your server from OS X 10.11 and then post the results here. For example:

$ TLSTool s_client -connect forums.developer.apple.com:443
… lots of output elided …

Share and Enjoy

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

let myEmail = "eskimo" + "1" + "@apple.com"
How to setup forward secrecy in nginx so that iOS9 (Xcode7) app with default ATS settings can connect to the server?
 
 
Q