Dezvoltatori → Ghiduri

Certificate wildcard cu DNS-01 și certbot

Provocarea DNS-01 dovedește că dețineți controlul asupra unui domeniu printr-o înregistrare TXT, nu printr-o pagină web. Este singura modalitate de a obține un certificat wildcard și funcționează și pentru servere care nu sunt accesibile din internet. Acest hook îi permite lui certbot să publice înregistrarea respectivă prin API-ul NameOcean.

NameOcean emite gratuit un certificat wildcard pentru orice domeniu de pe NameOcean DNS, îl reînnoiește și vă oferă un link de descărcare (SSL sau POST /ssl/example.com). Folosiți acest ghid atunci când serverul dvs. trebuie să își obțină și să își reînnoiască singur certificatul.

De ce aveți nevoie

  • DNS-ul domeniului pe NameOcean (serverele de nume ns1.nameocean.net până la ns4.nameocean.net).
  • certbot, dig (dnsutils sau bind-utils) și CLI-ul nameocean instalate pe server.
  • O cheie API cu dns:read și dns:write. Dacă puteți, restricționați-o la adresa IP a serverului.

1. Instalați hook-ul

root@server
# curl -fsSL https://nameocean.net/install.sh | sh
# curl -fsSL https://nameocean.net/developers/guides/letsencrypt-dns-01/nameocean-hook.sh \
    -o /etc/letsencrypt/nameocean-hook.sh
# chmod 700 /etc/letsencrypt/nameocean-hook.sh
# echo 'NAMEOCEAN_API_KEY=no_live_…' > /etc/letsencrypt/nameocean.env
# chmod 600 /etc/letsencrypt/nameocean.env

Cheia rămâne într-un fișier pe care îl poate citi doar root; setările de reînnoire salvate de certbot nu o conțin niciodată.

2. Obțineți certificatul

root@server
# certbot certonly --manual --preferred-challenges dns \
    --manual-auth-hook "/etc/letsencrypt/nameocean-hook.sh auth" \
    --manual-cleanup-hook "/etc/letsencrypt/nameocean-hook.sh cleanup" \
    -d example.com -d "*.example.com"

Pentru fiecare nume, hook-ul identifică zona căreia îi aparține dintre zonele dvs. NameOcean, adaugă _acme-challenge ca înregistrare TXT și așteaptă până când toate cele patru servere de nume răspund cu ea, de obicei în cel mult zece secunde. După verificare, pasul de curățare șterge exact înregistrarea adăugată. example.com și *.example.com folosesc amândouă _acme-challenge.example.com; cele două valori sunt publicate în paralel.

3. Reînnoiri

certbot stochează hook-urile împreună cu certificatul, așa că timer-ul său îl reînnoiește în același mod. Testați acest lucru o dată:

root@server
# certbot renew --dry-run

Fiecare înregistrare adăugată și ștearsă de hook apare în Panou → Activitate, împreună cu cheia care a efectuat operațiunea, și generează evenimentele webhook dns.record.created și dns.record.deleted.

Hook-ul

Citiți-l înainte de a-l rula ca root. Apelează doar CLI-ul nameocean și dig.

/etc/letsencrypt/nameocean-hook.sh
#!/bin/sh
# certbot DNS-01 hooks for NameOcean DNS:
#   --manual-auth-hook "/etc/letsencrypt/nameocean-hook.sh auth"
#   --manual-cleanup-hook "/etc/letsencrypt/nameocean-hook.sh cleanup"
# Needs the nameocean CLI and an API key with dns:write, in /etc/letsencrypt/nameocean.env:
#   NAMEOCEAN_API_KEY=no_live_...
set -e
[ -f /etc/letsencrypt/nameocean.env ] && . /etc/letsencrypt/nameocean.env && export NAMEOCEAN_API_KEY

# the zone CERTBOT_DOMAIN is in: the longest of your zones it ends with
zone="$NAMEOCEAN_ZONE"
if [ -z "$zone" ]; then
  for z in $(nameocean dns ls --json | sed -n 's/.*"name": *"\([^"]*\)".*/\1/p'); do
    case "$CERTBOT_DOMAIN" in "$z" | *".$z") [ ${#z} -gt ${#zone} ] && zone="$z" ;; esac
  done
fi
[ -n "$zone" ] || { echo "no NameOcean DNS zone for $CERTBOT_DOMAIN" >&2; exit 1; }
name="_acme-challenge"
[ "$CERTBOT_DOMAIN" = "$zone" ] || name="_acme-challenge.${CERTBOT_DOMAIN%.$zone}"

case "$1" in
auth)
  id=$(nameocean dns add "$zone" TXT "$name" "$CERTBOT_VALIDATION" --ttl 5m --json \
    | sed -n 's/.*"id": *\([0-9][0-9]*\).*/\1/p' | head -n 1)
  [ -n "$id" ] || { echo "could not add the TXT record" >&2; exit 1; }
  echo "$id" # certbot passes this to the cleanup hook as CERTBOT_AUTH_OUTPUT
  # wait until all four nameservers answer with it (usually a few seconds)
  for i in $(seq 1 60); do
    n=0
    for ns in ns1 ns2 ns3 ns4; do
      dig +short TXT "$name.$zone" "@$ns.nameocean.net" | grep -q -- "$CERTBOT_VALIDATION" && n=$((n + 1))
    done
    [ "$n" -eq 4 ] && exit 0
    sleep 2
  done
  echo "the TXT record is not on every nameserver after 2 minutes" >&2
  exit 1
  ;;
cleanup)
  [ -z "$CERTBOT_AUTH_OUTPUT" ] || nameocean dns rm "$zone" TXT "$CERTBOT_AUTH_OUTPUT"
  ;;
*)
  echo "usage: $0 auth|cleanup" >&2
  exit 2
  ;;
esac

Fără CLI

Hook-ul face două apeluri API pe care le puteți efectua din orice client ACME sau limbaj:

curl
$ curl -X POST https://nameocean.net/api/v1/dns/example.com/records \
    -H "Authorization: Bearer $NAMEOCEAN_API_KEY" -H "Content-Type: application/json" \
    -d '{"type": "TXT", "hostname": "_acme-challenge", "text": "<validation>", "ttl": "5m"}'
{"id": 4190, "type": "TXT", "hostname": "_acme-challenge", …}
$ curl -X DELETE https://nameocean.net/api/v1/dns/example.com/records/TXT/4190 \
    -H "Authorization: Bearer $NAMEOCEAN_API_KEY"