Hopefully, at this point everyone has secured all their public facing services with HTTPS. Let’s Encrypt makes this quick and easy to do (not to mention free!). What about local services that are only available on your lan though? This is tougher because normal verification methods don’t work, yet it is still important. Part of a defense in depth strategy is to always assume you are in a hostile environment, and with all the router vulnerabilities, Universal Plug and Play problems, and issues such as DNS rebinding attacks, it is not a good assumption that there are no malicious actors on your lan.
To secure your local resources there are a few things that you need.
- A domain name - This domain name must be a real domain that you own. For this blog I’ll use example.com.
- Publicly hosted DNS with a provider that Certbot Supports. DNS providers that I know have plugins for Certbot are:
- A local DNS resolver that you can use to serve your internal subdomain.
Once you have these components in place, you can get started.
Setup an internal subdomain
The first step is to setup an internal subdomain. If I own example.com, I might use local.example.com for local resources. I might host a NextCloud instance at nextcloud.local.example.com, an internal wiki at wiki.local.example.com, and maybe a local copy of Gitlab at gitlab.local.example.com for extra geek points. For each of these services, you’ll need to create DNS records on your local DNS server so that you computers can find them. Make sure they all have static IP addresses (or static DHCP reservations which is my preferred way to do it) and create an A record for each (and an AAAA record if you use IPv6).
Get credentials to use your DNS provider’s API
I use AWS Route53 to host my DNS. It costs $1/month, but is very good. I have been nothing but happy with their service. Instructions for this part will vary depending on what provider you use. For AWS, you need to create an IAM role that has the following permissions:
- route53:GetChange - all resources
- route53: ListHostedZones - all resources
- route53:ListResourceRecordSets - all resources
- route53:ChangeResourceRecordSets - arn of example.com
After setting up this user, click on “Create Security Credentials” and you will be given a Access Key ID and a Secret Key. You need to save these to your server under /root/.aws/credentials.
Download and install Certbot and the plugin for your DNS provider and webserver.
In this case for me, I had to install python2-certbot, python2-certbot-apache and python2-certbot-dns-route53. I am running this on a Centos7 server. Choose your packages as needed.
for example, to run on your wiki host, you would run:
sudo certbot --installer=apache --dns-route53 -d wiki.local.example.com
This will automatically go out and create a dns record on your dns provider (assuming you got the credentials formatted correctly), verify them, and then clean up the record for you. You get a legitimate, verified, Let’s Encrypt certificate without ever exposing that server to the internet.
Add a renewal check to your root user’s crontab. This command will check twice a day it renewals are due. For extra credit, forward root’s mail to your email address and you’ll get the results of these renewals in your inbox.
sudo crontab -e 0 0,12 \* \* \* python -c 'import random; import time; time.sleep(random.random() \* 3600)' && certbot renew
That’s all there is to it. Now you have secure HTTPS that browsers trust by default on local services. No need to mess around with self-signed certs or insecure connections.