DNS challenge for let’s encrypt SSL certificates

Last week I had to generate a SSL certificate for a domain which has its web server on a corporate network. The Web Server on the corporate network has outgoing internet access but cannot be reach from Internet. I was not sure it was possible to generate a certificate in this case with let’s encrypt since my previous experience was with a Web server reachable from internet to answer the let’s encrypt challenge (http://djynet.net/?p=821).

Luckily I was wrong 😉 It is indeed possible to prove let’s encrypt that you own the domain with a DNS challenge! Here are my notes on how to do it.

Download the client with:

wget https://dl.eff.org/certbot-auto
chmod a+x ./certbot-auto

Run the client in manual mode with DNS challenge and wait for the client to provide you the challenge

[root@vps99754 ~]# ./certbot-auto certonly --manual --preferred-challenges dns --email <your email> -d <the domain>

Saving debug log to /var/log/letsencrypt/letsencrypt.log

Obtaining a new certificate

Performing the following challenges:

dns-01 challenge for <the domain>

-------------------------------------------------------------------------------

NOTE: The IP of this machine will be publicly logged as having requested this

certificate. If you're running certbot in manual mode on a machine that is not

your server, please ensure you're okay with that.

Are you OK with your IP being logged?

-------------------------------------------------------------------------------

(Y)es/(N)o: Y

-------------------------------------------------------------------------------

Please deploy a DNS TXT record under the name

_acme-challenge. <the domain> with the following value:

bIwIxGg1IXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Once this is deployed,

-------------------------------------------------------------------------------

Press Enter to Continue

At this point you just need to update your DNS with the entry provided as show in the following picture and press enter (maybe wait few seconds after you done the update if you use a webUI like me to update your DNS provider)

Waiting for verification...

Cleaning up challenges

Generating key (2048 bits): /etc/letsencrypt/keys/0000_key-certbot.pem

Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem

IMPORTANT NOTES:

 - Congratulations! Your certificate and chain have been saved at

   /etc/letsencrypt/live/<the domain>/fullchain.pem. Your cert will

   expire on 2017-07-23. To obtain a new or tweaked version of this

   certificate in the future, simply run certbot-auto again. To

   non-interactively renew *all* of your certificates, run

   "certbot-auto renew"

 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate

   Donating to EFF:                    https://eff.org/donate-le

All set 😉 Pretty easy and very nice feature to validate a Webserver not connected to internet (as long as you have access to its DNS server and it is reachable from internet).

Let’s encrypt TLS setup for nodejs

Following my first test to setup a HTTPS server to dialogue with facebook API describe in my previous article here I had error when trying to register the facebook webhook:

facebookCaError

I dig deeper and also verified the domain certificate with https://www.ssllabs.com/ssltest :

sslcheckKo

It seems good but there is a warning about the certificate chain… I done some quick research and it seem to be the root cause. After some investigation (and mainly thanks to this post) it seems the error comes from my nodejs server setup and more particularly the missing certificate authority certificate info. I miss it since it is not used in the official documentation. It is indeed an optional parameter

If this is omitted several well-known “root” CAs will be used, like VeriSign

Let’s add it in the options:

var options = {
    key: fs.readFileSync('/etc/letsencrypt/live/djynet.xyz/privkey.pem'),
    cert: fs.readFileSync('/etc/letsencrypt/live/djynet.xyz/cert.pem'),
    ca: fs.readFileSync('/etc/letsencrypt/live/djynet.xyz/chain.pem')
};

I done the ssl check another time and the error is now gone…. And the facebook webhook work fine too:

sslCheckOk