in reply to Re: Dynamic SNI certificates while upgrading to SSL
in thread Dynamic SNI certificates while upgrading to SSL

thanks for this!

according to CPAN

http://search.cpan.org/~mikem/Net-SSLeay-1.66/lib/Net/SSLeay.pod#Low_level_API:_Server_side_Server_Name_Indication_%28SNI%29_support

the goal can be reached with code like this:

# create default context my $ctx = Net::SSLeay::CTX_new or die; Net::SSLeay::CTX_set_cipher_list($ctx, 'ALL'); Net::SSLeay::set_cert_and_key($ctx, 'cert.pem','key.pem') or die; # create new context for each new hostname my %hostnames = (); Net::SSLeay::CTX_set_tlsext_servername_callback( $ctx, sub { my $ssl = shift; my $h = Net::SSLeay::get_servername($ssl); unless (exists $hostnames{$h}) { $hostnames{$h}->{ctx} = Net::SSLeay::CTX_new or die; Net::SSLeay::CTX_set_cipher_list($hostnames{$h}->{ctx}, 'A +LL'); $hostnames{$h}->{cert} = ... # generate certificate and $hostnames{$h}->{key} = ... # key based on hostname in $h # and re-use them in future f +rom hash as below Net::SSLeay::set_cert_and_key( $hostnames{$h}->{ctx}, $hostnames{$h}->{cert}, $hostnames{$h}->{key} ) or die; } Net::SSLeay::set_SSL_CTX($ssl, $hostnames{$h}->{ctx}); } );

but every new cert/key pair generation will use some time.
in my case, the script is a multiplexing server based on IO::Select, so it reads and writes with short parts of data to prevent any long/heavy transfer to block the others.
and each time the new pair is generated the script will block for this time.

is there a way to solve this in non-blocking manner?

thanks!

Replies are listed 'Best First'.
Re^3: Dynamic SNI certificates while upgrading to SSL
by noxxi (Pilgrim) on Jan 03, 2015 at 19:45 UTC
    > is there a way to solve this in non-blocking manner?

    I don't think so. To do this in a sensible non-blocking way you would need to have control about the SSL state machine. But OpenSSL only exposes some hooks into this machine with callbacks and I don't think you can have multiple servername callbacks on the same context run in parallel.

      and what if i detach (maybe fork) this process from the main one?
      in such case, the problem is how to return the upgraded socket object from child to main one?

      i know, it sounds somewhat insane (in case of fork)...

      i'm not familiar with threads, however maybe it could help...
      i don't know.
      could it?

      thanks!

        I hope you don't mind me necroing this old topic but I solved the exact same problem successfully by forking the process this way:

        my $pid = open(my $pipe, "-|");

        In the child process I then upgrade the client socket to SSL, contact the server and relay data between the two. Whatever info I need to send back to the parent process I can just print to STDOUT. The parent process has a very tight main loop switching between accept()'ing new connections and using IO::Select to determine which $pipe sockets are ready for non-blocking reads.

        In another project of mine (not SSL related) I went a little further and established a plain two-way socket between the two processes and used non-blocking/select based sysread/syswrite on those as well. Non-blocking sockets between forked processes are actually a lot of fun :-)

        Admittedly, the forking model does have its limitations when it comes to scaling, but it's relatively simple to get up and running and I found it quite sufficient for doing simple traffic inspection.

        -- FloydATC

        I got 99 problems, most of them have to do with printers.

        > in such case, the problem is how to return the upgraded socket object from child to main one?

        Since SSL is a user-space layer on top of the kernel TCP socket there is no sane way to upgrade the socket to SSL in a child and then continue with the upgraded socket in the parent process.
        You might try with threads but the OpenSSL FAQ clearly states that a single SSL connection should not be used from within multiple threads at the same time. I'm not sure if this applies in this case too where you are using different SSL connections but the same SSL context object.