Opened 7 years ago

Closed 6 years ago

#1376 closed enhancement (fixed)

nginx disable client initiated renegotiation not working perfect with openssl 1.1.0c

Reported by: taolinke@… Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.11.x
Keywords: renegotiation openssl Cc:
uname -a: Linux centos_8 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.11.6

Description

Hey i recompile Nginx 1.11.6 with openssl 1.1.0, then i found that disable client initiated renegotiation is not working perfect.
openssl command is

./openssl s_client -tls1_2  -connect 192.168.19.133:443 -msg

With openssl 1.0.2h,openssl got "write: errno =0" after send ClientHello.

R
RENEGOTIATING
>>> ??? [length 0005]
    16 03 03 00 ac
>>> TLS 1.2Handshake [length 0094], ClientHello
    01 00 00 90 03 03 a8 cc dd 75 1e 1b ed f9 5b 43
    df 96 0c 68 b5 5d 89 c4 db ed d7 19 95 1b e7 0b
    10 9f bb 2a 30 61 00 00 10 c0 2c c0 30 c0 af c0
    ad c0 24 c0 28 c0 0a c0 14 01 00 00 57 ff 01 00
    0d 0c 0f 3b 9f 13 0c 93 d1 20 ac a0 31 83 00 0b
    00 04 03 00 01 02 00 0a 00 0a 00 08 00 1d 00 17
    00 19 00 18 00 23 00 00 00 0d 00 20 00 1e 06 01
    06 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03
    03 01 03 02 03 03 02 01 02 02 02 03 00 16 00 00
    00 17 00 00
'''write:errno=0'''

But With openssl 1.1.0,openssl got "write: errno =0" after finished renegotiation.

---
R
RENEGOTIATING
>>> ??? [length 0005]
    16 03 03 00 ac
>>> TLS 1.2Handshake [length 0094], ClientHello
    01 00 00 90 03 03 54 52 70 89 38 26 eb b0 95 26
    69 ab 80 dd 26 6d 88 a7 87 0c 4f 76 b7 e7 20 4d
    c6 99 74 e5 aa 65 00 00 10 c0 2c c0 30 c0 af c0
    ad c0 24 c0 28 c0 0a c0 14 01 00 00 57 ff 01 00
    0d 0c 4d 15 33 c5 7f 5c da 76 29 5f 77 a8 00 0b
    00 04 03 00 01 02 00 0a 00 0a 00 08 00 1d 00 17
    00 19 00 18 00 23 00 00 00 0d 00 20 00 1e 06 01
    06 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03
    03 01 03 02 03 03 02 01 02 02 02 03 00 16 00 00
    00 17 00 00
<<< ??? [length 0005]
    16 03 03 00 71
<<< TLS 1.2Handshake [length 0059], ServerHello
    02 00 00 55 03 03 61 91 92 bc a9 9f 7d 6e 26 12
    63 36 3b 49 78 14 3b 62 f0 49 a3 e9 c8 09 aa 81
    da 92 b5 b4 05 59 00 c0 30 00 00 2d ff 01 00 19
    18 4d 15 33 c5 7f 5c da 76 29 5f 77 a8 29 cd 5d
    c4 a3 88 f7 eb 39 1e a6 96 00 0b 00 04 03 00 01
    02 00 23 00 00 00 17 00 00
<<< ??? [length 0005]
    16 03 03 03 42
<<< TLS 1.2Handshake [length 032a], Certificate
......
<<< ??? [length 0005]
    16 03 03 00 1c
<<< TLS 1.2Handshake [length 0004], ServerHelloDone
    0e 00 00 00
>>> ??? [length 0005]
    16 03 03 00 3d
>>> TLS 1.2Handshake [length 0025], ClientKeyExchange
    10 00 00 21 20 72 dd b8 de 67 0c 18 8e fd 9c 54
    5c 4f e9 a3 0a 55 01 c3 0a 84 29 83 f7 8e a2 fd
    09 01 cb c6 24
>>> ??? [length 0005]
    14 03 03 00 19
>>> TLS 1.2ChangeCipherSpec [length 0001]
    01
>>> ??? [length 0005]
    16 03 03 00 28
'''>>> TLS 1.2Handshake [length 0010], Finished
    14 00 00 0c 28 e9 5d 49 f7 6e e4 b3 83 cb c5 ff
write:errno=0'''

That means Nginx server costs CPU to calculate keys.
That's not the purpose.

Change History (8)

comment:1 by taolinke@…, 7 years ago

Sorry about the nginx -v,here is nginx -V

