Automatic Let’s Encrypt certificates in Apache with mod_md

Since 2.4.30, Apache comes with experimental support for ACME certificates (Let’s Encrypt et al.) in the form of mod_md (short for “managed domains”). It’s kind of a pain but it’s still better than what I had before, i.e. a mess of shell and Perl scripts based on Crypt::LE, and if your use case is limited to Apache, it appears to be simpler than Certbot as well. Unfortunately for me, it’s not very well documented and I wasted a considerable amount of time figuring out how to use it. Fortunately for you, I then decided to blog about it so you don’t have to repeat my mistakes.

Edit: the author of mod_md, Stefan Eissing, got in touch and pointed me to his own documentation, which is far superior to the one available from Apache.

Continue reading “Automatic Let’s Encrypt certificates in Apache with mod_md” »

Configuring strict SNI with Apache httpd 2.4

Imagine the following scenario:

  1. Your web server hosts both www.example.com and www.example.net using Apache httpd with name-based virtual hosts, and the configuration is structured such that httpd sees the former before the latter. Each vhost has its own non-wildcard certificate.
  2. A user tries to access www.example.net using an old browser which does not support SNI.
  3. Since httpd cannot see the Host header without first performing a TLS handshake, and cannot perform a TLS handshake without a key and certificate, it needs to pick one blindly. In accordance with its virtual host matching algorithm, it defaults to the first configured vhost, i.e. www.example.com.
  4. The browser receives a certificate wit a CN which does not match the name of the host it is trying to access, and either throws up a scary warning or simply refuses to connect.

You might say that this acceptable — after all, it only affects a minuscule proportion of users using very old clients — but TLS validators such as Qualys SSL labs have started testing non-SNI requests, and while they don’t yet penalize servers for this issue, they might very well start doing so soon.

Apache httpd has an option called SSLStrictSNIVHostCheck which, in theory, should take care of this. But I haven’t had much luck with it (to put it bluntly: it does not seem to have any effect at all), and it appears from various discussions on Reddit, StackExchange, etc. that I am not alone. The solution I have found is to create a dummy vhost with a dummy, self-signed certificate, and ensure that it is loaded first.

The first step is to create a dummy certificate for localhost with a 100-year lifespan (unless you feel like setting up a cron job that regenerates a 90-day certificate every 30 days or so):

$ openssl genrsa -out localhost.key 2048
$ openssl req -new -key localhost.key -subj /CN=localhost -out localhost.csr
$ echo subjectAltName=DNS:localhost | openssl x509 \
    -in localhost.csr -out localhost.crt -req -signkey localhost.key -days 36525 -extfile -

Next, create a vhost configuration which uses that certificate:

<VirtualHost *:443>
  ServerName localhost
  SSLEngine On
  SSLStrictSNIVHostCheck On
  SSLCertificateKeyFile /path/to/localhost.key
  SSLCertificateFile /path/to/localhost.crt
  <Location />
    Require all denied
  </Location>
</VirtualHost>

This must be placed in a location where it will be read before any other vhost configuration, e.g. 00localhost.conf in your server’s Includes directory.

TLS connections without a server name will now be directed to your dummy vhost and fail, and Qualys will report that any site hosted on your server “works only in browsers with SNI support”.

As a footnote, my TLS configuration (derived from the Mozilla project’s recommendations) looks like this:

SSLProtocol +TLSv1.3 +TLSv1.2
SSLCipherSuite TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLCompression off

Between that, strict SNI, HSTS, and CAA, you will easily achieve an A+ score.

wtf, zsh

wtf, zsh

wtf, zsh

% uname -sr
FreeBSD 12.1-RELEASE-p10
% for sh in sh csh bash zsh ; do printf "%-8s" $sh ; $sh -c 'echo \\x21' ; done 
sh      \x21
csh     \x21
bash    \x21
zsh     !
% cowsay wtf, zsh       
 __________ 
< wtf, zsh >
 ---------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

I mean. Bruh. I know it’s intentional & documented & can be turned off, but every other shell defaults to POSIX semantics…

BTW:

% ln -s =zsh /tmp/sh
% /tmp/sh -c 'echo \x21'
\x21

Netlink, auditing, and counting bytes

In which we find bugs in both the kernel and userspace parts of the Linux audit subsystem.

I’ve been messing around with Linux auditing lately, because of reasons, and ended up having to replicate most of libaudit, because of other reasons, and in the process I found bugs in both the kernel and userspace parts of the Linux audit subsystem.

Continue reading “Netlink, auditing, and counting bytes” »

On dinosaurs and context

Some of you may know that the 2020 Hugo Award ceremony was held last night¹ and that it was hosted by George R. R. Martin. Some of you may have heard that it did not go well. Some of you may already know what happened, more or less. I watched it live, and unsurprisingly, I have opinions.

This post is not a blow-by-blow account of events or any sort of clever analysis or deep thoughts on how to move forward. Better minds than mine have already taken care of that; see for instance Natalie Luhrs’s take on the affair. Instead, I would like to offer a little bit of context for those who heard what happened (or watched it happen) and have a vague idea that it was bad but do not understand why everybody is so upset and do not want to jump down the rabbit hole of SFF fandom drama.

Continue reading “On dinosaurs and context” »