March 1, 2016 · ssl servers

Proxying letsencrypt acme-challenge requests

Let’s Encrypt is cool enough. But I personally run into problem with fqdn verification, letsencrypt client should be invoked from the same ip that domain has.

So if u wanna ssl certificate for (which obviously has ipv4 address but want generate certificate(s) from some another server (e.g. micro aws instance or so with ip you out of luck. There are several workarounds explicitly described in rfc. But they can't be automated easily, moreover certificates issued for 90 days, so automation is a good choice here.

But, if you own your servers or have access to server/application configs - there are elegant solution. We need just proxying letsencrypt acme-challenge request from to that server where letsencrypt run's and use webroot native plugin (standalone is also usable, but not flexible at all).

In a nutshell:

Let’s Encrypt service want receive acme-challenge from, it make request to unique address (hash) after /.well-known/acme-challenge/ path. So when{$hash} has correct hash path and value - certificate will be issued.

Process is something like this:

#letsencrypt client sends to letsencrypt service dns, hash and value
1) -> letsencrypt service [ & $hash & $value]  
#letsencrypt service make request and obtain value (if so)
2) letsencrypt service ->{$hash}  
#and if all is ok
3) letsencrypt service -> <storing key and certificate>  

Example from - - [05/Jan/2016:20:11:24 -0500] "GET /.well-known/acme-challenge/HGr8U1IeTW4kY_Z6UIyaakzOkyQgPr_7ArlLgtZE8SX HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +"  

First of all, we need to specify webroot plugin, authenticator (used for certonly) and acme-challenge location for letsencrypt client:

./letsencrypt-auto certonly -w /opt/ssl/ --authenticator webroot --email -d

In this case letsencrypt client will write verification file to /opt/ssl/ and tell letsencrypt service to make verification request.

Now, just one simple change in server config (nginx in my case):

location  "/.well-known/acme-challenge/" {  

Ok, all acme-challenge requests now goeing to

letsencrypt service ->{$hash} ->  

And now we just need to serve acme-challenge hash file using favorite method (nginx, Node, Python, netcat :D). For testing, python one-liner will be enough:

cd /opt/ssl/ && python -m "SimpleHTTPServer" 80  

Ok, cool:

 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/ Your cert
   will expire on 2016-06-03. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:
   Donating to EFF:          

That method is extremely easy to configure and automate, for receiving certificates from dozen different domains using one letsencrypt endpoint.

Note: letsencrypt has a limit (around 5) for certificates per week.

Cheers :)

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket
Comments powered by Disqus