Project

General

Profile

[Solved] Lighttpd multiple SSL hosts using Server Name Indication (SNI)

Added by paullylittlefield over 4 years ago

Hello Folks,

My first post, so be gentle :-)

I have the latest version installed and have followed these official instructions...

https://redmine.lighttpd.net/projects/1/wiki/Docs_SSL#Server-Name-Indication-SNI

...but my server refuses to use the correct SSL certificate for each host.

It appears to be ignoring the $HTTP["host"] setting and offering the default SSL certificate instead.

If I test my config by viewing the non-https version of the web site it works and loads the correct document root page.

I have also tested all the config files with the official command...

lighttpd -t -f /etc/lighttpd/lighttpd.conf -p

...which shows Syntax OK.

Here is an extract of the config (with the domain names changed):-

==> /etc/lighttpd/lighttpd.conf <==

$SERVER["socket"] == ":443" {
    ssl.engine  = "enable" 
    ssl.pemfile = "/etc/lighttpd/domain1_com.pem" 
    ssl.ca-file = "/etc/lighttpd/domain1_com.ca-bundle" 
    ssl.dh-file = "/etc/ssl/certs/dhparam.pem" 
    ssl.ec-curve = "secp384r1" 
    ssl.use-sslv2 = "disable" 
    ssl.use-sslv3 = "disable" 
    ssl.cipher-list = "HIGH" 
    $HTTP["host"] == "www.domain2.com" {
      ssl.pemfile = "/etc/lighttpd/domain2_com.pem" 
      ssl.ca-file = "/etc/lighttpd/domain2_com.ca-bundle" 
    }
    $HTTP["host"] == "www.domain3.com" {
      ssl.pemfile = "/etc/lighttpd/domain3_com.pem" 
      ssl.ca-file = "/etc/lighttpd/domain3_com.ca-bundle" 
    }
}

==> /etc/lighttpd/domain2.com.conf <==

$HTTP["scheme"] == "http" {
  $HTTP["host"] == "domain2.com" {
    url.redirect = ( ".*" => "https://www.domain2.com/$1" )
    url.redirect-code = 301
  }
  $HTTP["host"] == "www.domain2.com" {
    url.redirect = ( ".*" => "https://www.domain2.com/$1" )
    url.redirect-code = 301
  }
}

$HTTP["scheme"] == "https" {
  $HTTP["host"] == "domain2.com" {
    url.redirect = ( ".*" => "https://www.domain2.com/$1" )
    url.redirect-code = 301
  }
  $HTTP["host"] == "www.domain2.com" {
    server.name = "www.domain2.com" 
    server.document-root = "/var/www/www.domain2.com/html" 
    accesslog.filename = "/var/www/www.domain2.com/logs/access.log" 
    url.rewrite-if-not-file = ( "^/(wp-.+).*/?" => "$0", "^/keyword/([A-Za-z_0-9\-]+)/?$" => "/index.php?keyword=$1", "^/.*?(\?.*)?$" => "/index.php$1" )
  }
}

Can anyone help?

Thanks,

Paully


Replies (29)

RE: Lighttpd multiple SSL hosts using Server Name Indication (SNI) - Added by paullylittlefield about 4 years ago

So, maybe it's the "non focal" SSL libraries that are causing a problem.

The sury PPA wants to install versions that match the PHP software he has compiled and installs.

e.g.

apt-cache policy libssl-dev
libssl-dev:
  Installed: 1.1.1j-1+ubuntu20.04.1+deb.sury.org+3
  Candidate: 1.1.1j-1+ubuntu20.04.1+deb.sury.org+3
  Version table:
 *** 1.1.1j-1+ubuntu20.04.1+deb.sury.org+3 500
        500 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 Packages
        100 /var/lib/dpkg/status
     1.1.1f-1ubuntu2.2 500
        500 http://eu-west-2.ec2.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages
        500 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages
     1.1.1f-1ubuntu2 500
        500 http://eu-west-2.ec2.archive.ubuntu.com/ubuntu focal/main amd64 Packages

So, in each case, could I install the 'focal' version and lock that?

e.g.

sudo apt-get install libssl-dev=1.1.1f-1ubuntu2.2
sudo apt-mark hold libssl-dev

Then try again?

Paully

RE: Lighttpd multiple SSL hosts using Server Name Indication (SNI) - Added by paullylittlefield about 4 years ago

OK, so I bit the bullet and swapped the Sury PPA SSL Libraries for the 'focal' ones...

apt-get install libssl1.1=1.1.1f-1ubuntu2.2 libssl-dev=1.1.1f-1ubuntu2.2 openssl=1.1.1f-1ubuntu2.2

