Opened 3 years ago

Closed 5 weeks ago

#1445 closed enhancement (fixed)

OpenSSL - ChaCha prioritized - Nginx enhancement

Reported by: xetorixik@… Owned by:
Priority: minor Milestone:
Component: other Version: 1.13.x
Keywords: chacha openssl nginx Cc:
uname -a: Linux some.domain.com 4.13.3-xn #1 SMP Thu Sep 21 18:31:01 EEST 2017 x86_64 Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz GenuineIntel GNU/Linux
nginx -V: nginx version: nginx/1.13.6 built with OpenSSL 1.0.2l 25 May 2017 TLS SNI support enabled configure arguments: --prefix=/usr --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error_log --pid-path=/run/nginx.pid --lock-path=/run/lock/nginx.lock --with-cc-opt='-I/usr/include -DNGX_HAVE_INET6=0' --with-ld-opt=-L/usr/lib64 --http-log-path=/var/log/nginx/access_log --http-client-body-temp-path=/var/lib/nginx/tmp/client --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --with-compat --with-file-aio --with-http_v2_module --with-pcre --with-threads --without-http_memcached_module --without-http_scgi_module --without-http_ssi_module --without-http_split_clients_module --without-http_upstream_hash_module --without-http_upstream_ip_hash_module --without-http_upstream_keepalive_module --without-http_upstream_least_conn_module --without-http_userid_module --without-http_uwsgi_module --with-http_geoip_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_realip_module --with-http_ssl_module --without-stream_access_module --without-stream_geo_module --without-stream_limit_conn_module --without-stream_map_module --without-stream_return_module --without-stream_split_clients_module --without-stream_upstream_hash_module --without-stream_upstream_least_conn_module --without-stream_upstream_zone_module --without-mail_imap_module --without-mail_pop3_module --without-mail_smtp_module --user=nginx --group=nginx

Description

OpenSSL supports ChaCha prioritized in their upcoming version.

With this new feature you could not only set ServerPreference (SSL_OP_CIPHER_SERVER_PREFERENCE) but also PrioritizeChaCha (SSL_OP_PRIORITIZE_CHACHA).

Please add OpenSSL PrioritizeChaCha support to Nginx.

"IFF the client has ChaCha first, and server cipher priority is used,
and the new SSL_OP_PRIORITIZE_CHACHA_FOR_MOBILE option is used,
then reprioritize ChaCha above everything else. This way, A matching
ChaCha cipher will be selected if there is a match. If no ChaCha ciphers
match, then the other ciphers are used."

Change History (14)

comment:1 by Maxim Dounin, 3 years ago

So, it's basically allows configuring something like "prefer server ciphers, but not for ChaCha; for ChaCha, prefer client ciphers instead". Funny enough. Simply "prefer client ciphers" might actually be a better option, and this is the default.

Just for the record, here is the pull request which introduces the option and the related discussion. I completely agree with Viktor Dukhovni that this "feature" looks more like a hack. And I don't think that the same hack should be introduced in nginx. At most, we can consider a generic interface to set various OpenSSL options.

comment:2 by xetorixik@…, 3 years ago

A "generic interface to set various OpenSSL options" should be fine.
Thanks for the reply.

comment:3 by Neil Craig, 2 years ago

Hi
I'd really love to see a way to be able to use the -prioritize_chacha flag in nginx, ideally as a runtime (rather than compile time) option.

For the sake of completeness (apologies if you know all this already), it's perhaps worth stating that CHACHA is roughly 3x faster than AES-based suites (see https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/#performance) for clients which don't have AES NI instructions in their CPU - so clearly CHACHA is attractive. Also worth noting that CHACHA is significantly slower than AES on platforms which do have AES NI.

We can't use simple (serverside) ciphersuite pref order to use CHACHA as many/most clients running on platforms which do have AES NI instructions in their CPU and they offer CHACHA so if we pref that as #1 on the server side, CHACHA will be used for clients with AES NI and performance suffers.

