Co je acme-dns
Nástroj acme-dns je specializovaný DNS server, určený k pohodlnému ověřování DNS-01 challenges ze standardu ACME. Ten používá především certifikační autorita Let's Encrypt.
Server acme-dns zjednodušuje generování certifikátů včetně wildcard a podporují ho různé nástroje pro generování certifikátů – ze známých například acme.sh, traefik nebo v Kubernetes cert-manager.
Proč použít acme-dns?
Tento odstavec může spěchající čtenář, který hledá rychlý návod copy-and-paste, v klidu přeskočit. Setkáme se zase u nadpisu: „Jak acme-dns použít“, ano?
Challenge DNS-01 od uživatele žádajícího o vystavení certifikátu očekává, že dokáže vložit TXT záznam _acme-challenge
do DNS zóny, pro kterou vyžaduje certifikát. Při vystavování certifikátu pro example.com
tedy autorita hledá TXT záznam _acme-challenge.example.com
. Dotyčný záznam by měl obsahovat náhodný řetězec, který nám autorita poslala, čímž prokážeme, že doménu ovládáme a jsme oprávněni pro ni požadovat certifikát. Vytvoření TXT záznamu je možné zařídit mnoha různými způsoby, pro Bind a Knot DNS to popsali Ondřej Caletka s Petrem Krčmářem v článku na Rootu.
Nevýhodou konfigurace v původním článku popsané je, že proces žádající o certifikát musí mít oprávnění zasahovat do DNS zóny, což není vždy technicky možné.
Alternativní řešení se zástupnou (proxy) zónou popsal v češtině Dan Ohnesorg v jiném článku na Root.cz. V angličtině ho popsal na blogu EFF v zápisku Securing the Automation of ACME DNS Joona Hoikkala (autor acme-dns) a použil acme-dns.
Řešení spočívá v tom, že DNS jméno _acme-challenge.example.com
delegujeme na DNS jméno, které směřuje na jiný DNS server, který dynamické změny podporuje. Obvykle je toto jméno ve speciální DNS zóně – té se říká zástupná zóna (proxy).
Acme-dns se používá právě pro obsluhu této zástupné zóny a nabízí k tomu pohodlné HTTP API. Pomocí API je možné vkládat TXT záznamy, které tam potom Let's Encrypt může hledat. Jiné než TXT dotazy acme-dns zamítne.
Protože je acme-dns open-source, můžeme ho provozovat na vlastní infrastruktuře, což autoři i doporučují. Pro lenochy je ale dostupná i veřejná instance, která běží na adrese auth.acme-dns.io.
Jak acme-dns použít?
Ukázka: Chceme zřídit wildcard certifikát například pro jména: koren.cz
a *.koren.cz
a použijeme zmíněnou veřejnou instanci acme-dns.
Nejprve se na acme-dns zaregistrujeme. To provedeme pomocí HTTP POST požadavku na URL /register/
:
$ curl -XPOST https://auth.acme-dns.io/register
Nameserver v acme-dns
vytvoří samostatnou subdoménu. V HTTP odpovědi pak dostaneme JSON se jménem domény a přihlašovací údaje potřebné ke změně DNS záznamů. Např.
{ "username":"4a9b69a2-bb8d-4cda-b2e3-fd1a265c3b04", "password":"aer7eL0ooch6Dohg6Uo0xaY8hokoorohmie7ohga", "fulldomain":"b1efaf61-e641-4b2c-9168-b8adc2ca0801.auth.acme-dns.io", "subdomain":"b1efaf61-e641-4b2c-9168-b8adc2ca0801", "allowfrom":[] }
Tahle část se provádí pouze při prvním generování certifikátu. Jméno uživatele, heslo a jméno domény si schováme.
Interně si acme-dns vytvoří v databázi dva prázdné TXT záznamy, které bude později měnit podle požadavků na API.
Získali jsme vlastní DNS doménu b1efaf61-e641-4b2c-9168-b8adc2ca0801.auth.acme-dns.io
. Můžeme si ručně vyzkoušet, že nastavení TXT záznamu pomocí HTTP API funguje:
# export config variables export ACMEDNS_BASE_URL="https://auth.acme-dns.io" export ACMEDNS_USERNAME="4a9b69a2-bb8d-4cda-b2e3-fd1a265c3b04" export ACMEDNS_PASSWORD="aer7eL0ooch6Dohg6Uo0xaY8hokoorohmie7ohga" export ACMEDNS_SUBDOMAIN="b1efaf61-e641-4b2c-9168-b8adc2ca0801" # generate random token export TOKEN=__this_is_very_random_token_______nbusr123_ curl -XPOST \ -H "X-Api-User: ${ACMEDNS_USERNAME}" \ -H "X-Api-Key: ${ACMEDNS_PASSWORD}" \ -H 'content-type: application/json' \ -d "{ \"subdomain\": \"${ACMEDNS_SUBDOMAIN}\", \"txt\": \"${TOKEN}\" }" \ ${ACMEDNS_BASE_URL}/update
Ověřit, že TXT záznam se povedlo vložit, můžeme např. příkazem dig
dig ${ACMEDNS_SUBDOMAIN}.auth.acme-dns.io txt
Pokud acme-dns věříme, můžeme ověření v tomto kroku přeskočit. Štouralové na vlastní infrastruktuře se naopak mohou podívat, že v databázi acme-dns je opravdu vložený nový záznam.
Máme tedy k dispozici DNS záznam b1efaf61-e641-4b2c-9168-b8adc2ca0801.auth.acme-dns.io
a je potřeba upravit DNS záznam _acme-challenge.koren.cz
tak, aby směroval na ten zástupný záznam.
Přidáme do nameserveru, obsluhujícím zónu koren.cz nový CNAME záznam:
_acme-challenge.koren.cz. 300 IN CNAME b1efaf61-e641-4b2c-9168-b8adc2ca0801.auth.acme-dns.io.
Můžeme opět ověřit, že uvidíme náhodný token zadaný v předchozím kroku.
$ dig _acme-challenge.koren.cz txt
Přípravná práce je hotová, můžeme si vyžádat certifikát, v případěacme.sh
například pomocí:
# export config variables export ACMEDNS_BASE_URL="https://auth.acme-dns.io/update" export ACMEDNS_USERNAME="4a9b69a2-bb8d-4cda-b2e3-fd1a265c3b04" export ACMEDNS_PASSWORD="aer7eL0ooch6Dohg6Uo0xaY8hokoorohmie7ohga" export ACMEDNS_SUBDOMAIN="b1efaf61-e641-4b2c-9168-b8adc2ca0801" # ./acme.sh --issue --dns dns_acmedns -d *.koren.cz -d koren.cz
Pokud bude všechno v pořádku, acme.sh
připraví soukromý klíč, žádost o certifikát a nechá ji ověřit od CA LetsEncrypt.
Při žádosti acme.sh
vytvoří záznamy v připravené zástupné zóně, proběhne ověření ze strany Let's Encrypt a na lokální disk se uloží podepsané certifikáty.
Nainstalujeme vystavené certifikáty a máme hotovo. Při prodlužování certifikátu už má acme.sh
poznamenáno, ve které zástupné zóně jsou DNS záznamy vedené, a použije přihlašovací údaje znovu.
Pozor: současná implementace acme.sh
implementuje použití pouze jedné sady přihlašovacích údajů a jednoho acme-dns serveru.
Použití s cert-manager v Kubernetes
Pokud bychom chtěli acme-dns použít s Kubernetes a cert-managerem, stačí vytvořit v Kubernetes objekty typu Issuer nebo ClusterIssuer se solverem ACMEDNS. Solver acmedns z cert-manageru vyžaduje uložení jména a hesla pro acme-dns do Kubernetes objektu Secret
. Pro každé jméno certifikátu můžeme zadat jiný acme-dns server.
Konfigurace acme-dns
Pro každou proxy zónu je potřeba vytvořit jednu registraci uživatele v acme-dns a pro každou registraci nám acme-dns vytvoří jednu zónu. Nic ale nebrání tomu, do jedné zástupné zóny delegovat více CNAME záznamů z „opravdových“ domén.
Pozor: acme-dns drží v databázi pouze dva poslední TXT záznamy pro každou zónu, pokud by došlo k souběhu při ověřování, mohlo by ověřování selhat.
Registrované účty a vytvořené domény se ukládají do databáze, kterou je potřeba chránit před ztrátou – přijdeme-li o seznam doménových jmen a přihlašovacích účtu, nebudou fungovat a neprodloužíme certifikáty.
Pro ukládání dat o registraci je dispozici sqlite nebo připojení do PosgreSQL. Typ a umístění databáze se zadává v konfiguračním souboru.
Kromě umístění databáze je v konfiguračním souboru je možné zadat i další běžné konfigurační volby, např. na kterých adresách má acme-dns poslouchat. HTTP endpoint je možné provozovat na HTTP i HTTPS, a i tahle volba se zadává do konfiguračního souboru.
Pokud neprovozujeme službu pro celý svět, obvykle nechceme, aby se na na naši soukromou instanci acme-dns mohli registrovat náhodní kolemjdoucí uživatelé. Po vytvoření všech potřebných registrací je možné acme-dns zakázat registraci nových uživatelů – volba v konfiguračním souboru se jmenuje disable_registration
.
Podobně při registraci nového uživatele je možné omezit seznam IP adres, ze kterých bude možné volat požadavek /update
na konkrétní zástupnou zónu. Stačí při registraci poslat JSON slovník s klíčem allowfrom
. Např.
$ curl -XPOST curl -XPOST https://auth.acme-dns.io/register \ -d '{ "allowfrom": [ "91.213.160.188/32", "2001:67c:68::76/64"] }'
Rok bezproblémového provozu
acme-dns v tomto okamžiku používáme necelý rok a velmi nám zjednodušil správu wildcard certifikátů. Pro uživatele, kteří se nechtějí obtěžovat s nastavováním tradičního DNS serveru, to může být docela dobrá volba a zvážil bych jeho nasazení.
Za největší výhodu acme-dns považuji to, že dělá pouze jednu věc a snaží se ji dělat dobře.