[ 
https://issues.apache.org/jira/browse/TS-3283?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Susan Hinrichs updated TS-3283:
-------------------------------
    Comment: was deleted

(was: Looked at the code more closely and ran a few cases though the debugger.  
I think we are in good shape here.

In the accept case, the trampoline sends the accept message through other 
accept objects.  Ultimately session objects are created.

In the error case, we don't want to create a session object.  The accept 
objects are static so they do not need to be deleted.

Looking through the other case that send and receive NET_EVENT_ACCEPT events, 
the error cases are mostly not addressed.  In one case, the do_io_close was 
called on the net vc.

Here in the SSLNextProtocolTrampoline, with the patch in the error case we call 
netvc->do_io_close and delete the trampoline object.  Which I think cleans up 
everything that has been allocated for the connection so far.)

> Certain SSL handshake error during client-hello hangs the client and leaves 
> network connection open
> ---------------------------------------------------------------------------------------------------
>
>                 Key: TS-3283
>                 URL: https://issues.apache.org/jira/browse/TS-3283
>             Project: Traffic Server
>          Issue Type: Bug
>          Components: SSL
>            Reporter: Joe Chung
>            Assignee: Phil Sorber
>             Fix For: 4.2.3
>
>
> h3. Problem Description
> Send an SSLv2 Client Hello with an old cipher suite request against Traffic 
> Server 4.2.2, and the connection will freeze on the client side and 
> eventually time out after 120 seconds.
> The Traffic Server detects the SSL error, but instead of closing the 
> connection, goes on to accept new connections.
> h3. Reproduction
> === Client: Macbook Pro running OSX Mavericks 10.9.5 ===
> {code:none}
> $ openssl version -a
> OpenSSL 0.9.8za 5 Jun 2014
> built on: Aug 10 2014
> platform: darwin64-x86_64-llvm
> options:  bn(64,64) md2(int) rc4(ptr,char) des(idx,cisc,16,int) blowfish(idx)
> compiler: -arch x86_64 -fmessage-length=0 -pipe -Wno-trigraphs 
> -fpascal-strings -fasm-blocks -O3 -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H 
> -DL_ENDIAN -DMD32_REG_T=int -DOPENSSL_NO_IDEA -DOPENSSL_PIC -DOPENSSL_THREADS 
> -DZLIB -mmacosx-version-min=10.6
> OPENSSLDIR: "/System/Library/OpenSSL"
> {code}
> h4. The following command triggers the bad behavior on the 4.2.2 server.
> {code:none}
> $ openssl s_client -connect 192.168.20.130:443 -ssl2 -debug
> CONNECTED(00000003)
> write to 0x7fb9f2508610 [0x7fb9f300f201] (45 bytes => 45 (0x2D))
> 0000 - 80 2b 01 00 02 00 12 00-00 00 10 07 00 c0 03 00   .+..............
> 0010 - 80 01 00 80 06 00 40 04-00 80 02 00 80 f4 71 1a   ......@.......q.
> 0020 - ad 23 06 59 4d f8 d2 c5-b2 57 a9 66 4c            .#.YM....W.fL
> ^C
> {code}
> At this point, the client is hung, and I have to hit ctrl-c to interrupt it 
> or wait 120 seconds for tcp timeout.
> h3. Server: Lubuntu 13.10 on VMware
> {code:none}
> $ openssl version -a
> OpenSSL 1.0.1e 11 Feb 2013
> built on: Fri Jun 20 18:52:25 UTC 2014
> platform: debian-i386
> options:  bn(64,32) rc4(8x,mmx) des(ptr,risc1,16,long) blowfish(idx) 
> compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT 
> -DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector 
> --param=ssp-buffer-size=4 -Wformat -Werror=format-security 
> -D_FORTIFY_SOURCE=2 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack 
> -Wall -DOPENSSL_NO_TLS1_2_CLIENT -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 
> -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT 
> -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM 
> -DRMD160_ASM -DAES_ASM -DVPAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
> OPENSSLDIR: "/usr/lib/ssl"
> {code}
> {code:none}
> $ diff /usr/local/etc/trafficserver/records.config.422 
> /usr/local/etc/trafficserver/records.config
> 113c113
> < CONFIG proxy.config.http.server_ports STRING 8080
> ---
> > CONFIG proxy.config.http.server_ports STRING 8080 443:ssl
> 594,595c594,595
> < CONFIG proxy.config.diags.debug.enabled INT 0
> < CONFIG proxy.config.diags.debug.tags STRING http.*|dns.*
> ---
> > CONFIG proxy.config.diags.debug.enabled INT 1
> > CONFIG proxy.config.diags.debug.tags STRING ssl.*
> {code}
> {code:none}
> $ /usr/local/bin/traffic_server --version
> [TrafficServer] using root directory '/usr/local'
> Apache Traffic Server - traffic_server - 4.2.2 - (build # 0723 on Jan  7 2015 
> at 23:04:32)
> $ sudo /usr/local/bin/traffic_server
> [sudo] password for user:
> [TrafficServer] using root directory '/usr/local'
> [Jan  8 00:53:42.618] Server {0xb702e700} DEBUG: (ssl) setting SNI callbacks 
> with for ctx 0xa4a7928
> [Jan  8 00:53:42.618] Server {0xb702e700} DEBUG: (ssl) indexed '*' with 
> SSL_CTX 0xa4a7928
> [Jan  8 00:53:42.619] Server {0xb702e700} DEBUG: (ssl) importing SNI names 
> from /usr/local/etc/trafficserver
> [Jan  8 00:54:02.256] Server {0xb6265b40} DEBUG: (ssl) 
> [SSLNextProtocolAccept:mainEvent] event 202 netvc 0xb280fa90
> [Jan  8 00:54:02.256] Server {0xb6265b40} DEBUG: (ssl) ssl_callback_info ssl: 
> 0xb280fcb8 where: 16 ret: 1
> [Jan  8 00:54:02.256] Server {0xb6265b40} DEBUG: (ssl) ssl_callback_info ssl: 
> 0xb280fcb8 where: 8193 ret: 1
> [Jan  8 00:54:02.256] Server {0xb6265b40} DEBUG: (ssl) ssl_callback_info ssl: 
> 0xb280fcb8 where: 8194 ret: -1
> [Jan  8 00:54:02.256] Server {0xb6265b40} DEBUG: (ssl) 
> SSL::3055967040:error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown 
> protocol:s23_srvr.c:628
> [Jan  8 00:54:02.256] Server {0xb6265b40} DEBUG: <SSLNetVConnection.cc:526 
> (sslServerHandShakeEvent)> (ssl) SSL handshake error: SSL_ERROR_SSL (1), 
> errno=0
> {code}
> At this point, the server has not closed the tcp connection, and has instead 
> gone back to the accept loop, waiting for new connections.
> After 120 seconds (TCP timeout) the connection is eventually closed. During 
> this time, the server process holds onto a file descriptor needlessly for 120 
> seconds. I connected to the server from multiple clients and counted the 
> server's number of open fds after each connection ({{sudo ls -1 /proc/$pid/fd 
> | wc -l}}).
> This behavior makes the server vulnerable to a denial-of-service attack.
> h3. Possible Fix
> In gdb, I compared the behavior of 5.1.2 vs 4.2.2 in the face of an 
> {{SSL_ERROR_SSL}} during the Client Hello handshake. I noticed that in 5.1.2, 
> there is a {{netvc->do_io(VIO::CLOSE)}} in 
> {{SSLNextProtocolTrampoline::ioCompletionEvent()}} that closes the TCP 
> connection.
> When I apply the following diff to the 4.2.2 code base (essentially making 
> this function look more like the 5.1.2 version), it fixes the problem; i.e. 
> the server immediately closes the TCP connection after the error is detected.
> {code:none}
> $ git diff
> diff --git a/iocore/net/SSLNextProtocolAccept.cc 
> b/iocore/net/SSLNextProtocolAccept.cc
> index bfc2f0b..a5612c6 100644
> --- a/iocore/net/SSLNextProtocolAccept.cc
> +++ b/iocore/net/SSLNextProtocolAccept.cc
> @@ -78,19 +78,22 @@ struct SSLNextProtocolTrampoline : public Continuation
>      Continuation * plugin;
>      SSLNetVConnection * netvc;
> +    vio = static_cast<VIO *>(edata);
> +    netvc = dynamic_cast<SSLNetVConnection *>(vio->vc_server);
> +    ink_assert(netvc != NULL);
> +
>      switch (event) {
>      case VC_EVENT_INACTIVITY_TIMEOUT:
> -    case VC_EVENT_READ_COMPLETE:
>      case VC_EVENT_ERROR:
> -      vio = static_cast<VIO *>(edata);
> +      netvc->do_io(VIO::CLOSE);
> +      delete this;
> +      return EVENT_CONT;
> +    case VC_EVENT_READ_COMPLETE:
>        break;
>      default:
>        return EVENT_ERROR;
>      }
> -    netvc = dynamic_cast<SSLNetVConnection *>(vio->vc_server);
> -    ink_assert(netvc != NULL);
> -
>      plugin = netvc->endpoint();
>      if (plugin) {
>        send_plugin_event(plugin, NET_EVENT_ACCEPT, netvc);
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to