From 8574c70d6b7e0dc274a6dbbe755bd6a0ba0ec4ac Mon Sep 17 00:00:00 2001 From: bob7123 Date: Tue, 16 Jun 2026 16:18:12 +0000 Subject: [PATCH 1/2] Register SNI callback on all SSL contexts, not just the default setup_ssl_contexts() registers CTX_set_tlsext_servername_callback only on the default (*) context. Per-IP contexts from ipcert entries do not get the callback. When a client connects to a dedicated IP, the per-IP context is used directly, the SNI callback never fires, and the wrong certificate is served regardless of the requested hostname. Fix: register the same SNI callback on every context in %ssl_contexts. The callback function is unchanged. Clients without SNI still receive the per-IP certificate. Clients with SNI get the correct certificate matched by hostname. Related: https://github.com/virtualmin/virtualmin-gpl/pull/1229 Co-Authored-By: Claude Opus 4.6 (1M context) --- miniserv.pl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/miniserv.pl b/miniserv.pl index 72cdce74f..a4d65dd08 100755 --- a/miniserv.pl +++ b/miniserv.pl @@ -4823,10 +4823,12 @@ foreach my $ip (keys %ssl_contexts) { } } -# Setup per-hostname SSL contexts on the main IP +# Setup per-hostname SSL contexts on all IPs, not just the default +# Ref: https://github.com/virtualmin/virtualmin-gpl/pull/1229 if (defined(&Net::SSLeay::CTX_set_tlsext_servername_callback)) { + foreach my $ctx_key (keys %ssl_contexts) { Net::SSLeay::CTX_set_tlsext_servername_callback( - $ssl_contexts{"*"}->{'ctx'}, + $ssl_contexts{$ctx_key}->{'ctx'}, sub { my $ssl = shift; my $h = Net::SSLeay::get_servername($ssl); @@ -4837,6 +4839,7 @@ if (defined(&Net::SSLeay::CTX_set_tlsext_servername_callback)) { } }); } + } return undef; } From 74bd78ae353fa8977135c8b310d9b079b1470998 Mon Sep 17 00:00:00 2001 From: bob7123 Date: Thu, 18 Jun 2026 08:23:45 +0000 Subject: [PATCH 2/2] Fix indentation inside foreach loop per review --- miniserv.pl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/miniserv.pl b/miniserv.pl index a4d65dd08..698da3a60 100755 --- a/miniserv.pl +++ b/miniserv.pl @@ -4827,18 +4827,18 @@ foreach my $ip (keys %ssl_contexts) { # Ref: https://github.com/virtualmin/virtualmin-gpl/pull/1229 if (defined(&Net::SSLeay::CTX_set_tlsext_servername_callback)) { foreach my $ctx_key (keys %ssl_contexts) { - Net::SSLeay::CTX_set_tlsext_servername_callback( - $ssl_contexts{$ctx_key}->{'ctx'}, - sub { - my $ssl = shift; - my $h = Net::SSLeay::get_servername($ssl); - my $c = $ssl_contexts{$h} || - $h =~ /^[^\.]+\.(.*)$/ && $ssl_contexts{"*.$1"}; - if ($c) { - Net::SSLeay::set_SSL_CTX($ssl, $c->{'ctx'}); - } - }); - } + Net::SSLeay::CTX_set_tlsext_servername_callback( + $ssl_contexts{$ctx_key}->{'ctx'}, + sub { + my $ssl = shift; + my $h = Net::SSLeay::get_servername($ssl); + my $c = $ssl_contexts{$h} || + $h =~ /^[^\.]+\.(.*)$/ && $ssl_contexts{"*.$1"}; + if ($c) { + Net::SSLeay::set_SSL_CTX($ssl, $c->{'ctx'}); + } + }); + } } return undef; }