Let’s Encrypt でワイルドカード 証明書を得る (nsd4 利用)

Let’s Encrypt でワイルドカード証明書を得るためには DNS-01 で認証を得る必要があります。

nsd4 と dehydrated の組み合わせで一応出来たので、備忘録として記載します。なお、マスターサーバ上で実装、bind9 付属の named-checkzone を利用しているので注意して下さい。

・/etc/nsd/zones/example.com (ゾーンファイルの修正)

nsd4 では、動的にゾーンのレコードを追加したり削除したり出来ないので、実際のゾーンファイルを直接書き換えます。

関係ないところを書き換えないためにも、シリアル値を「;SERIAL_START」から「;SERIAL_END」の範囲で、DNS-01 で使う「_acme-challenge」については「;LE_DNS-01_START」から「;LE_DNS-01_END」の範囲でくくります。

$TTL 86400
example.com.		IN	SOA	ns.example.com. root.ns.example.com. (
;SERIAL_START
				2018051301	; Serial
;SERIAL_END
				86400		; Refresh 24 Hours
				7200		; Retry 2 Hours
				1209600		; Expire 2 Weeks
				7200		; Negative cache TTL 2 Hours
			)

					IN	NS	ns.example.com.

;LE_DNS-01_START
;_acme-challenge.example.com.	60	IN	TXT	"NOTHING"
;LE_DNS-01_END

NS					IN	A	192.168.1.1

・hook.sh

dehydrated 同梱の hook スクリプトを以下の様にします。

#!/usr/bin/env bash

deploy_challenge() {
    local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"
    local REGEXDOMAINNAME=`echo ${DOMAIN} | sed -e 's/\./\\\./'`
    local NOWUMASK="`umask`"
    local serial1=`named-checkzone "${DOMAIN}" "/etc/nsd/zones/${DOMAIN}" | awk '/serial/ {print $5}'`
    local serial2=`expr $serial1 + 1`
    
    umask 022
    
    sed -i -e "/;SERIAL_START/,/;SERIAL_END/ s/$serial1/$serial2/" "/etc/nsd/zones/${DOMAIN}"
    sed -i -e "/;LE_DNS-01_START/,/;LE_DNS-01_END/ s/^;_acme-challenge\.${REGEXDOMAINNAME}\..*/_acme-challenge.${DOMAIN}.\t60\tIN\tTXT\t\"${TOKENVALUE}\"/" /etc/nsd/zones/${DOMAIN}
    nsd-control reload
    
    sleep 5
    
    umask ${NOWUMASK}
}

clean_challenge() {
    local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"
    local REGEXDOMAINNAME=`echo ${DOMAIN} | sed -e 's/\./\\\./'`
    local NOWUMASK="`umask`"
    local serial1=`named-checkzone "${DOMAIN}" "/etc/nsd/zones/${DOMAIN}" | awk '/serial/ {print $5}'`
    local serial2=`expr $serial1 + 1`
    
    umask 022
    
    sed -i -e "/;SERIAL_START/,/;SERIAL_END/ s/$serial1/$serial2/" "/etc/nsd/zones/${DOMAIN}"
    sed -i -e "/;LE_DNS-01_START/,/;LE_DNS-01_END/ s/^_acme-challenge\.${REGEXDOMAINNAME}\..*/;_acme-challenge.${DOMAIN}.\t60\tIN\tTXT\t\"NOTHING\"/" /etc/nsd/zones/${DOMAIN}
    nsd-control reload
    
    sleep 5
    
    umask ${NOWUMASK}
}

deploy_cert() {
}
deploy_ocsp() {
}
unchanged_cert() {
}
invalid_challenge() {
}
request_failure() {
}
generate_csr() {
}
startup_hook() {
}
exit_hook() {
}

HANDLER="$1"; shift
if [[ "${HANDLER}" =~ ^(deploy_challenge|clean_challenge|deploy_cert|deploy_ocsp|unchanged_cert|invalid_challenge|request_failure|generate_csr|startup_hook|exit_hook)$ ]]; then
  "$HANDLER" "$@"
fi

dehydrated の config ファイルの修正

DNS-01 と hook.sh を使う様に指定します。その他は適切に設定して下さい。

CHALLENGETYPE="dns-01"
HOOK=./hook.sh

dehydrated の domains.txt ファイルの修正

以下の様な書式で記載します。

*.example.com > wildcard.exaple.com

証明書発行

後は、いつもどおり証明書を要求すると、DNS-01 で認証され、発行されます。

その他

domains.txt で「example.com *.example.com」の様にすると、example.com に 2 回 DNS-01 認証が発生し、上手くいきませんでした。