title: How to setup forward secrecy in nginx so that iOS9 (Xcode7) app with default ATS settings can connect to my server?
body: <p>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 (<a href="https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/index.html" rel="nofollow noreferrer">https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/index.html</a>)</p>
  
  <ul>
  <li>The server must support at least Transport Layer Security (TLS) protocol version 1.2.</li>
  <li>Connection ciphers are limited to those that provide forward secrecy (see the list of ciphers below.)</li>
  <li>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.</li>
  </ul>
  
  <p>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 <code>NSExceptionRequiresForwardSecrecy</code> to <code>NO</code> in the app's <code>Info.plist</code>, 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:</p>
  
  <pre><code>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';
  </code></pre>
  
  <p>My certificate is issued by Comodo and the setting I used above is also from Comodo's support document (<a href="https://support.comodo.com/index.php?/Default/Knowledgebase/Article/View/789/37/certificate-installation-nginx" rel="nofollow noreferrer">https://support.comodo.com/index.php?/Default/Knowledgebase/Article/View/789/37/certificate-installation-nginx</a>).</p>
  
  <p>According to Apple's document, with default ATS settings, accepted ciphers include:</p>
  
  <ul>
  <li>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384</li>
  <li>TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</li>
  <li>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384</li>
  <li>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA</li>
  <li>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</li>
  <li>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA</li>
  <li>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</li>
  <li>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</li>
  <li>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384</li>
  <li>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256</li>
  <li>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</li>
  </ul>
  
  <p>(It seems that my nginx's ssl_ciphers setting has these ciphers.)</p>
  
  <p>And if <code>NSExceptionRequiresForwardSecrecy</code> is set to <code>NO</code> in the app's settings, following ciphers will also be accepted: </p>
  
  <ul>
  <li>LS_RSA_WITH_AES_256_GCM_SHA384</li>
  <li>TLS_RSA_WITH_AES_128_GCM_SHA256</li>
  <li>TLS_RSA_WITH_AES_256_CBC_SHA256</li>
  <li>TLS_RSA_WITH_AES_256_CBC_SHA</li>
  <li>TLS_RSA_WITH_AES_128_CBC_SHA256</li>
  <li>TLS_RSA_WITH_AES_128_CBC_SHA</li>
  </ul>
  
  <p>With this set to <code>NO</code>, my app connects successfully to my server, though the reason remains unknown to me.</p>
  
  <p>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?</p>
  
  <hr>
  
  <p>UPDATED:</p>
  
  <p>With the suggestion given by @keno, I reconfigured my server following the guide from <a href="https://weakdh.org/sysadmin.html" rel="nofollow noreferrer">https://weakdh.org/sysadmin.html</a>.  I regenerate a new DH group with the following command:</p>
  
  <pre><code>openssl dhparam -out dhparams.pem 2048
  </code></pre>
  
  <p>and added it in my nginx configuration:</p>
  
  <pre><code>ssl_dhparam dhparams.pem;
  </code></pre>
  
  <p>But the connection from my app still fails.  The <code>nsurl --ats-diagnostics</code> tool still indicates that the problem is caused by forward secrecy.</p>
  
  <hr>
  
  <p>For diagnosis purpose, below is the <strong>ssltest</strong> result page screenshot of my server given by <a href="https://www.ssllabs.com/ssltest" rel="nofollow noreferrer">ssllabs</a>:</p>
  
  <p><a href="https://i.stack.imgur.com/Dg6cL.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Dg6cL.png" alt="enter image description here"></a></p>