From: Török E. <edw...@et...> - 2013-09-21 19:58:26
Attachments:
https_client.patch
|
Hi, Attached patch implements a workaround to allow persistent connections to work with HTTPS, avoiding bugs in Https_client#continue. See below for the long explanation. Persistent HTTP connections work if I enable the aggressive connection cache with Http_client. However with Https_client I noticed that it always closed and reopened the Ssl connections. While this doesn't influence the application's correctness (thanks to the retry mechanisms in Http_client!), it heavily influences its performance: the latency is very bad due to repeated reopened connections, and repeated SSL handshakes ... even on localhost. Enabling Netlog debugging showed that some Ssl exceptions were thrown each time around read/write/shutdown after the 1st query completed. Further investigation revealed that the problem might be with Https_client#continue: method continue fd cb tmo tmo_x host port esys = - let mplex = - Uq_ssl.create_ssl_multiplex_controller - ~close_inactive_descr:true - ~preclose:(preclose fd) - ~initial_state:`Client - ~timeout:(tmo, tmo_x) - fd ctx esys in - (mplex :> Uq_engines.multiplex_controller) Problems with this code: * creating a new ssl multiplex controller will create a new Ssl.socket (and share just the Ssl.context and fd). * the new Ssl.socket doesn't have a defined state (SSL_set_connected_state was not called, and there was no prior handshake either), causing further operations on it to raise errors (if I add some debugging code to Uq_ssl to print Ssl.get_error_string): [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL write error: error:140D0114:SSL routines:SSL_write:uninitialized [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL read error: error:140DF114:SSL routines:SSL_read:uninitialized [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL shutdown error: error:140E0114:SSL routines:SSL_shutdown:uninitialized * the new Ssl.socket is probably missing the state of the handshake (session keys, etc.) The attached workaround implements a very simple workaround: if the esys is still the same just reuse the previous multiplex controller, I'm guessing this is what the Hashtbl was meant for anyway. A better solution would be to have something like create_ssl_multiplex_controller_for_existing_session that would take the existing Ssl.socket instead of creating a new one, and then Https_client#continue wouldn't have to drop the connection if esys or tmo changes. Best regards, --Edwin |
From: Gerd S. <in...@ge...> - 2013-09-23 10:57:16
Attachments:
signature.asc
|
Hi, thanks for the patch. If I don't find another solution, I'll apply it. Currently, I'm revising SSL anyway - OCamlnet 4.0 will have its own binding for GnuTLS, and this will give us a lot more freedom in the design. In particular, the management of the TCP connection and the TLS tunnel can be completely decoupled (i.e. TLS will appear as a separate layer on top of the multiplex controller). (If you are curious: https://godirepo.camlcity.org/wwwsvn/branches/onet4/code/src/nettls-gnutls/?root=lib-ocamlnet2) Gerd Am Samstag, den 21.09.2013, 22:58 +0300 schrieb Török Edwin: > Hi, > > Attached patch implements a workaround to allow persistent connections to work with HTTPS, > avoiding bugs in Https_client#continue. See below for the long explanation. > > Persistent HTTP connections work if I enable the aggressive connection cache with Http_client. > However with Https_client I noticed that it always closed and reopened the Ssl connections. > While this doesn't influence the application's correctness (thanks to the retry mechanisms in Http_client!), it heavily influences its performance: the latency is very bad due to repeated reopened connections, and repeated SSL handshakes ... even on localhost. > > Enabling Netlog debugging showed that some Ssl exceptions were thrown each time around read/write/shutdown after the 1st query completed. Further investigation revealed that the problem might be with Https_client#continue: > > method continue fd cb tmo tmo_x host port esys = > - let mplex = > - Uq_ssl.create_ssl_multiplex_controller > - ~close_inactive_descr:true > - ~preclose:(preclose fd) > - ~initial_state:`Client > - ~timeout:(tmo, tmo_x) > - fd ctx esys in > - (mplex :> Uq_engines.multiplex_controller) > > Problems with this code: > * creating a new ssl multiplex controller will create a new Ssl.socket (and share just the Ssl.context and fd). > * the new Ssl.socket doesn't have a defined state (SSL_set_connected_state was not called, and there was no prior handshake either), causing further operations on it to raise errors (if I add some debugging code > to Uq_ssl to print Ssl.get_error_string): > [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL write error: error:140D0114:SSL routines:SSL_write:uninitialized > [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL read error: error:140DF114:SSL routines:SSL_read:uninitialized > [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL shutdown error: error:140E0114:SSL routines:SSL_shutdown:uninitialized > * the new Ssl.socket is probably missing the state of the handshake (session keys, etc.) > > > The attached workaround implements a very simple workaround: if the esys is still the same > just reuse the previous multiplex controller, I'm guessing this is what the Hashtbl was meant for anyway. > > A better solution would be to have something like create_ssl_multiplex_controller_for_existing_session that would take the existing Ssl.socket instead of creating a new one, and then Https_client#continue wouldn't have to drop the connection if esys or tmo changes. > > Best regards, > --Edwin > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/22/13. > http://pubads.g.doubleclick.net/gampad/clk?id=64545871&iu=/4140/ostg.clktrk > _______________________________________________ Ocamlnet-devel mailing list Oca...@li... https://lists.sourceforge.net/lists/listinfo/ocamlnet-devel -- ------------------------------------------------------------ Gerd Stolpmann, Darmstadt, Germany ge...@ge... My OCaml site: http://www.camlcity.org Contact details: http://www.camlcity.org/contact.html Company homepage: http://www.gerd-stolpmann.de ------------------------------------------------------------ |
From: Török E. <edw...@et...> - 2013-09-23 15:10:18
|
On 09/23/2013 01:56 PM, Gerd Stolpmann wrote: > Hi, > > thanks for the patch. If I don't find another solution, I'll apply it. > > Currently, I'm revising SSL anyway - OCamlnet 4.0 will have its own > binding for GnuTLS, and this will give us a lot more freedom in the > design. In particular, the management of the TCP connection and the TLS > tunnel can be completely decoupled (i.e. TLS will appear as a separate > layer on top of the multiplex controller). > > (If you are curious: > https://godirepo.camlcity.org/wwwsvn/branches/onet4/code/src/nettls-gnutls/?root=lib-ocamlnet2) Interesting, does this mean that an application could choose between OpenSSL and GnuTLS by simply linking with nettls.gnutls vs nettls.openssl? [*] [*] Or why not someone could contribute a nettls.nss, as Fedora seems to prefer it over GnuTLS (Debian on the other hand seems to default to GnuTLS in curl for example): https://fedoraproject.org/wiki/FedoraCryptoConsolidation Best regards, --Edwin |
From: Gerd S. <in...@ge...> - 2013-09-23 15:39:17
Attachments:
signature.asc
|
Am Montag, den 23.09.2013, 18:10 +0300 schrieb Török Edwin: > On 09/23/2013 01:56 PM, Gerd Stolpmann wrote: > > Hi, > > > > thanks for the patch. If I don't find another solution, I'll apply it. > > > > Currently, I'm revising SSL anyway - OCamlnet 4.0 will have its own > > binding for GnuTLS, and this will give us a lot more freedom in the > > design. In particular, the management of the TCP connection and the TLS > > tunnel can be completely decoupled (i.e. TLS will appear as a separate > > layer on top of the multiplex controller). > > > > (If you are curious: > > https://godirepo.camlcity.org/wwwsvn/branches/onet4/code/src/nettls-gnutls/?root=lib-ocamlnet2) > > Interesting, does this mean that an application could choose between OpenSSL and GnuTLS by simply > linking with nettls.gnutls vs nettls.openssl? [*] > > [*] Or why not someone could contribute a nettls.nss, as Fedora seems to prefer it over GnuTLS (Debian > on the other hand seems to default to GnuTLS in curl for example): > https://fedoraproject.org/wiki/FedoraCryptoConsolidation There will be just a module type TLS_provider that can be packed as value and passed around, and it will be possible to have several implementations for it (switchable even at runtime). GnuTLS serves "only" as the implementation that is included. I don't know yet whether I personally want to create another one - the existing binding for OpenSSL is so minimal that it is hardly usable for anything else than a simple client, so it would be some work to add all the missing functionality. But if somebody else did it, I'd happily include it in Ocamlnet. Same for NSS (which is probably easier to do). Independently of the TLS implementation, there will also be a parser for X.509 certificates. This is already written (directly in OCaml), and will give you complete access to all the details. Gerd > Best regards, > --Edwin > > -- ------------------------------------------------------------ Gerd Stolpmann, Darmstadt, Germany ge...@ge... Creator of GODI and camlcity.org. Contact details: http://www.camlcity.org/contact.html Company homepage: http://www.gerd-stolpmann.de ------------------------------------------------------------ |
From: Gerd S. <in...@ge...> - 2013-10-01 14:27:01
Attachments:
signature.asc
|
Hi, I finally fixed this problem the clean way, namely by storing the SSL socket in the connection cache. This solution is now committed to trunk. Gerd Am Samstag, den 21.09.2013, 22:58 +0300 schrieb Török Edwin: > Hi, > > Attached patch implements a workaround to allow persistent connections to work with HTTPS, > avoiding bugs in Https_client#continue. See below for the long explanation. > > Persistent HTTP connections work if I enable the aggressive connection cache with Http_client. > However with Https_client I noticed that it always closed and reopened the Ssl connections. > While this doesn't influence the application's correctness (thanks to the retry mechanisms in Http_client!), it heavily influences its performance: the latency is very bad due to repeated reopened connections, and repeated SSL handshakes ... even on localhost. > > Enabling Netlog debugging showed that some Ssl exceptions were thrown each time around read/write/shutdown after the 1st query completed. Further investigation revealed that the problem might be with Https_client#continue: > > method continue fd cb tmo tmo_x host port esys = > - let mplex = > - Uq_ssl.create_ssl_multiplex_controller > - ~close_inactive_descr:true > - ~preclose:(preclose fd) > - ~initial_state:`Client > - ~timeout:(tmo, tmo_x) > - fd ctx esys in > - (mplex :> Uq_engines.multiplex_controller) > > Problems with this code: > * creating a new ssl multiplex controller will create a new Ssl.socket (and share just the Ssl.context and fd). > * the new Ssl.socket doesn't have a defined state (SSL_set_connected_state was not called, and there was no prior handshake either), causing further operations on it to raise errors (if I add some debugging code > to Uq_ssl to print Ssl.get_error_string): > [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL write error: error:140D0114:SSL routines:SSL_write:uninitialized > [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL read error: error:140DF114:SSL routines:SSL_read:uninitialized > [Thu Sep 19 14:57:29 2013] [debug] [7534:11] Uq_ssl: SSL shutdown error: error:140E0114:SSL routines:SSL_shutdown:uninitialized > * the new Ssl.socket is probably missing the state of the handshake (session keys, etc.) > > > The attached workaround implements a very simple workaround: if the esys is still the same > just reuse the previous multiplex controller, I'm guessing this is what the Hashtbl was meant for anyway. > > A better solution would be to have something like create_ssl_multiplex_controller_for_existing_session that would take the existing Ssl.socket instead of creating a new one, and then Https_client#continue wouldn't have to drop the connection if esys or tmo changes. > > Best regards, > --Edwin > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/22/13. > http://pubads.g.doubleclick.net/gampad/clk?id=64545871&iu=/4140/ostg.clktrk > _______________________________________________ Ocamlnet-devel mailing list Oca...@li... https://lists.sourceforge.net/lists/listinfo/ocamlnet-devel -- ------------------------------------------------------------ Gerd Stolpmann, Darmstadt, Germany ge...@ge... My OCaml site: http://www.camlcity.org Contact details: http://www.camlcity.org/contact.html Company homepage: http://www.gerd-stolpmann.de ------------------------------------------------------------ |