Skip to content

Instantly share code, notes, and snippets.

@andrewn
Last active November 14, 2023 13:17
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save andrewn/b30375074398ab94361dc607ac7c0e12 to your computer and use it in GitHub Desktop.
Save andrewn/b30375074398ab94361dc607ac7c0e12 to your computer and use it in GitHub Desktop.
Testing SSL (LetsEncrypt certificate and loopback domain)

Testing SSL (LetsEncrypt certificate and loopback domain)

General approach

This sets up a publically-available domain that loops back to localhost IP address 127.0.0.1. For example, this address could be localhost.example.com if we controlled the example.com domain. This relies on having a public domain name whose DNS records you can control. We can then generate LetsEncrypt certificates for this domain.

Our HTTP server runs on localhost:80 (default HTTP port). This lets us visit http://localhost.example.com in a web browser and see the server running on localhost:80.

We then run an HTTPS proxy server on localhost:443 (default HTTPS port) that uses the LetsEncrypt certificates we generated for localhost.example.com. Visiting https://localhost.example.com hits the proxy, which returns the correct certificates meaning the browser displays the "Secure" message. The proxy then passes the request through to the HTTP server.

Issues

  • it's very convoluted
  • private keys etc need to be distributed to any machine running the server
  • must have control of DNS records on domain
  • LetsEncrypt certificates expire so the whole process must be repeated to get new ones (steps 5-9 below)
  • ...?

Steps

  1. Create the loopback A record for localhost.example.com:

    In your DNS provider's control panel:

      Type: A
      Name: localhost.example.com.
      Data: 127.0.0.1
      TTL: 3600
  1. After a while, the following command:
    $ dig a localhost.example.com.

    ;; ANSWER SECTION:
    localhost.example.com.	3599 IN	A	127.0.0.1
  1. Install LetsEncrypt's certbot so we can generate a valid SSL cert:
    brew install certbot
  1. Generate a SSL cert for your domain using the DNS challenge type which means you won't need to have a server running on this domain:
    sudo certbot certonly --config-dir . --work-dir . --logs-dir . --manual --preferred-challenges dns
  1. Enter the domain name when prompted:
    localhost.example.com
  1. Ok with logging? Yes

  2. Add the DNS record and TXT value in your DNS provider's control panel as requested by certbot. Do not press Enter until it's been deployed.

  3. There are a few more questions then certbot will have generated files in the directory you ran the command in:

    live
    └── localhost.example.com
        ├── README
        ├── cert.pem
        ├── chain.pem
        ├── fullchain.pem
        └── privkey.pem
  1. Use the redbox proxy to point to the generated certificates and start on port 443:
    sudo node redbird-proxy.js live/localhost.example.com/
  1. Set the API_URL in .env to:
    API_URL=https://localhost.example.com/api
  1. Start HTTP client on port 80 (edit .env to set PORT=80)
    sudo npm start
  1. Visit https://localhost.example.com

The HTTPS server should be available without any browser warnings. HTTP version will be available on http://localhost.example.com.

/*
Relies on redbird being installed:
npm install redbird
Usage: node proxy <public-loopback-domain> <path-to-pems>
e.g. node proxy localhost.example.com ./live/localhost.example.com
*/
const path = require('path');
const incomingDomain = process.argv[2];
const possibleCertDir = process.argv[3];
if (incomingDomain == null || possibleCertDir == null) {
console.log('Usage: node proxy localhost.example.com path/to/pem/dir');
process.exit();
}
const certDir = path.resolve(possibleCertDir);
const redbird = new require('redbird')({
ssl: {
port: 443,
ca: path.join(certDir, 'chain.pem'),
cert: path.join(certDir, 'cert.pem'),
key: path.join(certDir, 'privkey.pem'),
},
});
redbird.register(
incomingDomain,
'localhost'
);
@dkprog
Copy link

dkprog commented Sep 1, 2020

I'm using similar approach to test a WebRTC solution inside my network. I also have created a free .TK domain using freenom.com.
Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment