if($usessl) { my $defaultdomain = $self->{config}->{sslconfig}->{ssldefaultdomain}; my $encrypted; my $ok = 0; eval { $encrypted = IO::Socket::SSL->start_SSL($client, SSL_server => 1, SSL_key_file=> $self->{config}->{sslconfig}->{ssldomains}->{$defaultdomain}->{sslkey}, SSL_cert_file=> $self->{config}->{sslconfig}->{ssldomains}->{$defaultdomain}->{sslcert}, SSL_cipher_list => $self->{config}->{sslconfig}->{sslciphers}, SSL_create_ctx_callback => sub { my $ctx = shift; #print STDERR "******************* CREATING NEW CONTEXT ********************\n"; # Enable workarounds for broken clients Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); # Disable session resumption completely Net::SSLeay::CTX_set_session_cache_mode($ctx, $SSL_SESS_CACHE_OFF); # Disable session tickets Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_NO_TICKET); # Load certificate chain my $defaultdomain = $self->{config}->{sslconfig}->{ssldefaultdomain}; Net::SSLeay::CTX_use_certificate_chain_file($ctx, $self->{config}->{sslconfig}->{ssldomains}->{$defaultdomain}->{sslcert}); # Check requested server name Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, sub { my $ssl = shift; my $h = Net::SSLeay::get_servername($ssl); if(!defined($h)) { #print STDERR "SSL: No Hostname given during SSL setup\n"; return; } if(!defined($self->{config}->{sslconfig}->{ssldomains}->{$h})) { #print STDERR "SSL: Hostname $h not configured\n"; #print STDERR Dumper($self->{config}->{sslconfig}->{ssldomains}); return; } if(defined($self->{config}->{sslconfig}->{ssldomains}->{$h}->{internal_socket})) { # This SSL connection uses a different backend $selectedbackend = $self->{config}->{sslconfig}->{ssldomains}->{$h}->{internal_socket}; } if($h eq $self->{config}->{sslconfig}->{ssldefaultdomain}) { # Already the correct CTX setting, just return return; } #print STDERR "§§§§§§§§§§§§§§§§§§§§§§§ Requested Hostname: $h §§§\n"; my $newctx; if(defined($self->{config}->{sslconfig}->{ssldomains}->{$h}->{ctx})) { $newctx = $self->{config}->{sslconfig}->{ssldomains}->{$h}->{ctx}; } else { $newctx = Net::SSLeay::CTX_new or croak("Can't create new SSL CTX"); Net::SSLeay::CTX_set_cipher_list($newctx, $self->{config}->{sslconfig}->{sslciphers}); Net::SSLeay::set_cert_and_key($newctx, $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslcert}, $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslkey}) or croak("Can't set cert and key file"); Net::SSLeay::CTX_use_certificate_chain_file($newctx, $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslcert}); #print STDERR "Cert: ", $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslcert}, " Key: ", $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslkey}, "\n"; $self->{config}->{sslconfig}->{ssldomains}->{$h}->{ctx} = $newctx; } Net::SSLeay::set_SSL_CTX($ssl, $newctx); }); # Prepared/tested for future ALPN needs (e.g. HTTP/2) ## Advertise supported HTTP versions #Net::SSLeay::CTX_set_alpn_select_cb($ctx, ['http/1.1', 'http/2.0']); }, ); $ok = 1; }; if(!$ok) { print "EVAL ERROR: ", $EVAL_ERROR, "\n"; $self->endprogram(); } elsif(!$ok || !defined($encrypted) || !$encrypted) { print "startSSL failed: ", $SSL_ERROR, "\n"; $self->endprogram(); } } #### # Enable workarounds for broken clients Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); # Disable session resumption completely Net::SSLeay::CTX_set_session_cache_mode($ctx, $SSL_SESS_CACHE_OFF); # Disable session tickets Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_NO_TICKET); #### Net::SSLeay::CTX_use_certificate_chain_file($ctx, $self->{config}->{sslconfig}->{ssldomains}->{$defaultdomain}->{sslcert}); #### Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, sub { my $ssl = shift; my $h = Net::SSLeay::get_servername($ssl); if(!defined($h)) { #print STDERR "SSL: No Hostname given during SSL setup\n"; return; } ... # ---- THIS SELECTS THE CORRECT BACKEND ----- if(defined($self->{config}->{sslconfig}->{ssldomains}->{$h}->{internal_socket})) { # This SSL connection uses a different backend $selectedbackend = $self->{config}->{sslconfig}->{ssldomains}->{$h}->{internal_socket}; } if($h eq $self->{config}->{sslconfig}->{ssldefaultdomain}) { # Already the correct CTX setting, just return return; } ... # Switch over to the new certificate key and chain $newctx = Net::SSLeay::CTX_new or croak("Can't create new SSL CTX"); Net::SSLeay::CTX_set_cipher_list($newctx, $self->{config}->{sslconfig}->{sslciphers}); Net::SSLeay::set_cert_and_key($newctx, $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslcert}, $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslkey}) or croak("Can't set cert and key file"); Net::SSLeay::CTX_use_certificate_chain_file($newctx, $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslcert}); #print STDERR "Cert: ", $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslcert}, " Key: ", $self->{config}->{sslconfig}->{ssldomains}->{$h}->{sslkey}, "\n"; $self->{config}->{sslconfig}->{ssldomains}->{$h}->{ctx} = $newctx; } Net::SSLeay::set_SSL_CTX($ssl, $newctx); }); ... },