This means that it's essentially impossible to use CHACHA without a directive or a patch (of which several exist e.g. https://github.com/cloudflare/sslconfig/tree/master/patches but trying to use patches long term is obviously not ideal as all those i have tried don't work on current nginx versions). I can't even find a way to pref CHACHA in Lua (via the Openresty module).

So if there is any way we could get a way in nginx runtime (or failing that, compile time) directives to pref CHACHA if it's the top client pref, that'd be amazing. Since OpenSSL has done (what looks to me like) most of the heavy lifting, it seems like it might be quite simple to do (?). I personally would have no preference for a specific (i.e. "prioritise_chacha: <boolean>") or a generic (i.e. "openssl_flags: <string>") directive, it'd just be a great help to be able to use what openSSL provides.

If it would help, i could ask one of my colleagues in engineering if they could create a diff to be (hopefully) merged, though they might need some pointers/help to make sure it's done in an acceptable way).

Cheers
Neil

comment:4 by Neil Craig, 2 years ago

Sorry to hassle but i'm just wondering if the above changes things at al? It'd be great to hear the thoughts of the nginx folks :-)

comment:5 by Maxim Dounin, 2 years ago

As already mentioned in the comment:1, most simple solution would be to keep the default value of ssl_prefer_server_ciphers. Trying to configure ciphers preference order on the server side inevitably means that the resulting order will be suboptimal for some clients.

comment:6 by Steffen Weber, 2 years ago

Patch that enables the SSL_OP_PRIORITIZE_CHACHA flag if "ssl_prefer_server_ciphers" is enabled. Maybe this could be an option for nginx?

diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 7512913..bae62b7 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -665,7 +665,7 @@ ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
     }

     if (prefer_server_ciphers) {
-        SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
+        SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_PRIORITIZE_CHACHA);
     }

 #if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)

Originally posted here: https://www.computerbase.de/forum/threads/in-eigener-sache-computerbase-nutzt-tls-1-3-ecdsa-und-lets-encrypt.1829997/page-3#post-21831569

Last edited 2 years ago by Steffen Weber (previous) (diff)

comment:8 by Maxim Dounin, 2 years ago

I'm sceptical about unconditional use of SSL_OP_PRIORITIZE_CHACHA, as this is not what ssl_prefer_server_ciphers is expected to mean.

Note well that if really needed, SSL_OP_PRIORITIZE_CHACHA can be turned on via OpenSSL config, without patching nginx. For example:

openssl_conf = default_conf

[default_conf]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
Options = PrioritizeChaCha

comment:9 by Maxim Dounin, 2 years ago

See also #1529 for another example where a generic interface to set various OpenSSL options might be useful.

comment:10 by Maxim Dounin, 19 months ago

See also #1778.

comment:11 by Alexey Ivanov, 19 months ago

In BoringSSL we use "equal preference cipher groups":

e.g.:

ssl_ciphers                 '[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:ECDHE+AES128:RSA+AES128:ECDHE+AES256:RSA+AES256:ECDHE+3DES:RSA+3DES';

comment:12 by Maxim Dounin, 8 months ago

See also #1942.

comment:13 by Maxim Dounin <mdounin@…>, 5 weeks ago

In 7729:3bff3f397c05/nginx:

SSL: ssl_conf_command directive.

With the ssl_conf_command directive it is now possible to set
arbitrary OpenSSL configuration parameters as long as nginx is compiled
with OpenSSL 1.0.2 or later. Full list of available configuration
commands can be found in the SSL_CONF_cmd manual page
(https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html).

In particular, this allows configuring PrioritizeChaCha option
(ticket #1445):

ssl_conf_command Options PrioritizeChaCha;

It can be also used to configure TLSv1.3 ciphers in OpenSSL,
which fails to configure them via the SSL_CTX_set_cipher_list()
interface (ticket #1529):

ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256;

Configuration commands are applied after nginx own configuration
for SSL, so they can be used to override anything set by nginx.
Note though that configuring OpenSSL directly with ssl_conf_command
might result in a behaviour nginx does not expect, and should be
done with care.

comment:14 by Maxim Dounin, 5 weeks ago

Resolution: fixed
Status: newclosed

Committed, thanks to all involved for prodding this.

Note: See TracTickets for help on using tickets.