...and rebooted the server to be sure.

I then cleaned and recompiled 1.4.59 and used gdb run.

It crashed and burned with exactly the same error and complained about /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ...

0x00007ffff7a0720e in mod_openssl_cert_cb (ssl=0x555555707340, arg=<optimized out>) at mod_openssl.c:1058
1058        if (NULL == pc->ssl_pemfile_x509 || NULL == pc->ssl_pemfile_pkey) {
(gdb) bt full
#0  0x00007ffff7a0720e in mod_openssl_cert_cb (ssl=0x555555707340, arg=<optimized out>) at mod_openssl.c:1058
        hctx = 0x555555707280
        pc = 0x0
#1  0x00007ffff79c1c45 in ?? () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
No symbol table info available.
#2  0x00007ffff79b12cf in ?? () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
No symbol table info available.
#3  0x00007ffff7988886 in ?? () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
No symbol table info available.
#4  0x00007ffff798fc45 in ?? () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
No symbol table info available.
#5  0x00007ffff799aa1f in ?? () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
No symbol table info available.
#6  0x00007ffff799ab27 in SSL_read () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
No symbol table info available.

So, I'm lost and all out of ideas... well, maybe NginX but that's my last resort!

:-(

Help please.

Paully

RE: Lighttpd multiple SSL hosts using Server Name Indication (SNI) - Added by gstrauss about 4 years ago

(gdb) bt full
#0  0x00007ffff7a0720e in mod_openssl_cert_cb (ssl=0x5555557075f0, arg=<optimized out>) at mod_openssl.c:1058
        hctx = 0x555555707580
        pc = 0x0

For some reason yet to be determined, the openssl routine to retrieve application data (stored by lighttpd) is returning a lighttpd handler context (hctx), and insided the lighttpd handler context, hctx->conf.pc is NULL for lighttpd's configured (plugin_cert *) (pc). This should not happen since lighttpd tries to ensure that you have configured certificates whenever ssl.engine = "enable".

While lighttpd should not crash, the root cause of your issue is almost guaranteed to be somewhere in your configuration.

However, you have never provided your full, actual config (lighttpd -p -f /etc/lighttpd/lighttpd.conf)

As a guess, please test what happens if you configure your certificates as recommended in lighttpd TLS docs

      ssl.pemfile = "/etc/lighttpd/domain1_fullchain.pem" 
      ssl.privkey = "/etc/lighttpd/domain1_privkey.pem" 

where the full certificate chain is in domain1_fullchain.pem and the private key is in domain1_privkey.pem.

If you compile lighttpd 1.4.59 with the following patch, then instead of crashing, you should get error trace SSL: no certificate/private key for TLS server name ... and that might help you find what is wrong in your lighttpd config.

--- a/src/mod_openssl.c
+++ b/src/mod_openssl.c
@@ -1055,7 +1055,7 @@ mod_openssl_cert_cb (SSL *ssl, void *arg)
     UNUSED(arg);
     if (hctx->alpn == MOD_OPENSSL_ALPN_ACME_TLS_1) return 1;

-    if (NULL == pc->ssl_pemfile_x509 || NULL == pc->ssl_pemfile_pkey) {
+    if (!pc || NULL == pc->ssl_pemfile_x509 || NULL == pc->ssl_pemfile_pkey) {
         /* x509/pkey available <=> pemfile was set <=> pemfile got patched:
          * so this should never happen, unless you nest $SERVER["socket"] */
         log_error(hctx->r->conf.errh, __FILE__, __LINE__,

RE: Lighttpd multiple SSL hosts using Server Name Indication (SNI) - Added by gstrauss about 4 years ago

You might note the comment in the code:

         /* x509/pkey available <=> pemfile was set <=> pemfile got patched:
          * so this should never happen, unless you nest $SERVER["socket"] */

I see that this might have previously happened to work for you with lighttpd 1.4.55, but nesting $SERVER["socket"] is wrong and has always been wrong. ...It is possibly the reason why SNI was not working for you with lighttpd 1.4.55.

This is called out in lighttpd TLS docs:

Note: ssl.* configuration options are generally valid only in global scope or in the top level of a $SERVER["socket"] configuration condition, as they are needed when the socket connection is established, before the host is known. In cases where the client adds SNI (server name indication), some ssl.* options can be specified in $HTTP["host"] or $HTTP["scheme"] conditions, e.g. to select certificates for that specific connection. All other conditions occur after TLS negotiation has completed, so ssl.* directives nested in other configuration conditions may be ignored, including $SERVER["socket"] or $HTTP["host"] or $HTTP["scheme"] nested in other configuration conditions.

(26-29/29)