आधुनिक प्रमाणपत्र नवीनीकरण CLI टूल lego के साथ DNS प्रमाणीकरण को स्वचालित करें
नमस्ते, मैं मुनो हूँ।
हाल ही में मैं फ़ाइल प्रमाणीकरण से छुटकारा पाने की कोशिश कर रहा हूँ, या यूँ कहें कि मुझे यह थोड़ा अजीब लगता है कि मैं certbot के साथ प्रमाणपत्र अपडेट चला रहा हूँ, क्योंकि उस स्थिति में फ़ाइल प्रमाणीकरण का उपयोग किया जाता है और mail.example.com डोमेन को डमी के रूप में Nginx की तरफ से Listen करना पड़ता है।
चूंकि यह स्वचालित रूप से चल रहा है इसलिए यह ठीक है, लेकिन certbot फ़ाइल प्रमाणीकरण के लिए अस्थायी रूप से पथ पर एक फ़ाइल रखता है और उसे अपडेट करता है। लेकिन, मेल सर्वर को वास्तव में http की आवश्यकता नहीं है और मैं वास्तव में इसे स्वीकार नहीं करना चाहता।
इसके अलावा, यदि A रिकॉर्ड में कई Origin निर्दिष्ट हैं, तो यह ऑपरेशन विफल हो जाता है।
क्योंकि
$dig soulminingrig.com +short
91.98.169.80
163.44.113.145
यदि इस तरह से दो IP पर अनुरोध स्वीकार किए जा रहे हैं, और एक सर्वर पर certbot चलाया जा रहा है, तो दूसरे सर्वर पर उस फ़ाइल प्रमाणीकरण के लिए फ़ाइल मौजूद नहीं होगी। HTTP या DNS क्लाइंट-साइड के निकटतम सर्वर पर अनुरोध भेजने के विनिर्देश (specification) के कारण शायद यह सफल हो रहा है, लेकिन इस तरह के "जादू" पर निर्भर रहना संचालन (operation) के रूप में विफल हो जाता है।
acme.sh और certbot के विनिर्देशों (specifications) के कारण DNS प्रमाणीकरण लागू करने में आने वाली कठिनाइयाँ
इन दोनों के साथ DNS प्रमाणीकरण स्वयं संभव है।
हालाँकि, certbot के मामले में, DNS अपडेट API को स्वचालित रूप से कॉल करने के लिए कोई प्रीसेट नहीं है। इसलिए रिकॉर्ड पंजीकरण आदि सब कुछ हमें ही करना पड़ता है, और स्वचालित अपडेट व्यावहारिक रूप से DNS प्रमाणीकरण के लिए उपयोग नहीं किए जा सकते।
acme.sh के मामले में, यह डिफ़ॉल्ट रूप से ConoHa DNS API का समर्थन नहीं करता है। यदि आप इसे विकल्पों (options) के साथ उपयोग करने का प्रयास करते हैं, तो विकल्प काफी अस्त-व्यस्त हो जाते हैं। इस स्थिति में, यदि DNS सर्वर बदलता है, तो यह काफी कठिन हो जाता है।
lego
जब मैं कुछ और खोज रहा था, तो मुझे आश्चर्य हुआ कि Go में बना एक टूल ConoHa DNS API का समर्थन करता है।
ConoHa v3 :: Let’s Encrypt client and ACME library written in Go.
GitHub - go-acme/lego: Let's Encrypt/ACME client and library written in Go · GitHub
कमाल है!
इंस्टॉलेशन
pkg में भी उपलब्ध होने के लिए धन्यवाद...।
# pkg search lego
lego-4.33.0 Let's Encrypt client and ACME library written in Go
pkg install lego-4.33.0
निष्पादन स्क्रिप्ट
मेरे मामले में, लगभग सभी डोमेन Nginx पक्ष पर प्रबंधित होते हैं और बाकी कुछ ही हैं, इसलिए मैंने चैपी (Chappy) से अपडेट स्क्रिप्ट बनवाई है।
मेरे मामले में, मैं www.example.com और example.com के लिए SAN प्रमाणपत्र जारी करना चाहता हूँ और वाइल्डकार्ड प्रमाणपत्र जारी नहीं करना चाहता हूँ, इसलिए यह इस तरह दिखता है।
#!/bin/sh
set -eu
SITES_DIR="/usr/local/etc/nginx/sites-enabled"
export CONOHAV3_TENANT_ID=""
export CONOHAV3_API_USER_ID=""
export CONOHAV3_API_PASSWORD=""
export CONOHAV3_PROPAGATION_TIMEOUT="600"
export CONOHAV3_POLLING_INTERVAL="300"
LEGO="/usr/local/bin/lego"
SSLDIR="/usr/local/etc/ssl/lego"
EMAIL="taro@example.com"
DNS_PROVIDER="conohav3"
# nginx管理外でも更新したいドメインをここに追加
# スペース区切りで複数記述
EXTRA_DOMAINS="
mail.example.com
"
tmp_all="$(mktemp)"
tmp_done="$(mktemp)"
trap 'rm -f "$tmp_all" "$tmp_done"' EXIT INT TERM
# nginx の server_name から抽出
grep -RhoE 'server_name[[:space:]]+[^;]+' "$SITES_DIR" \
| sed -E 's/^server_name[[:space:]]+//' \
| tr ' ' '\n' \
| sed 's/;$//' \
| sed '/^$/d' \
| sed '/^\*\./d' \
| sed '/^_/d' \
>> "$tmp_all"
printf '%s\n' "$EXTRA_DOMAINS" \
| tr ' ' '\n' \
| sed '/^$/d' \
>> "$tmp_all"
sort -u -o "$tmp_all" "$tmp_all"
: > "$tmp_done"
issue_cert() {
echo "==> issuing certificate for: $*"
"$LEGO" \
--accept-tos \
--path "${SSLDIR}" \
--email "$EMAIL" \
--dns "$DNS_PROVIDER" \
--dns.resolvers 1.1.1.1 \
"$@" \
run
}
already_done() {
grep -Fxq "$1" "$tmp_done"
}
mark_done() {
printf '%s\n' "$1" >> "$tmp_done"
}
while IFS= read -r host; do
[ -n "$host" ] || continue
if already_done "$host"; then
continue
fi
case "$host" in
www.*)
apex="${host#www.}"
if grep -Fxq "$apex" "$tmp_all"; then
issue_cert -d "$apex" -d "$host"
mark_done "$apex"
mark_done "$host"
else
issue_cert -d "$host"
mark_done "$host"
fi
;;
*.*.*)
issue_cert -d "$host"
mark_done "$host"
;;
*.*)
if grep -Fxq "www.$host" "$tmp_all"; then
issue_cert -d "$host" -d "www.$host"
mark_done "$host"
mark_done "www.$host"
else
issue_cert -d "$host"
mark_done "$host"
fi
;;
*)
echo "skip invalid host: $host" >&2
;;
esac
done < "$tmp_all"
अपडेट करने के लिए बस run विकल्प को renew में बदलना होगा।
स्वचालित अपडेट
मेरे मामले में, चूंकि यह FreeBSD है, इसलिए मैं इसे /etc/periodic.conf में लिखता हूँ।
weekly_lego_enable="YES"
weekly_lego_renewscript="/usr/local/etc/lego/dns.sh"
weekly_lego_deployscript="/usr/local/etc/lego/deploy.sh"
चूंकि डिफ़ॉल्ट /usr/local/etc/lego/deploy.sh और /usr/local/etc/lego/lego.sh उपलब्ध हैं, इसलिए मूल रूप से इस डिज़ाइन का पालन करना बेहतर है। हालाँकि, जहाँ तक देखा जा सकता है, डिफ़ॉल्ट फ़ाइल प्रमाणीकरण का उपयोग करता है, इसलिए यदि आप इस बार की तरह DNS प्रमाणीकरण करना चाहते हैं, तो बदलाव आवश्यक हैं।