Issuing valid certificates for LAN-only websites

The scenario: you have some websites that only face your network. You want to enable SSL on them, and the certificate to be recognized out of the box on the clients, without the need for installing on each of them. For this, you have your own domain name.

So a self-signed certificate is not an option, and you’ll probably want to use Let’s Encrypt. However, if you try Let’s Encrypt, the HTTP-01 challenge will fail, as your website doesn’t face the internet.

A solution may be to use the DNS-01 challenge, but your domain DNS may not support it. In that case, what can you do?

The solution

The problem we have here is that your server can’t be contacted from the internet for the HTTP-01 challenge. A way to overcome this is to set up a dummy server to listen in the appropriate place.

My goal in the next paragraphs is to guide you on how to do it a general way. Then, if needed, you can research a particular step to get more in-depth details for your particular setup.

To start, I’ll assume you want to setup 2 websites using domain example.com: subdomain1.example.com and subdomain2.example.com.

1. Set up a dummy server

First, we’ll set up a web server to be contacted for the challenge. This should be a non-SSL server and listen externally on port 80. You can keep its root empty.

How exactly you’ll implement it depends on your setup. For example, you could add a new virtual server to the same web server that hosts your LAN websites and set it to listen to a different port. Then, forward that port to external port 80.

2. Point your (sub)domains to that IP

Configure your domain’s DNS to point subdomain1.example.com and subdomain2.example.com to the public IP of the dummy server. If you are configuring many subdomains, consider using CNAME.

3. Issue the certificate

Now with the appropriate Let’s Encrypt tools, issue the certificate using the dummy server. Include all the subdomains you need.

For example, if you set the root of the dummy server to /var/www/dummy, using acme.sh you’d run:

$ acme.sh -d 'subdomain1.example.com' -d 'subdomain2.example.com' -w '/var/www/dummy'

Your dummy server should be contacted and the certificate generated with success. You can then install it normally. For example, on acme.sh you can use --installcert.

4. Configure the certificate on the actual websites

On your web server, configure the actual websites to use the installed certificate.

Set them to listen on the https port (443) and their server_name to subdomain1.example.com or subdomain2.example.com, accordingly.

5. Set split-horizon DNS

By now, your real websites are not reachable from the internet, as you wanted. However, they aren’t available for your LAN either.

To fix this, we need to tell the devices on our network that (subdomain1|subdomain2).example.com aren’t available on that IP we set on the public DNS, but on the appropriate internal IP.

Two ways of doing that are:

  • Edit the hosts file on the devices you want.

  • Set a DNS on your LAN that resolves those entries.

    This can be done on a capable router or on a small device such as a Raspberry Pi.

6. Test

Enter (subdomain1|subdomain2).example.com while on your LAN and you should access your websites securely with SSL. Exit your LAN and they’ll not be available.

All done

You now have multiple websites that are only available on your network and they have a valid certificate issued by a trusted CA. If you did everything properly, it should also be automatically renewed.


All posts · Show comments