SSL сертификат Let’s Encrypt с помощью acme.sh и bind

В этой статье я расскажу о получении wildcard SSL сертификата Let’s Encript при помощи скрипта acme.sh, и сервера bind. Также покажу как настроить автоматическое обновление сертификатов.

Надо сказать, что ранее на своих серверах я использовал для этих целей certbot, который просто устанавливал при помощи пакетного менеджера. Но так как разработчики certbot приняли решение распространять его в виде snap-пакета, а у меня демон snapd полностью из системы выпилен, то пришлось искать альтернативные решения. Об одном из них — acme.sh, я и хочу рассказать.

Оглавление

Настройка BIND

Итак, друзья, давайте мы займемся настройкой возможности динамического обновления сервера DNS bind (о его настройке я уже писал ранее). Во-первых, для этого нам необходимо создать ключи TSIG.

TSIG (transaction signature) – это протокол, позволяющий системе доменных имен аутентифицировать обновления в базе данных

Чтобы создать ключ tsig и файл конфигурации зоны для bind вы можете выполнить shell-скрипт, которым я пользуюсь для экономии времени.

#!/usr/bin/env bash

domain='domain.tld'

tsig-keygen -a HMAC-SHA512 acme.$domain > acme.$domain.key

cat <<EOF > acme.$domain.conf
zone "acme.$domain" IN {
    type master;
    file "/var/lib/bind/acme.$domain";
    allow-query { any; };
    update-policy {
        grant "acme.$domain" name _acme-challenge.acme.$domain. txt;
    };
};
EOF

cat acme.$domain.key >> acme.$domain.conf

В результате его выполнения вы получите два файла: acme.domain.tld.conf — файл конфигурации зоны и acme.domain.tld.key — файлы tsig-ключа. Конфигурационный файл зоны нужно добавить в конфигурационный файл bind /etc/bind/named.conf.local.

Не забудьте перезапустить сервис bind и исправить domain.tld на имя вашего домена!

В целях безопасности мы не будем добавлять разрешение на обновление основной зоны нашего домена, а добавим еще одну техническую зону для ответа на вызовы dns-01 ACME и уже для нее включим динамические обновления. Ну а в основной зоне мы просто создадим запись CNAME для challenge-записи, которая будет указывать на техническую зону:

; Алиас для записи dns-01 challenge.
_acme-challenge CNAME _acme-challenge.acme.domain.tld.

В итоге нам, конечно, необходимо убедиться, что динамические обновления работают. Это можно сделать с помощью утилиты nsupdate. Давайте добавим запись TXT в нашей зоне acme.domain.tld проверим ее добавление.

$ nsupdate -k /etc/bind/acme.domain.tld.key -v
> debug yes
> server domain.tld
> zone acme.domain.tld.
> update add test.acme.domain.tld. 86400 TXT "text"
> show
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:      0
;; flags:; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; ZONE SECTION:
;acme.domain.tld.		IN	SOA

;; UPDATE SECTION:
test.acme.domain.tld. 86400	IN	TXT	"text"

> send
Sending update to ::1#53
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:  46815
;; flags:; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 1
;; ZONE SECTION:
;acme.domain.tld.		IN	SOA

;; UPDATE SECTION:
test.acme.domain.tld. 86400	IN	TXT	"text"

;; TSIG PSEUDOSECTION:
acme.domain.tld.	0	ANY	TSIG	hmac-sha512. 1636652685 300 64 acIwDVA9B0WS+koh9/OWNOHbIRnONkmGN/d6zVbY8bVAcoxyDDIJvGi8 1NP6uaWzubn4iITO2qHLAo5t/RO2KQ== 46815 NOERROR 0 


Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: REFUSED, id:  46815
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 1
;; ZONE SECTION:
;acme.domain.tld.		IN	SOA

;; TSIG PSEUDOSECTION:
acme.domain.tld.	0	ANY	TSIG	hmac-sha512. 1636652685 300 64 pkodEyw4PIiR8qTy9Gnmjg/MKDGW245CcMUShfRYlDy7/gXSSvsEeCJN 5h56SMRjctB5fPsXY04mGbsqcM9A1w== 46815 NOERROR 0 

> quit
$ dig +short -t txt test.acme.domain.tld
"text"

После проверки не забудьте удалить TXT запись из зоны (update delete test.acme.domain.tld.).

Установка acme.sh

Если у вас все получилось, то можно приступать к установке shell-скрипта acme.sh. Я предпочитаю способ установки при помощи git (на странице скрипта в github есть и другие способы).

sudo -s
cd /tmp
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install --cert-home '/etc/letsencript' --email 'account@email.com'
cd ..
rm -rf acme.sh

Итак, скрипт по умолчанию будет установлен в ~/.acme.sh. Кроме этого будет добавлена задача обновления сертификатов в crontab. Вы можете посмотреть ее при помощи crontab -e.

Получение сертификатов

Ну что же, почти все готово. Чтобы получить сертификаты Let’s Encript при помощи скрипта acme.sh мы будем использовать плагин dns_nsupdate для внесения требуемых записей в зону, обслуживаемую bind. Для выпуска сертификата можно воспользоваться следующим скриптом:

#!/usr/bin/env bash
NSUPDATE_SERVER='ns.domain.tld'
export NSUPDATE_SERVER
NSUPDATE_KEY='/etc/bind/acme.domain.tld.key'
export NSUPDATE_KEY

. "/root/.acme.sh/acme.sh.env"

/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt
/root/.acme.sh/acme.sh --issue -d 'domain.tld' -d '*.domain.tld' --challenge-alias acme.domain.tld --dns dns_nsupdate --renew-hook '/root/.acme.sh/renew-hook.sh'

Если все прошло успешно, то выпущенные сертификаты можно будет найти в каталоге, который вы указали в параметре --cert-home при установке скрипта ( по умолчанию ~/.acme.sh/domain.tld ). Ну а содержимое скрипта, которое будет выполнено после обновления сертификатов предлагаю вам написать самостоятельно. Обычно — это просто перезапуск сервисов, которые используют выпущенные сертификаты.

На этом статья об автоматизации получения SSL сертификатов Let’s Encrypt с помощью acme.sh и bind завершена. Как обычно я жду ваши вопросы и замечания в комментариях. Удачи!

Один комментарий к “SSL сертификат Let’s Encrypt с помощью acme.sh и bind

  1. Если указывать:
    update-policy {
    grant «acme.$domain» name _acme-challenge.acme.$domain. txt;
    То update add test.acme.domain.tld. 86400 TXT «text» не отработает
    Надо тогда на _acme-challenge.acme и проверять

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *