Let’s Encrypt when your server is behind a firewall and you can’t use DNS Challenge

Sometimes you want to give a server that is  behind a firewall a valid SSL certificate. Let’s Encrypt provides a nice solution for this called DNS Challenge. The problem with DNS Challenge is it may require some manual configuring to on your server to set it up. That is all fine and good but sometimes the server won’t allow you to do that configure. A classic example is the hass.io (Home Assistant) appliance or FreePBX

I couldn’t find a coherent set of instructions for setting up Let’s Encrypt DNS Challenges with hassio, especially as my DNS provider requires custom scripts in order to achieve this.

However, I came up with a work around. First let’s think about how Let’s Encrypt (LE) usually works. Suppose you want to get a certificate for my.example.com (MEC), but my.example.com is NATed behind example.com’s (EC) IP address. When you run the LE client on MEC, it requests the LE servers to do a challenge request to MEC. MEC will have the same public IP as EC. the client on MEC will some information on the MEC server at the <webroot>/.well-known/acme-challenge. The LE servers will try and query it. If they find what they are looking for, they issue you the certificate.

So I got to thinking, as this request takes place on port 80, it must contain the domain name header, and so, if you run an web server on port 80 of EC and A entry for  MEC the same public IP address as EC, EC could simply proxy that request to the MEC server.

I looked up how to do this and set it up on my server and low and behold, I was able to get a valid certificate.

In my case I did it with nginx , so the config looked like this:

On my server on port 80 (example.com) of the firewall in /etc/nginx/sites-available/my.example.com:

server {
       server_name my.example.com;
       location / {
       		proxy_pass http://192.168.1.9:80/;
		proxy_set_header Host $http_host;
	}
}

Then symlink it to /etc/nginx/sites-enabled/my.example.com and test the nginx config:

$ sudo ln -s /etc/nginx/sites-available/my.example.com  /etc/nginx/sites-enabled/my.example.com
$ sudo nginx -t
[sudo] password for jason: 
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart nginx:

sudo systemctl restart nginx.service

Now start your Let’s Encrypt certificate request on your server and you should be good to go.

Leave a Reply

Your email address will not be published. Required fields are marked *