This project goes alongside my blog post TLS certs for internal OTS hardware and provides a full proof of concept demonstration of the concepts I set out in it. Full code for the project is available in my GitHub Repo .
To setup your own demo, all you need is:
For the domain, remember, this should be similar to, but not, your main domain.
I chose Cloudflare for their simple to use DNS API. The DNS code for the project is modular so feel free to swap it out for a different provider if you do not agree with their choices of who they allow to use their platform.
You will need to set the domain up with Cloudflare so it is handling DNS for your chosen domain, it does not need to handle any web traffic. You then need to generate an API key so the server can interact and generate DNS entries.
If I could work out the correct way to do it, I would distribute binaries for the major platforms but it seems to be too tricky due to dependency issues so, instead, you'll need to compile your own. If you are not a developer, don't worry, it is very straight forward. I'm going to assume you are on a Linux based system, if you are on Windows, the commands will be very similar, you'll probably just need to add a ".exe" here and there and swap the slashes around.
First you'll need Go installed, you can do this either through your OS package management system or by following these Getting Started instructions.
Once you have that in place you can check out the source, this is done with:
go get -v github.com/digininja/ots-cert-demo
Now we have the code, let's build the server:
cd ~/go/src/github.com/digininja/ots-cert/server go get -v ./... go build cp ots-cert-server.cfg-template ots-cert-server.cfg
At the end of this, you should have a binary called server and an empty configuration file. Populate the configuration file with your chosen domain and the Cloudflare API details, you should not need to update any of the other fields but have a look just in case.
The app needs to know the IP address of the host so the DNS can be setup correctly. As this is a demo, it will only bind on an internal IP address, so to find an IP, it scans through all the available interfaces looking for IPs in the RFC 1918 ranges, if it finds just one of these, it will use it, if it finds multiple then you have to tell it which interface you want it to take the address from, you can set this either in the config file or on the command line with
You should then be able to start the server:
./server INFO Starting the server INFO No valid certificate found, going to create a new one INFO Creating DNS record INFO Starting web server on: https://iotserver.ots-cert.space:9443
If there are no errors, then you've just tested all the key parts of the system and everything is good and working. This is because, when the server starts up, it has no certificate and no usable DNS name so the first thing it does is to go off and set itself up. It creates a new certificate, registers its name with the DNS provider and then starts up a web server listening on HTTPS. To save repeated calls to get new certificates, the server stores the certificate and key locally so the next time it starts, it doesn't need to go get a new one.
Now, lets get the client up and running. In a new terminal run:
cd ~/go/src/github.com/digininja/ots-cert/client go get -v ./... go build cp ots-cert-client.cfg-template ots-cert-client.cfg
Similar to before, you should now have a client binary and an empty configuration file. The only change you will need to make to the config file is to set the hostname for your server.
Once the configuration is complete, let's run it and see what happens:
./client INFO The hostname is: nifty-babbage.ots-cert.space INFO The certificate was generated INFO Setup complete, browse to https://nifty-babbage.ots-cert.space:8443
Hopefully you will get something which looks like the above and you will be able to browse to the URL you are shown:
curl https://nifty-babbage.ots-cert.space:8443 Congratulations, you should be viewing this over HTTPS on your custom domain.
A quick check on the server and you should see the steps it went through in generating the certificate and returning it.
./server INFO Starting the server INFO No valid certificate found, going to create a new one INFO Creating DNS record INFO Starting web server on: https://iotserver.ots-cert.space:9443 INFO Call to register a client INFO The client ID is: aeadc9da-2057-4c3d-8a75-63369c68af43 INFO Hostname generated for client: nifty-babbage INFO Creating DNS record INFO Call to generate a certificate INFO Certificate generated and being returned to the client
And that is it, you how have a web server running on an internal IP address which has a valid certificate from Lets Encrypt.
The client writes the certificate to disk but deliberately does not reload it next time it starts up, this is to allow the process to be demonstrated, in the real world, the client would check the certificate on start up, and if it is valid, reuse it. If either the server or the client are likely to be up for a while, they would also need to periodically check the certificate expiry date so they can be renewed so they can be renewed at an appropriate time.
If you want to manually check the certificate, to confirm it is valid, you can do this as follows:
openssl x509 -in cert.pem -text -noout Certificate: Data: Version: 3 (0x2) Serial Number: 03:db:bb:db:00:46:81:9d:88:4d:c6:de:a3:8b:56:5b:25:b3 Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 Validity Not Before: Jun 25 09:51:16 2019 GMT Not After : Sep 23 09:51:16 2019 GMT Subject: CN = nifty-babbage.ots-cert.space
When the server receives the initial request to register the client, it checks the IP address provided is an internal address, this is a way to prevent the server being used to setup DNS entries and certificates for sites which could be made internet facing. Despite the domain in use not being the main one for the company, having attackers being able to start up externally reachable websites with valid DNS and certificates is probably not the best thing to have.
I was originally planning to run a public server so users could see the concept running as it would in the wild, but as I've got the default restriction of only being able to issue a small number of Lets Encrypt certificates a day, I do not think it would work too well and might end up confusing rather than helping people.
If you like this demo, and are thinking of creating something based on it, pleaseget in touch, it would be brilliant to know the process is being used in the real world and that there are manufacturers of OTS hardware that are taking security seriously.