Apache with LibreSSL


We are going to build Apache with LibreSSL.

We will also attempt to score an A+ with 100/100/100/100 points on the Qualys SSL Labs Server Test.

We assume we have
1.   Ubuntu Server 14.04 with httpd-2.4.12 from ppa:ondrej/apache2.
2.   A working, running Apache configuration.
3.   At least one SSL-enabled VirtualHost with a valid SSL certificate.

DISCLAIMER: I’m not in any way responsible for any damage to your system and/or configuration which may result from following this text. It it assumed that you have the knowledge how to restore things back to their original state and that you make backups.

Getting the files

Let’s grab all the necessary files and unpack them in our homedir :

$ cd ~
$ wget http://apache.hippo.nl/httpd/httpd-2.4.12.tar.gz
$ tar zxvf httpd-2.4.12.tar.gz
$ cd httpd-2.4.12/srclib
$ wget http://ftp.nluug.nl/internet/apache/apr/apr-1.5.1.tar.gz
$ wget http://ftp.nluug.nl/internet/apache/apr/apr-util-1.5.4.tar.gz
$ tar zxvf apr-1.5.1.tar.gz
$ tar zxvf apr-util-1.5.4.tar.gz
$ ln -s apr-1.5.1 apr
$ ln -s apt-util-1.5.4 apr-util
$ cd ~ && wget http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.1.6.tar.gz
$ tar zxvf libressl-2.1.6.tar.gz

Installing LibreSSL

We will not replace the system’s default OpenSSL.
We will just install it in /opt/libressl-2.1.6 :

$ cd ~
$ cd libressl-2.1.6
$ ./configure --prefix=/opt/libressl-2.1.6 --exec-prefix=/opt/libressl-2.1.6
$ make -j3
$ sudo make install

Patching Apache for LibreSSL

Now we partly apply the following patch to Apache’s mod_ssl source :

--- a/modules/ssl/ssl_engine_init.c 2014-07-15 18:48:00.382044224 +0200
+++ b/modules/ssl/ssl_engine_init.c 2015-03-28 18:48:35.452335112 +0100
@@ -275,9 +275,11 @@ apr_status_t ssl_init_Engine(server_rec
             return ssl_die(s);
         }
 
+#ifdef ENGINE_CTRL_CHIL_SET_FORKCHECK
         if (strEQ(mc->szCryptoDevice, "chil")) {
             ENGINE_ctrl(e, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0);
         }
+#endif
 
         if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
             ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01889)
