По следам статьи с сайта — https://www.umgum.com/letsencrypt-wildcard-bind9
Я только актуализировал информацию и оставил только один DNS.
Для автоматического получения wildcard сертификата используемый ACME-клиент (в данном случае Certbot) запрашивает у сервера Let’s Encrypt уникальную строку-идентификатор, которую любым способом необходимо разместить в специальной TXT-записи нижеследующего формата, чтобы проверяющий сервер Let’s Encrypt мог считать её и удостовериться, что мы владеем или управляем указанным DNS-сервером:
_acme-challenge.example.net. 120 IN TXT "Sg0...oLc"
Все вышеуказанные действия подразумевают под собой ручное редактирование зоны, что в условиях наличия нескольких серверов DNS представляет большую трудоёмкость, да и ручное обновление сертификатов рано или поздно приведёт к истечению срока действия текущего.
Поэтому проще всего использовать дополнительно устанавливаемый certbot-плагин «dns-rfc2136«, автоматизирующий процедуры получения секретного ключа, публикующий его и удаляющий DNS-запись после завершения запроса, область действия которого, как правило, достаточно просто ограничивается настройками NS-сервера, как такового.
Плагин «dns-rfc2136» взаимодействует с DNS-сервером посредством протокола «Dynamic DNS (DDNS)» с подписанием команд посредством «Transaction SIGnature (TSIG)». Не все DNS-серверы поддерживают эту связку, но Bind9 в этом плане полностью функциональный.
Для начала подготовим необходимые файлы и настройки на DNS-сервере
ОС: Ubuntu
ПО: Certbot, bind9
Сгенерируем TSIG-ключ для подписания транзакций от ACME-приложений
tsig-keygen -a hmac-sha512 letsencrypt-example.net > /etc/bind/tsig.key
, где
tsig-keygen — утилита, входящая в состав bindutils при установке сервера bind9,
-a — тип алгоритма генерации,
hmac-sha512 — сам алгоритм,
letsencrypt-example.net — просто имя ключа. Его можно задать любым.
Сгенерированный ключ пишется в файл /etc/bind/tsig.key, содержимое которого примерно такое
key "letsencrypt-example.net" { algorithm hmac-sha512; secret "INVc+PYj...sF/USw=="; };
Защищаем файл от просмотра другими пользователями
chown bind:bind /etc/bind/tsig.key chmod 640 /etc/bind/tsig.key
Включаем файл ключа в конфигурацию Bind9. Главное, чтобы ключ был описан вне пределов параметра options . Лучше описать его в файле named.conf
nano /etc/bind/named.conf
... include "/etc/bind/tsig.key"; ...
Использование протокола DDNS, посредством которым Certbot подключается и оперирует сущностями Bind9 проявляет в работе последнего неприятную особенность — при внесении изменений в доменную зону таковые вначале записываются в автоматически создаваемый файл журнала транзакций «*.jnl», которые минут через пятнадцать вливаются в оригинальный конфигурационный файл зоны, перезаписывая его с форматированием возможно кардинально отличающимся от исходного. Это неприемлемо в случае поддержания DNS-сервиса ручными правками, так что для тех доменов, для которых нужно запрашивать wildcard-сертификаты «Let`s Encrypt», будет лучше создавать выделенные для ACME-взаимодействий конфигурационные файлы доменной зоны:
В файле описания местоположения доменных зон пишем
nano /etc/bind/named.conf.local
... // Выделенная для взаимодействия с сервисами "Let`s Encrypt" доменная зона zone "_acme-challenge.example.net" IN { type master; file "/var/lib/bind/db._acme-challenge.example.net"; check-names ignore; // Разрешаем предъявителю TSIG-ключа вносить изменения строго определённого характера update-policy { grant letsencrypt-example.net name _acme-challenge.example.net. TXT; }; }; ...
, где
указывается файл отделённой зоны для продления сертификатов. Файл располагается не там, где основное описание доменных зон, а по адресу /var/lib/bind, потому что в Ubuntu из-за политики AppArmor, указанной в файле /etc/apparmor.d/usr.sbin.named описано, что для исполняемого файла named запрещено писать в /etc/bind/, но можно в /var/lib/bind/
В поле update-policy указывается, что только ключ с именем letsencrypt-example.net может менять TXT записи в зоне _acme-challenge.
В файл отделённой доменной зоны помещаются стандартные записи
nano /var/lib/bind/db._acme-challenge.example.net
$TTL 3600 _acme-challenge.example.net. IN SOA ns.example.net. root.example.net. ( 2022121501 ; Serial 900 ; Refresh 60 ; Retry 86400 ; Expire 900 ) ; Negative Cache TTL @ IN NS ns.example.net.
Проверяем файл зоны
named-checkconf /etc/bind/named.conf named-checkzone _acme-challenge.example.net /var/lib/bind/db._acme-challenge.example.net zone _acme-challenge.example.net/IN: loaded serial 2022121525 OK
systemctl restart bind9
Теперь когда на DNS-сервере подготовлены файлы зоны, ключа и указана новая зона, можно приступить к настройке на стороне сервера, где установлен Certbot.
Устанавливаем плагин certbot-dns-rfc2136
apt install python3-certbot-dns-rfc2136
Настраиваем плагин.
Подготовим TSIG ключ, который был сгенерирован на DNS-сервере
nano /etc/letsencrypt/ns.example.net-rfc2136.ini
# (обязательно указывать IP-адрес, а не FQDN целевого NS-сервера!) dns_rfc2136_server = 192.168.1.1 dns_rfc2136_name = letsencrypt-example.net dns_rfc2136_secret = INVc+PY...LsF/USw== dns_rfc2136_algorithm = HMAC-SHA512
,где
dns_rfc2136_server — IP сервера, на котором установлен Bind9,
dns_rfc2136_name — имя ключа, который указывался в файле tsig.key,
dns_rfc2136_secret — секрет, который так же указывался в файле ключа tsig.key.
dns_rfc2136_algorithm — алгоритм шифрования ключа.
Защищаем файл настройки от просмотра другими пользователями.
chmod 640 /etc/letsencrypt/ns.example.net-rfc2136.ini
Проверяем, что certbot корректно отрабатывает
Запускаем его с параметром —dry-run
certbot certonly --dry-run --dns-rfc2136 --force-renewal \ --dns-rfc2136-propagation-seconds 10 \ --dns-rfc2136-credentials /etc/letsencrypt/ns.example.net-rfc2136.ini \ --server https://acme-v02.api.letsencrypt.org/directory --email hostmaster@example.net \ --agree-tos --no-eff-email -d "example.net" -d "*.example.net"
, где —dns-rfc2136 — тип аутентификации через плагин dns-rfc2136,
—dns-rfc2136-propagation-seconds — количество секунд для ожидания создания и появления TXT записей, чтобы сервер Let’s Encrypt смог их увидеть,
—dns-rfc2136-credentials — ini файл настроек
Когда пробный запуск увенчается успехом, можно запустить команду без ключа —dry-run
certbot certonly --dns-rfc2136 --force-renewal --dns-rfc2136-propagation-seconds 10 \ --dns-rfc2136-credentials /etc/letsencrypt/ns.example.net-rfc2136.ini \ --server https://acme-v02.api.letsencrypt.org/directory --email hostmaster@example.net \ --agree-tos --no-eff-email -d "example.net" -d "*.example.net"
Команда запишет необходимые настройки в файл /etc/letsencrypt/renewal/example.net.conf и получит новые сертификаты.
Для последующего продления можно использовать команду certbot renew
Полученные сертификаты можно использовать с любимым веб-сервером. Ну и занести в крон. Или в таймеры systemd. Кому как нравится.
Список использованных источников:
Thank you so much. This works great in general. Two comments
(1) it may be good to remind scatterbrained readers that they also have to set the _acme zone for the secondaries they may run. I certainly for
(2) if you run this for several domains, can you reuse the key? In that case your key name should not depend on the zone you are currently configuring. So could it be
key «letsencrypt» {
algorithm hmac-sha512;
secret «INVc+PYj…sF/USw==»;
};
Thank you for your feedback. Yes, you can use one key for multiply domains, zones, etc. It’s working.
But I’m separate keys for individual domain because it’s my habit.