nsupdate doesn't need "zone" statement in normal operation. Explain creating separate _acme-challenge zones.

Brian Candler
2017-11-23 16:13:13 +00:00
parent e61e943864
commit d306462124

@@ -17,18 +17,18 @@ set -o pipefail
NSUPDATE="nsupdate -k /path/to/Kdnsupdatekey.private"
DNSSERVER="127.0.0.1"
ZONE="mydomain.com"
TTL=300
case "$1" in
"deploy_challenge")
printf "server %s\nzone %s.\nupdate add _acme-challenge.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${ZONE}" "${2}" "${TTL}" "${4}" | $NSUPDATE
printf "server %s\nupdate add _acme-challenge.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${2}" "${TTL}" "${4}" | $NSUPDATE
;;
"clean_challenge")
printf "server %s\nzone %s.\nupdate delete _acme-challenge.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${ZONE}" "${2}" "${TTL}" "${4}" | $NSUPDATE
printf "server %s\nupdate delete _acme-challenge.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${2}" "${TTL}" "${4}" | $NSUPDATE
;;
"deploy_cert")
# do nothing for now
# optional:
# /path/to/deploy_cert.sh "${1}" "${2}" "${3}" "${4}"
;;
"unchanged_cert")
# do nothing for now
@@ -47,16 +47,49 @@ esac
exit 0
```
If you are using CNAMEs to put all your dynamic updates into a single zone, then you can modify it:
The file `/path/to/Kdnsupdatekey.private` looks like this:
```
key "<keyname>" {
algorithm hmac-md5;
secret "<key>";
};
```
To avoid making your entire production DNS subject to dynamic DNS updates, then for each certificate domain you want:
1. In your main DNS infrastructure create a delegation: `_acme-challenge.<domain>. NS <your-nameserver>.`
2. Create a new zone `_acme-challenge.<domain>` on `<your-nameserver>`, with an empty zonefile (just an SOA and NS record), writeable by the nameserver
3. Create a new TSIG key: `dnssec-keygen -r /dev/urandom -a hmac-md5 -b 128 -n HOST <keyname>`
4. Enable dynamic updates on the `_acme-challenge.<domain>` zone with this key
e.g. for bind9:
~~~
key "<keyname>" {
algorithm hmac-md5;
secret "<key>";
};
zone "_acme-challenge.<domain>" {
type master;
file "/var/cache/bind/_acme-challenge.<domain>";
masterfile-format text;
allow-update { key "<keyname>"; };
};
~~~
This is the most secure approach because each host will have its own key, and hence can only obtain certificates for those domains you have explicitly authorized it for.
An alternative approach is to use CNAMEs to put all your dynamic updates into a single zone. You will need to modify the script:
```
ZONE="acme.mydomain.com"
...
"deploy_challenge")
printf "server %s\nzone %s.\nupdate add _acme-challenge.%s.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${ZONE}" "${2}" "${ZONE}" "${TTL}" "${4}" | $NSUPDATE
printf "server %s\nupdate add _acme-challenge.%s.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${2}" "${ZONE}" "${TTL}" "${4}" | $NSUPDATE
;;
"clean_challenge")
printf "server %s\nzone %s.\nupdate delete _acme-challenge.%s.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${ZONE}" "${2}" "${ZONE}" "${TTL}" "${4}" | $NSUPDATE
printf "server %s\nupdate delete _acme-challenge.%s.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${2}" "${ZONE}" "${TTL}" "${4}" | $NSUPDATE
```
You then only need to create a single zone `acme.mydomain.com` which accepts dynamic DNS updates, but you will need to add static CNAMEs for `_acme-challenge.<certname>` pointing at `_acme-challenge.<certname>.acme.mydomain.com` for each certificate you want to issue.