Forum: NGINX Setting ssl_ecdh_curve to secp384r1 does not work

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
92986d4d0e7edc94494b2e1478228204?d=identicon&s=25 Florian Reinhart (Guest)
on 2016-07-05 14:00
(Received via mailing list)
Hi all,

I was running nginx 1.9.12 on Ubuntu 14.04 built from the source tarball
with these options: --with-ipv6 --with-http_ssl_module
--with-http_v2_module --with-openssl=/openssl-1.0.2g

While switching to a new server, I also wanted to switch to the nginx
Docker container using my existing nginx config.

First, I discovered an issue with missing ALPN support due to an old
OpenSSL version in Debian Jessie (see
https://github.com/nginxinc/docker-nginx/issues/76 ). Therefore, I
switched to the Alpine image and discovered another issue.

The issue seems to be related to the ssl_ecdh_curve setting. In my
config I set it to secp384r1. With this setting present clients won’t
connect. This is what curl outputs:

curl -vvvv -k  "https://localhost"
* Rebuilt URL to: https://localhost/
*   Trying ::1...
* connect to ::1 port 443 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection:
ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /usr/local/etc/openssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Unknown (21):
* TLSv1.2 (IN), TLS alert, Server hello (2):
* error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert
handshake failure
* Closing connection 0
curl: (35) error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3
alert handshake failure


When I remove ssl_ecdh_curve from my config or set it to auto (which is
the default) everything works fine.

To investigate this issue further I created a virtual machine running
Ubuntu 16.04 and installed the latest nginx from the official package
source: http://nginx.org/en/linux_packages.html I was able to reproduce
the exact same issue in this virtual machine.

Do you have an idea what’s going on here? Please let me know if you need
any additional information.

Thanks!
Florian
A8108a0961c6087c43cda32c8616dcba?d=identicon&s=25 Maxim Dounin (Guest)
on 2016-07-05 15:20
(Received via mailing list)
Hello!

On Tue, Jul 05, 2016 at 02:00:04PM +0200, Florian Reinhart wrote:

> curl -vvvv -k  "https://localhost"
>   CApath: none
>
> To investigate this issue further I created a virtual machine running Ubuntu
16.04 and installed the latest nginx from the official package source:
http://nginx.org/en/linux_packages.html I was able to reproduce the exact same
issue in this virtual machine.
>
> Do you have an idea what’s going on here? Please let me know if you need any
additional information.

It looks like the client doesn't support the curve you've
configured, and non-ECDH ciphers are disabled.

--
Maxim Dounin
http://nginx.org/
92986d4d0e7edc94494b2e1478228204?d=identicon&s=25 Florian Reinhart (Guest)
on 2016-07-05 16:02
(Received via mailing list)
Hi Maxim!

That’s what I thought. However, all clients can access the nginx server
on the old Ubuntu 14.04 server, which uses the same config,

I tested the following clients on OS X 10.11.5, all failed to connect:

curl, installed from Homebrew: curl 7.49.1 (x86_64-apple-darwin15.5.0)
libcurl/7.49.1 OpenSSL/1.0.2h zlib/1.2.5 nghttp2/1.12.0
Safari 9.1.1 (11601.6.17)
Chrome 51.0.2704.106
Firefox 47.0.1

That’s why I don’t think it is a client issue.

Best,
Florian
A8108a0961c6087c43cda32c8616dcba?d=identicon&s=25 Maxim Dounin (Guest)
on 2016-07-05 16:40
(Received via mailing list)
Hello!

On Tue, Jul 05, 2016 at 04:02:21PM +0200, Florian Reinhart wrote:

>
> That’s why I don’t think it is a client issue.

Yes, at least browsers are expected to support secp384r1, so it's
probably something different.

Which certificate do you use?  Is it the same as on the old
server?  Such a situation can easily happen if the only
certificate available is ECDSA one and uses, e.g., prime256v1 (not
secp384r1), but only secp384r1 is enabled by the configuration.

Looking into nginx error logs might also somewhat help to diagnose
what goes on here.

--
Maxim Dounin
http://nginx.org/
92986d4d0e7edc94494b2e1478228204?d=identicon&s=25 Florian Reinhart (Guest)
on 2016-07-05 17:02
(Received via mailing list)
Thanks a lot for your suggestions.

It is the same certificate on both servers and it is indeed a secp256r1
aka prime256v1 certificate. So does this mean, I have to use prime256v1
for ssl_ecdh_curve with this certificate? It’s still strange that it
used to work before...

Here is what the error log says:
2016/07/05 16:57:09 [info] 2525#2525: *115 SSL_do_handshake() failed
(SSL: error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared
cipher) while SSL handshaking, client: 192.168.241.1, server:
0.0.0.0:443

Thanks again!
A8108a0961c6087c43cda32c8616dcba?d=identicon&s=25 Maxim Dounin (Guest)
on 2016-07-05 20:16
(Received via mailing list)
Hello!

On Tue, Jul 05, 2016 at 05:02:07PM +0200, Florian Reinhart wrote:

> It is the same certificate on both servers and it is indeed a
> secp256r1 aka prime256v1 certificate. So does this mean, I have
> to use prime256v1 for ssl_ecdh_curve with this certificate? It’s
> still strange that it used to work before...

Since version 1.11.0 nginx uses the new SSL_CTX_set1_curves_list()
interface if available to configure supported curves, instead of
previously used EC_KEY_new_by_curve_name()/SSL_CTX_set_tmp_ecdh().
This new interface is generally better as it allows configuring
multiple curves.

I've just tested, and it looks like this new interface is also
more strict.  With previous interface it was possible to use any
certificate regardless of the ssl_ecdh_curve setting, and that's
why it worked for you in older versions.  The new interface does
not allow to use curves which are not listed at all, including
certificates using these curves.

Solution would be to list all curves you want to use, including
curves used by certificates, e.g.:

    ssl_ecdh_curve secp384r1:prime256v1;

Or, better yet, just leave the default ("auto"), it will allow
most common curves as supported by OpenSSL.

--
Maxim Dounin
http://nginx.org/
92986d4d0e7edc94494b2e1478228204?d=identicon&s=25 Florian Reinhart (Guest)
on 2016-07-06 09:16
(Received via mailing list)
Hi Maxim!

Thanks for investigating this! I thought ssl_ecdh_curve was only used to
specific curves for ECDHE.

Is there any way to know what curves "auto" will include on my system?

—Florian
2fd0c3f17efded066208e74d8e7f307e?d=identicon&s=25 Kurt Cancemi (Guest)
on 2016-07-06 11:33
(Received via mailing list)
Hello,

The following are in auto:

 secp256r1
 secp521r1
 brainpool512r1
 brainpoolP384r1
 secp384r1
 brainpoolP256r1
 secp256k1
If not configured with OPENSSL_NO_EC2M
 sect571r1
 sect571k1
 sect409k1
 sect409r1
 sect283k1
 sect283r1
#endif

From OpenSSL source:
https://github.com/openssl/openssl/blob/OpenSSL_1_...

Kurt Cancemi
https://www.x64architecture.com
A8108a0961c6087c43cda32c8616dcba?d=identicon&s=25 Maxim Dounin (Guest)
on 2016-07-06 18:08
(Received via mailing list)
Hello!

On Wed, Jul 06, 2016 at 09:15:59AM +0200, Florian Reinhart wrote:

> Is there any way to know what curves "auto" will include on my
> system?

This is not currently possible, AFAIK, and depends on the OpenSSL
library used.  Here is a short summary for varions OpenSSL version
I've previously looked into:

- OpenSSL 1.0.2, 1.0.2a: all curves supported, strongest first.
  Full list is available via "openssl ecparam -list_curves".

- OpenSSL 1.0.2b ... 1.0.2h: limited default list with at least
  256 bits, prime256v1 (aka P-256) first.  List in OpenSSL 1.0.2g
  is as follows:

      P-256:P-521:brainpoolP512r1:brainpoolP384r1:P-384:brainpoolP256r1:secp256k1:B-571:K-571:K-409:B-409:K-283:B-283

- Upcoming OpenSSL 1.1.0 uses X25519:P-256:P-521:P-384 (aka
  X25519:secp256r1:secp521r1:secp384r1).

--
Maxim Dounin
http://nginx.org/
This topic is locked and can not be replied to.