Securely creating TLS certificates with Let’s Encrypt

by Eric Fortis

This post explains why it is more secure to issue TLS certificates from an external server, as opposed to from each server. Also, we’ll discuss the chosen challenge, frequency, diversity, and key strength

Challenge type

DNS challenges are preferred because they require fewer privileges than HTTP ones. For instance, they only need TXT records that start with an _acme-challenge subdomain. For example:

_acme-challenge.example.com.     120 IN TXT "rAnd0mK"
_acme-challenge.foo.example.com. 120 IN TXT "43aZ09i"

On the other hand, HTTP challenges need:

  • to be via HTTP (not HTTPS),
  • a program on a live server,
  • write permissions on a servable directory, and
  • ‘pass out’ firewall exceptions without IP scope. We don’t publish a list of IP addresses we use to validate… Let’s Encrypt

Renewal frequency

Certificates are renewed at least once a month per server.

Let’s Encrypt certificates last for 90 days, and can be renewed up to 5 times a week. Josh Aas from the ISRG recommends renewing them every 60 days in his 2015 post:

We recommend that subscribers renew every sixty days. Once automated renewal tools are widely deployed and working well, we may consider even shorter lifetimes.

Diversity

Each server has a different certificate. As Uxtly doesn’t need stateful load balancing, this way mitigates the decryption of all the traffic of a particular user on a given period. In other words, an adversary hoarding encrypted traffic has to break more certificates.

Requisites

Although this guide uses Cloudflare®, the previous list shows how to adapt other providers. If your provider is not on that list, or if its API isn’t compatible with your security polices, you could use a different domain than the one the certificate is going to be issued for. For that, see challenging with an alias.

Cloudflare token

Create a custom API Token with these Permissions:

Zone | Zone | Read
Zone | DNS  | Edit

Cloudflare lets you limit the token to a specific zone (domain name) and from certain IP address. On the other hand, it doesn’t let you limit the privileges to ‘Only edit TXT records’, but other providers might, as suggested by Joona Hoikkala in his article.

CAA (Recommended)

Restrict which Certificate Authority is Authorized to issue certificates by adding a DNS CAA record. For example:

CAA @ letsencrypt.org

Issuing a certificate

Cloudflare-specific

export CF_Token=TheToken
export CF_Account_ID=TheAccountId

./acme.sh --server letsencrypt --issue --dns dns_cf -k ec-256 --force \
  -d    example.com \
  -d '*.example.com'

The wildcard -d '*.example.com' is handy for non‑public subdomains. For example, prevents enumeration via the Certificate Logs or inspecting the SAN.

Public-Key Cryptography

ec-256 is stronger than the default key, which is RSA 2048 bits. Check out the compatibility list.

Force

--force for being able to renew the certificate before the next renewal time (60 days by default).

Deployment

The previous command creates the certificate and key in a directory next to where the acme.sh script is.

DIR=~/.acme.sh/example.com_ecc

rsync $DIR/fullchain.cer   your_live_server:
rsync $DIR/example.com.key your_live_server:

sst -t your_live_server service nginx reload

Certificate Logs

crt.sh/?q=uxtly.com

Sponsored by: