I finally found a way to sort of securely start using Let’s Encrypt on my servers. One of the reasons I have been hesitant about installing the official client, certbot, is because of some statements made by Theo de Raadt about the security of most clients of the ACME protocol (which is the protocol to talk to Let’s Encrypt). Installing certbot on Ubuntu 16.04 means adding more than 600.000 lines of Python and more than 400.000 lines of C to your installation, and that’s even without counting OpenSSL. Furthermore this code is meant to run periodically as root and touches the network. Oh the horror!
Of course with some extra effort it is possible to run certbot as a dedicated user with minimal privileges. But instead of using a monolithic program, I’d like to focus my energy on a tool that is made with security by design. One that nicely separates all the important parts from each other like code that touches the keys, from code that touches the file system. And code that touches the network, from the complex code that parses the X.509 certificates. Hence, this tutorial will be about installing acme-client (formerly known as letskencrypt), which is made by Kristaps Dzonsons.
Note: the major drawback about the solution presented here, is that you have to watch for updates yourself of both LibreSSL and acme-client. If there is an update to any of those, you have to redo the steps in this tutorial in order to apply the patches. Be warned.
Bring out the tools
First make sure you have a working compiler and package configuration tool installed. Furthermore ensure all required libraries for building the software are available. These tools are only needed in order to compile new versions of the software and are not required for running them.
There are different ways to verify your download, but all involve a trust anchor. Check with the LibreSSL community, like consulting the OpenBSD mirrors and mailing list archives to obtain valid hashes. You ideally do this from different computers using different networks. Never trust a single blog like this one. Furthermore you can Google on the checksums of the files you just downloaded and make sure that they show up at different reputable sites with dates long before now.
Assuming you have a trusted copy of LibreSSL, let’s compile the sources. Because we don’t want to install LibreSSL on the system and mix it up with the installed version of OpenSSL, we’re going to keep it in it’s own directory.
1
2
3
4
5
6
7
8
9
tim@ubuntu:~$ tar zxf libressl-2.5.0.tar.gz
tim@ubuntu:~$ LSSLP=$(pwd)/libressl-2.5.0 # save a pointer to this dir
Now you have a fresh new copy of LibreSSL which is ready to be used. Let’s move on to the final part, compiling acme-client. Luckily, this is not as time consuming as compiling LibreSSL.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
tim@ubuntu:~/libressl-2.5.0$ cd ..
tim@ubuntu:~$ tar zxf acme-client-portable.tgz
tim@ubuntu:~$ cd acme-client-portable-0.1.15/
tim@ubuntu:~/acme-client-portable-0.1.15$ CFLAGS="-I$LSSLP/include" LDFLAGS="-L$LSSLP/ssl/.libs -L$LSSLP/tls/.libs -L$LSSLP/crypto/.libs" make
tim@ubuntu:~/acme-client-portable-0.1.15$ sudo make install
mkdir -p /usr/local/man/man1
mkdir -p /usr/local/bin
install -m 0755 acme-client /usr/local/bin
install -m 0644 acme-client.1 /usr/local/man/man1
Symlink the trust CA store to a location acme-client expects and setup the base directories that will later hold the keys, certificates and chrooted processes.
With the binary in place, we’re ready to start requesting a new certificate. Say we’ve got Nginx running and it serves blog.netsend.nl, which is stored in /var/www/blog.netsend.nl/public/. The document root of your site, in this example /var/www /blog.netsend.nl/public, should contain a .well-known/acme-challenge directory.
acme-client: /etc/ssl/acme/blog.netsend.nl/chain.pem: created
acme-client: /etc/ssl/acme/blog.netsend.nl/cert.pem: created
acme-client: /etc/ssl/acme/blog.netsend.nl/fullchain.pem: created
Now configure your webserver to use the new certificate which is stored in /etc/ssl/acme/blog.netsend.nl/fullchain.pem and the key which is stored in /etc/ssl/acme/private/blog.netsend.nl/privkey.pem. See the documentation of your webserver for specific instructions. In Nginx this would be:
Restart your webserver and see if the new certificate is successfully served. Tip: use https://www.ssllabs.com/ssltest/ to test your SSL configuration.
The last step is to automatically check for renewal via a cronjob, this can be as simple as:
And we’re all set! Now if there is any security update for either LibreSSL or acme-client, fetch the new version, verify your downloads and compile and install the new version.
Please contact me for any suggestions or criticism.