Module for handling dns-01 challenges by Dynamic DNS updates#90
Open
Yenya wants to merge 3 commits intodo-know:masterfrom
Open
Module for handling dns-01 challenges by Dynamic DNS updates#90Yenya wants to merge 3 commits intodo-know:masterfrom
Yenya wants to merge 3 commits intodo-know:masterfrom
Conversation
NAME
Crypt::LE::Challenge::DDNS - use dynamic DNS for ACME challenges
SYNOPSIS
use Crypt::LE;
use Crypt::LE::Challenge::DDNS;
...
my $le = Crypt::LE->new();
my $ddns_challenge = Crypt::LE::Challenge::DDNS->new(...);
..
$le->accept_challenge($ddns_challenge, ...);
$le->verify_challenge($ddns_challenge, ...);
# Shell command line:
$ le.pl ... --handle-as dns --handle-with Crypt::LE::Challenge::DDNS \
--handle-params '{"server": "127.0.0.1", "keyfile": "/var/named/keys/_le.example.org.key", "zone": "_le.example.org"}'
DESCRIPTION
This module uses Dynamic DNS (DDNS) updates for storing the ACME
challenges for DNS-01 validation.
Recommended mode of operation is to set up a Dynamic DNS subdomain
solely for ACME challenges (for example, "_le.example.org"), and for
domain names which would use Let's Encrypt certificates map their
"_acme-challenge.$fqdn" into this domain.
For example, to get a certificate for "myhost.example.org", create the
following static DNS record in the "example.org" zone:
_acme-challenge.myhost.example.org. IN CNAME myhost.example.org._le.example.org.
This module will then ask the ACME server (Let's Encrypt CA) for a
DNS-based challenge, and will store it using DDNS update to
"myhost.example.org._le.example.org." TXT record. LE will then try to
verify the challenge at "_acme-challenge.myhost.example.org" and will
find it after being redirected by the above CNAME record.
Note that ""example.org"" string is used both in the DDNS domain name,
and inside that name. This is intentional - this way one common DDNS
domain "_le.example.org" can serve for ACME challenges for multiple real
DNS domains. If you want the renaming to be done in a different way,
feel free to override the rr_from_fqdn() function in this module.
The module accepts the following parameters (usable in "--handle-params"
from the "le.pl" command line):
server
IP address of the DDNS server, where challenges will be stored.
keyfile
Authentication key for DDNS. This will be used for signing the DDNS
update requests. Any key file format supported by
"Net::DNS::RR::TSIG" will do.
zone
DDNS zone to which challenges will be written ("_le.example.org" in
the above examples). If "zone" is a suffix of the host name for
which the certificate is being created (e.g. "example.org"), then
the challenge will be stored directly to
_acme-challenge.$that_host_name
instead of mapping to a different zone as described above.
DDNS ZONE SETUP
A quick and dirty tutorial how to create a Dynamic DNS zone and key in
BIND.
Firstly, create directories and the key file:
BIND_DIR=/var/named
DDNS_DOMAIN=_le.example.org
install -d -u named -g named -m 775 $BIND_DIR/dynamic
install -d -u root -g named -m 755 $BIND_DIR/keys
tsig-keygen $DDNS_DOMAIN > $BIND_DIR/keys/$DDNS_DOMAIN.key
chown root:named $BIND_DIR/keys/$DDNS_DOMAIN.key
chmod 640 $BIND_DIR/keys/$DDNS_DOMAIN.key
Create a zone file:
cat > $BIND_DIR/dynamic/$DDNS_DOMAIN <<'EOF'
$TTL 300
IN SOA ns.example.org. root.example.org. (
1 ; serial
1H ; refresh
3H ; retry
2W ; expire
1 ; negative ttl
)
IN NS ns.example.org.
EOF
Use the key and zone file in your named.conf:
include "keys/_le.example.org.key";
zone "_le.example.org" {
type master;
file "dynamic/_le.example.org";
allow-query { any; };
allow-update { !{ !127.0.0.1; any; }; key _le.example.org; };
journal "dynamic/_le.example.org.jnl";
}
Reload named and verify that it works:
rndc reload
nsupdate -k $BIND_DIR/keys/$DDNS_DOMAIN.key
> server 127.0.0.1
> add test._le.example.org. 300 TXT "my test record"
> send
host -t any test._le.example.org. 127.0.0.1
SEE ALSO
<https://letsencrypt.org/docs/challenge-types/>, Crypt::LE,
Net::DNS::RR::TSIG, Crypt::LE::Challenge::Simple, nsupdate(1),
tsig-keygen(1)
AUTHOR
Jan "Yenya" Kasprzak "<kas you_know_what yenya.net>". Based on
"Crypt::LE::Challenge::Simple" by Alexander Yezhov.
guest20
reviewed
Apr 2, 2024
For wildcard certificates (*.$fqdn), ACME queries _acme-challenge.$fqdn,
without the "*." prefix, obviously. This has to be taken into account
when remapping the wildcard name to a different DDNS subdomain.
Moreover, when getting certificate for both $fqdn and *.$fqdn,
Crypt::LE calls ->handle_challenge_dns() twice for the same $fqdn,
and ACME expects _two_ TXT records. So we should not blindly delete
the TXT record at the beginning of ->handle_challenge_dns().
My approach is to count the number of times we've got called for
each $fqdn, store it in $self->{fqdn_seen}->{$fqdn},
and delete the TXT only in the first handle_challenge_dns() call,
and in the last handle_verification_dns() call.
|
Suggested documentation improvement: Change one of the two example domains to "example.com", this makes it easier to see which domain names are supposed to be the same, and gets rid of the awkward "used both in the DDNS domain name, |
|
@jb-wisemo that might be a good idea as a second ticket |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hello, Alexander,
I have written a module for storing dns-01 ACME challenges in the Dynamic DNS domain. Do you think it is suitable for inclusion in the Crypt::LE distribution?
Thanks,
-Yenya