SSL Certificate generation

You might've realized that since the Lab environment is accessible solely through VPN, requesting certificates from Let's Encrypt might be difficult/impossible.

It's true, by default Let's Encrypt uses the HTTP-01 challenge which either runs a small webserver or puts special challenge files on the server, that Let's Encrypt can check for through the domain. If it finds them, domain ownership is proved and SSL certificate is issued.

In our case Let's Encrypt can't access our VMs that are in a VPN, so we have to use an alternative challenge based on DNS-01.
Here's more information about how the different challenges work: https://letsencrypt.org/docs/challenge-types/

To request certificates for your Lab VMs, you need a few pre-requisites:

  • An individually issued "TSIG Key" (you should find it in your welcome email). This will be used to update DNS records and prove domain ownership through DNS.
  • Certbot (or an alternative webserver that handles key requests for you like Caddy) for certificate requests

Below are example with Certbot and Caddy with Caddyfile

Certbot

First make sure you have Certbot installed, most of the time it's available as certbot package in your package manager.
And the RFC2136 plugin for Certbot, in debian it's called python3-certbot-dns-rfc2136

Create a file called lab-creds.ini somewhere secure, as this will be a file holding secrets.
The file should contain the following content:

dns_rfc2136_server = 95.217.58.233
dns_rfc2136_port = 5355
dns_rfc2136_name = <username>.
dns_rfc2136_secret = <tsig key>
dns_rfc2136_algorithm = HMAC-SHA256
dns_rfc2136_sign_query = false

Make sure to replace <username> and <tsig key> with values from your welcome email.
Take note that there is a dot after the username, it's important, keep it there.

Since it's a sensitive file, Certbot requires secure permissions on it, execute the following:
chmod 600 /path/to/lab-creds.ini

After creating the file with the specified content and permissions, you can request a certificate with the following command:

certbot certonly --dns-rfc2136 --dns-rfc2136-credentials /path/to/lab-creds.ini -d <domain name>

Replace the path with an appropriate one and <domain name> with the domain name you're requesting a certificate for!

Here's an example output where the lab-creds.ini file is located in my current directory:

debian@testtt:~$ sudo certbot certonly --dns-rfc2136 --dns-rfc2136-credentials ./lab-creds.ini -d tttt.ffff.lab.dsnw.dev
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for tttt.ffff.lab.dsnw.dev
Waiting 60 seconds for DNS changes to propagate

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/tttt.ffff.lab.dsnw.dev/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/tttt.ffff.lab.dsnw.dev/privkey.pem
This certificate expires on 2024-12-01.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Caddy

Caddy setup is a bit simpler, you need to download Caddy with the RFC2136 plugin. You can either do that using the xcaddy utility or simply download it from here: Caddy with RFC2136 pre-selected
The plugin is already selected, you can just click "Download"

Once you have Caddy with the proper plugin, the Caddyfile section for TLS looks like this:

  tls {
    dns rfc2136 {
        key_name "<username>"
        key_alg "hmac-sha256"
        key "<tsig key>"
        server "ns.lab.dsnw.dev:5355"
    }
  }

Make sure to replace <username> and <tsig key> with values from your welcome email. Include this in the Server block where you need a TLS certificate

After updating your Caddyfile, you can start Caddy with something like caddy run and you should see a similar output to the one below:

2024/09/01 19:37:44.040	INFO	tls.issuance.acme.acme_client	trying to solve challenge	{"identifier": "test.ffff.lab.dsnw.dev", "challenge_type": "dns-01", "ca": "https://acme-v02.api.letsencrypt.org/directory"}
2024/09/01 19:37:47.604	INFO  tls.issuance.acme.acme_client	authorization finalized	{"identifier": "test.ffff.lab.dsnw.dev", "authz_status": "valid"}
2024/09/01 19:37:47.606	INFO	tls.issuance.acme.acme_client	validations succeeded; finalizing order	{"order": "https://acme-v02.api.letsencrypt.org/acme/order/1923213016/301443140866"}
2024/09/01 19:37:48.624	INFO	tls.issuance.acme.acme_client	got renewal info	{"names": ["test.ffff.lab.dsnw.dev"], "window_start": "2024/10/30 18:58:46.333", "window_end": "2024/11/01 18:58:46.333", "selected_time": "2024/11/01 08:48:17.000", "recheck_after": "2024/09/02 01:37:48.624", "explanation_url": ""}
2024/09/01 19:37:48.964	INFO	tls.issuance.acme.acme_client	got renewal info	{"names": ["test.ffff.lab.dsnw.dev"], "window_start": "2024/10/30 18:58:46.333", "window_end": "2024/11/01 18:58:46.333", "selected_time": "2024/10/31 22:07:45.000", "recheck_after": "2024/09/02 01:37:48.964", "explanation_url": ""}
2024/09/01 19:37:48.967	INFO	tls.issuance.acme.acme_client	successfully downloaded available certificate chains	{"count": 2, "first_url": "https://acme-v02.api.letsencrypt.org/acme/cert/03b10cce02a119144734340f54f7f5f47edc"}
2024/09/01 19:37:48.971	INFO	tls.obtain	certificate obtained successfully	{"identifier": "test.ffff.lab.dsnw.dev", "issuer": "acme-v02.api.letsencrypt.org-directory"}