--- a/modules/ssl/ssl_engine_rand.c 2014-07-15 18:49:13.853653603 +0200
+++ b/modules/ssl/ssl_engine_rand.c 2015-03-28 18:49:49.180946663 +0100
@@ -86,9 +86,11 @@ int ssl_rand_seed(server_rec *s, apr_poo
                  * seed in contents provided by the external
                  * Entropy Gathering Daemon (EGD)
                  */
+#ifdef HAVE_SSL_RAND_EGD
                 if ((n = RAND_egd(pRandSeed->cpPath)) == -1)
                     continue;
                 nDone += n;
+#endif
             }
             else if (pRandSeed->nSrc == SSL_RSSRC_BUILTIN) {
                 struct {

Now we apply this patch to fix a small memory leak. We adjust it slightly, to change the default EC curve from prime256v1 to brainpoolP384t1 :

--- a/modules/ssl/ssl_engine_init.c Fri Mar 13 07:32:46 2015
+++ b/modules/ssl/ssl_engine_init.c Fri Mar 29 13:32:46 2015
@@ -982,7 +982,7 @@ static apr_status_t ssl_init_server_cert
 #ifdef HAVE_ECC
     EC_GROUP *ecparams;
     int nid;
-    EC_KEY *eckey;
+    EC_KEY *eckey = NULL;
 #endif
 #ifndef HAVE_SSL_CONF_CMD
     SSL *ssl;
@@ -1151,10 +1151,11 @@ static apr_status_t ssl_init_server_cert
 #if defined(SSL_CTX_set_ecdh_auto)
         SSL_CTX_set_ecdh_auto(mctx->ssl_ctx, 1);
 #else
-        SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx,
-                             EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+        eckey = EC_KEY_new_by_curve_name(NID_brainpoolP384t1);
+        SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
 #endif
     }
+    EC_KEY_free(eckey);
 #endif
 
     return APR_SUCCESS;

Also – not at all necessary but it does look nicer – let’s change the string for SSL_LIBRARY_NAME to LibreSSL :

--- a/modules/ssl/ssl_util_ssl.h 2015-03-28 13:55:14.518443044 +0200
+++ b/modules/ssl/ssl_util_ssl.h 2015-03-29 13:02:08.450443044 +0100
@@ -39,7 +39,7 @@
 */
 
 #define SSL_LIBRARY_VERSION OPENSSL_VERSION_NUMBER
-#define SSL_LIBRARY_NAME "OpenSSL"
+#define SSL_LIBRARY_NAME "LibreSSL"
 #define SSL_LIBRARY_TEXT OPENSSL_VERSION_TEXT
 #define SSL_LIBRARY_DYNTEXT SSLeay_version(SSLEAY_VERSION)

Building Apache

WARNINGIn this example we are replacing the system’s default Apache !!!

If you do not want this, use –prefix=/opt/httpd (or some other path) in the ./configure line. I like it this way, because it allows me to continue using the regular service start/stop scripts without changing anything.

For any additional modules you want to use, you generally have to extract them to your Apache source directory manually and add –enable-modname (like for example –enable-fcgid) to the configure line. See the Apache documentation for more info.

Now we build Apache :

$ cd ~
$ cd httpd-2.4.12
$ ./configure --with-included-apr --enable-ssl --with-ssl=/opt/libressl-2.1.6 --with-crypto --enable-mpms-shared
$ make -j3
$ sudo service apache2 stop
$ sudo make install

In Ubuntu Server 14.04, Apache’s modules live in /usr/lib/apache2/modules. The *.load files in /etc/apache2/mods-available still link to the module files in that default directory. Let’s change all of these *.load files, to link them to the newly installed ones in /usr/local/apache2/modules :

$ cd /etc/apache2/mods-available
$ sudo sed -i 's|/usr/lib/apache2/modules|/usr/local/apache2/modules|g' *.load

If Apache complains about missing modules later when you start it, you could copy the missing modules over manually (but they were built against the system’s default Apache, it’s not a good idea) or compile them during the above procedure.

Now start Apache :

sudo service apache2 start

If all went well, you’ll find something similar to this in your log :

[mpm_prefork:notice] [pid 19325] AH00163: Apache/2.4.12 (Ubuntu) mod_fcgid/2.3.9 LibreSSL/2.1.6 configured -- resuming normal operations

Apache configuration

We will only use TLS 1.2 with 256-bit ciphersuites and either ECDHE or DHE. We explicitly disable the stuff we don’t want or need.

/etc/apache2/mods-enabled/ssl.conf :

<IfModule mod_ssl.c>
   # Other stuff
   # ...
   SSLProtocol -All +TLSv1.2
   SSLHonorCipherOrder on
   # LibreSSL can't do SSL compression by default.
   #SSLCompression Off
   SSLCipherSuite "ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-CAMELLIA256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:!aNULL:!eNULL:!NULL:!EXPORT:!MEDIUM:!LOW:!DES:!RC4:!3DES:!MD5:!SEED:!PSK:!ADH:!DSS"
   # ...
   # Other stuff
</IfModule>

/etc/apache2/conf-enabled/security.conf :

# Other stuff
# ...
ServerTokens Prod
ServerSignature Off
Header set X-Content-Type-Options: "nosniff"
Header set X-Frame-Options: "sameorigin"
Header set X-XSS-Protection: "1; mode=block"
# ...
# Other stuff

If you don’t want to hide version numbers replace the first line above with :

ServerTokens Full

Use these tutorials to set up HPKP, HSTS and OSCP Stapling :

HPKP
https://raymii.org/s/articles/HTTP_Public_Key_Pinning_Extension_HPKP.html

OSCP Stapling
https://support.globalsign.com/customer/portal/articles/1642333-apache—enable-ocsp-stapling

HSTS
https://raymii.org/s/tutorials/HTTP_Strict_Transport_Security_for_Apache_NGINX_and_Lighttpd.html

Testing the server

Now let’s test our Apache server with the Qualys® SSL Labs Server Test :

SSL Report: dorianharmans.nl

If you’re using ServerTokens Full it will mention that LibreSSL is being used :

HTTP server signature

This text was originally posted here.