nginx version: nginx/1.11.6
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC)
built with OpenSSL 1.1.0c  10 Nov 2016
TLS SNI support enabled
configure arguments: --with-http_ssl_module --with-openssl=/zz/openssl-1.1.0c

comment:2 by Maxim Dounin, 7 years ago

Resolution: wontfix
Status: newclosed

Unfortunately, OpenSSL provides no interface to disable renegotiation completely. We use two mechanisms to disable renegotiation:

  • set the SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS flag on s->s3->flags to prevent renegotiation handling within OpenSSL code;
  • detect renegotiation attempts via an info callback, and close the connection when we detect one.

With OpenSSL 1.1.0, it is no longer possible to set SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS, as it is no longer possible to access s->s3->flags directly, and there is no interface to set the flag. Moreover, the flag is at all removed in the OpenSSL master branch.

As such, only the "close the connection" mechanism remains. It is still expected to prevent most of the negative effects of renegotiation though. In particular, it doesn't allow one to use arbitrary amount of CPU resources in a single connection.

If you think that things can be improved further, feel free to contribute.

comment:3 by taolinke@…, 7 years ago

Thanks for replying.
I solve the problem by adding a magic number in SSL_set_options.
Like this one

unsigned long SSL_set_options(SSL *s, unsigned long op)
{
    if(op == 0x012fa6c6) {
            s->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
            op = 0;
    }
    return s->options |= op;
}

Then after first handshake finished, i invoke the SSL_set_options.
With the help of SSL_CTX_set_info_callback, i can close the connection right after
the client_hello in renegotiation.

in reply to:  2 comment:4 by taolinke@…, 7 years ago

Replying to mdounin:

Unfortunately, OpenSSL provides no interface to disable renegotiation completely. We use two mechanisms to disable renegotiation:

  • set the SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS flag on s->s3->flags to prevent renegotiation handling within OpenSSL code;
  • detect renegotiation attempts via an info callback, and close the connection when we detect one.

With OpenSSL 1.1.0, it is no longer possible to set SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS, as it is no longer possible to access s->s3->flags directly, and there is no interface to set the flag. Moreover, the flag is at all removed in the OpenSSL master branch.

As such, only the "close the connection" mechanism remains. It is still expected to prevent most of the negative effects of renegotiation though. In particular, it doesn't allow one to use arbitrary amount of CPU resources in a single connection.

If you think that things can be improved further, feel free to contribute.

Thanks for replying.
I solve the problem by adding a magic number in SSL_set_options.
Like this one

unsigned long SSL_set_options(SSL *s, unsigned long op)
{
    if(op == 0x012fa6c6) {
            s->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
            op = 0;
    }
    return s->options |= op;
}

Then after first handshake finished, i invoke the SSL_set_options.
With the help of SSL_CTX_set_info_callback, i can close the connection right after
the client_hello in renegotiation.

comment:5 by wynn.tee@…, 7 years ago

Resolution: wontfix
Status: closedreopened

The SSL_OP_NO_RENEGOTIATION option was added to openssl-1.1.0 in December 2017. See https://github.com/openssl/openssl/pull/4901

Should this issue be looked at again?

comment:6 by Maxim Dounin, 6 years ago

Try the following patch:

# HG changeset patch
# User Maxim Dounin <mdounin@mdounin.ru>
# Date 1531420730 -10800
#      Thu Jul 12 21:38:50 2018 +0300
# Node ID 1c07c30234a5e26b7f240a7582bb8b572182cf0b
# Parent  8f152ca81f5f11114e8853a0fe89fb42c977e605
SSL: use of the SSL_OP_NO_RENEGOTIATION option (ticket #1376).

The SSL_OP_NO_RENEGOTIATION option is available in OpenSSL 1.1.0h+ and can
save some CPU cycles on renegotiation attempts.

diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1193,6 +1193,10 @@ ngx_ssl_create_connection(ngx_ssl_t *ssl
 
     } else {
         SSL_set_accept_state(sc->connection);
+
+#ifdef SSL_OP_NO_RENEGOTIATION
+        SSL_set_options(sc->connection, SSL_OP_NO_RENEGOTIATION);
+#endif
     }
 
     if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {

comment:7 by Maxim Dounin <mdounin@…>, 6 years ago

In 7319:dcab86115261/nginx:

SSL: use of the SSL_OP_NO_RENEGOTIATION option (ticket #1376).

The SSL_OP_NO_RENEGOTIATION option is available in OpenSSL 1.1.0h+ and can
save some CPU cycles on renegotiation attempts.

comment:8 by Maxim Dounin, 6 years ago

Priority: majorminor
Resolution: fixed
Status: reopenedclosed
Type: defectenhancement
Note: See TracTickets for help on using tickets.