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"}