Настройка ACME#
Модуль ACME в Angie обеспечивает автоматическое получение сертификатов с использованием протокола ACME. Протокол ACME предусматривает несколько способов проверки доменов (также используется термин верификация); модуль реализует HTTP-проверку и DNS-проверку, а также проверку с помощью хуков через самостоятельно реализуемый внешний сервис.
Шаги настройки#
Общие шаги для включения запроса сертификатов в конфигурации:
Настройте ACME-клиент в блоке
http
с помощью директивы acme_client, задающей уникальное имя клиента и другие параметры; можно настроить несколько клиентов ACME.Укажите домены, для которых запрашиваются сертификаты: для доменных имен, перечисленных во всех директивах server_name всех блоков
server
с директивами acme, указывающими на один и тот же ACME-клиент, будет выдан единый сертификат.-
Настройте обработку запросов и вызовов ACME: это нужно для проверки владения доменом. Способ настройки зависит от способа проверки доменных имен:
Способ
Требования
Сертификаты
Требует ответа на специальный запрос (вызов) от ACME-сервера.
Нужно открыть порт 80 на самом сервере Angie.
Не поддерживает wildcard-сертификаты.
Позволяет выпускать мультидоменные сертификаты.
Требует обработки специальных DNS-запросов (вызовов) от ACME-сервера.
Необходима возможность изменять DNS-записи.
До сервера Angie должен быть открыт порт, заданный директивой acme_dns_port (по умолчанию 53).
Позволяет выпускать мультидоменные и wildcard-сертификаты.
Требует реализации внешнего сервиса, к которому обращается сервер Angie.
Требует наличия внешнего DNS- или HTTP-сервера, настраиваемого внешним сервисом.
Для внешнего DNS- или HTTP-сервера действуют требования соответствующего пункта выше.
Позволяет выпускать мультидоменные и wildcard-сертификаты.
-
Настройте SSL с использованием полученного сертификата и ключа: Модуль делает сертификаты и ключи доступными в виде встроенных переменных, которые можно использовать в конфигурации для заполнения ssl_certificate и ssl_certificate_key.
Инструкции по настройке SSL см. в разделе Настройка SSL.
Подробности реализации#
Здесь ключи и сертификаты клиентов хранятся
в кодировке PEM
в соответствующих подкаталогах каталога,
заданного с помощью параметра сборки
--http-acme-client-path
:
$ ls /var/lib/angie/acme/example/
account.key certificate.pem private.key
Клиенту ACME требуется учетная запись на сервере CA.
Для ее создания и управления ею клиент использует закрытый ключ
(account.key
);
если ключа у него еще нет, ключ создается при запуске.
Затем клиент использует его для регистрации учетной записи на сервере.
Примечание
Если у вас уже есть ключ учетной записи,
поместите его в подкаталог клиента перед запуском
для повторного использования учетной записи.
Файл ключа также можно указать с помощью параметра account_key
в acme_client.
Клиент ACME также использует отдельный ключ
(private.key
) для запросов на подпись сертификата (CSR);
если нужно, этот ключ сертификата также создается автоматически при запуске.
При запуске клиент запрашивает сертификат, если его еще нет,
подписывая и отправляя CSR для всех доменов, которыми он управляет, серверу CA.
Сервер проверяет владение доменом
путем HTTP- или DNS-проверки
и выдает сертификат,
который клиент сохраняет локально (certificate.pem
).
Как сказано выше, сертификат будет единым для всех доменных имен, для которых используется один и тот же ACME-клиент, то есть потенциально может быть мультидоменным. Список всех имен, для которых выдан сертификат, см. в разделе Subject Alternative Name (SAN) полученного сертификата. Проверить его можно в командной строке, например:
$ openssl x509 -in certificate.pem -noout -text | grep -A5 "Subject Alternative Name"
Когда приближается завершение срока действия сертификата или изменяется список доменов, клиент подписывает и отправляет еще один CSR на сервер CA. Сервер снова проверяет владение и выдает новый сертификат, который клиент устанавливает локально, заменяя предыдущий.
В конфигурации полученный сертификат и соответствующий ключ доступны через префиксные переменные $acme_cert_<имя> и $acme_cert_key_<имя>. Они содержат имена соответствующих файлов, которые следует использовать с ssl_certificate и ssl_certificate_key, например:
server {
listen 443 ssl;
server_name example.com www.example.com;
acme example;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
}
HTTP-проверка#
Проверка работает автоматически.
Суть ее заключается в том, что ACME-сервер, получив запрос,
запрашивает у клиента через HTTP
особый файл-токен по адресу /.well-known/acme-challenge/<TOKEN>
.
Наш модуль ACME отслеживает такие запросы и самостоятельно обрабатывает их.
Получив ожидаемый ответ с нужным содержимым,
ACME-сервер подтверждает, что домен принадлежит клиенту.
Пример конфигурации#
Здесь ACME-клиент с именем example
управляет сертификатами для
example.com
и www.example.com
(учтите, что wildcard-сертификаты не поддерживаются при HTTP-проверке):
http {
resolver 127.0.0.53; # требуется для директивы 'acme_client'
acme_client example https://acme-v02.api.letsencrypt.org/directory;
server {
listen 80; # Может стоять в другом блоке 'server'
# с другим списком доменов
# или даже без него
listen 443 ssl;
server_name example.com www.example.com;
acme example;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
}
}
Как уже отмечалось, порт 80 должен быть открыт для приема вызовов ACME по HTTP. Однако, как указывает этот пример, директива listen для этого порта может стоять в отдельном блоке server. Если существующего блока с такой директивой нет, можно ограничить новый блок одними только вызовами ACME:
server {
listen 80;
return 444; # Нет ответа, соединение закрыто
}
Почему это работает?
Модуль перехватывает запросы к /.well-known/acme-challenge/<TOKEN>
после чтения заголовков, но до выбора виртуального сервера
и обработки директив rewrite и location.
Такие перехваченные запросы обрабатываются, если значение <TOKEN>
соответствует ожидаемому для конкретного вызова.
Обращения к каталогу не будет; запрос полностью обрабатывается модулем.
DNS-проверка#
Проверка работает автоматически.
Суть в том, что при получении запроса на сертификат
ACME-сервер выполняет специальный DNS-запрос
к поддомену _acme-challenge.
проверяемого домена.
После получения ожидаемого ответа ACME-сервер подтверждает,
что домен принадлежит клиенту.
Наш модуль ACME отслеживает такие запросы и обрабатывает их автоматически,
при условии, что ваши записи DNS настроены должным образом,
чтобы указать сервер Angie в качестве авторитетного сервера имен
для поддомена _acme-challenge.
.
Например, чтобы подтвердить домен example.com
,
используя сервер Angie с IP-адресом 93.184.215.14
,
DNS-конфигурация вашего домена должна включать следующие записи:
_acme-challenge.example.com. 60 IN NS ns.example.com.
ns.example.com. 60 IN A 93.184.215.14
Эта конфигурация делегирует разрешение DNS для
_acme-challenge.example.com
на ns.example.com
,
обеспечивая доступность ns.example.com
путем сопоставления с IP-адресом (93.184.215.14
).
Этот способ позволяет запрашивать wildcard-сертификаты, например сертификат,
включающий запись *.example.com
в разделе Subject Alternative Name
(SAN). Чтобы в явной форме запросить сертификат для поддомена, например
www.example.com
, следует отдельно подтвердить этот поддомен описанным
выше способом.
Внимание
Применимость данного сценария во многом зависит от возможностей, предоставляемых вашим DNS-провайдером; некоторые провайдеры не позволяют выполнять такие настройки.
Пример конфигурации#
В целом, конфигурация схожа с примером из предыдущего раздела.
Нет необходимости в настройках, специфичных для HTTP;
вместо этого достаточно установить challenge=dns
для директивы acme_client.
Здесь ACME-клиент с именем example
управляет сертификатами для
example.com
и *.example.com
:
http {
resolver 127.0.0.53;
acme_client example https://acme-v02.api.letsencrypt.org/directory
challenge=dns;
server {
server_name example.com *.example.com;
acme example;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
}
}
Проверка с помощью хуков#
В отличие от предыдущих способов, эта проверка требует дополнительных усилий. Здесь ACME-сервер производит обычную HTTP-проверку или DNS-проверку, но обращается не к самому серверу Angie, а к внешнему сервису, которым сервер Angie управляет с помощью вызовов-хуков (acme_hook). В свою очередь, этот сервис настраивает отдельный DNS- или HTTP-сервер, куда и направляются запросы ACME-сервера.
Получив ожидаемый ответ от настроенного таким образом DNS- или HTTP-сервера, ACME-сервер подтверждает, что домен принадлежит клиенту.
Angie вызывает внешний сервис в моменты, когда требуется обновление сертификатов по протоколу ACME. Вызовы передаются путем проксирования запросов и данных на серверы FastCGI, SCGI и аналогичные с использованием директив fastcgi_pass, scgi_pass и т.д.
Сервис должен возвращать код 2xx
,
что можно сделать через заголовок Status
.
Любой другой код считается ошибкой, и обновление сертификата прекращается.
При этом вывод от сервиса игнорируется.
Пример конфигурации#
Здесь настраивается ACME-клиент example
для подтверждения домена при помощи DNS-вызова,
на что указывает параметр challenge=dns
директивы acme_client
.
Блок server
применяется ко всем поддоменам example.com
(например, *.example.com
)
и использует ACME-клиент example
для управления сертификатами,
что указано в директиве acme
.
Здесь также настроен именованный блок location
,
через который и производятся вызовы внешнего сервиса для DNS-верификации.
Директива acme_hook
связывает сервер с ACME-клиентом example
.
Запросы проксируются на FastCGI-сервер, работающий локально на порту 9000,
с помощью директивы fastcgi_pass
.
Директива fastcgi_param
передает во внешний сервис
данные об ACME-клиенте, хуке, типе вызова, домене, токене и ключе авторизации.
acme_client example https://acme-v02.api.letsencrypt.org/directory
challenge=dns;
server {
listen 80;
server_name *.example.com;
acme example;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
location @acme_hook_location {
acme_hook example;
fastcgi_pass localhost:9000;
fastcgi_param ACME_CLIENT $acme_hook_client;
fastcgi_param ACME_HOOK $acme_hook_name;
fastcgi_param ACME_CHALLENGE $acme_hook_challenge;
fastcgi_param ACME_DOMAIN $acme_hook_domain;
fastcgi_param ACME_TOKEN $acme_hook_token;
fastcgi_param ACME_KEYAUTH $acme_hook_keyauth;
include fastcgi.conf;
}
}
Пример соответствующего внешнего FastCGI-сервиса на Perl:
#!/usr/bin/perl
use strict; use warnings;
use FCGI;
my $socket = FCGI::OpenSocket(":9000", 5);
my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket);
while ($request->Accept() >= 0) {
print "\r\n";
my $client = $ENV{ACME_CLIENT};
my $hook = $ENV{ACME_HOOK};
my $challenge = $ENV{ACME_CHALLENGE};
my $domain = $ENV{ACME_DOMAIN};
my $token = $ENV{ACME_TOKEN};
my $keyauth = $ENV{ACME_KEYAUTH};
if ($hook eq 'add') {
DNS_set_TXT_record("_acme-challenge.$domain.", $keyauth);
} elsif ($hook eq 'remove') {
DNS_clear_TXT_record("_acme-challenge.$domain.");
}
};
FCGI::CloseSocket($socket);
Здесь DNS_set_TXT_record()
и DNS_clear_TXT_record()
—
функции, предположительно добавляющие и удаляющие TXT-записи
в конфигурации некого внешнего DNS-сервера, к которому и обратится ACME-сервер.
В этих записях должны содержаться переданные сервером Angie данные,
что позволит внешнему DNS-серверу успешно пройти проверку,
аналогичную описанной в разделе DNS-проверка.
Подробности реализации таких функций выходят за рамки этого руководства.
Миграция с certbot#
Если до перехода с nginx на Angie вы использовали certbot для получения и продления SSL-сертификатов от центра сертификации Let's Encrypt, выполните следующие шаги, чтобы перейти к использованию нашего модуля ACME.
Предположим, вы настроили сертификаты следующим образом:
$ sudo certbot --nginx -d example.com -d www.example.com
Автоматически созданная при этом конфигурация
обычно находится в файле /etc/nginx/sites-available/example.conf
и выглядит приблизительно так:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
root /var/www/example;
index index.html;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
try_files $uri $uri/ =404;
}
}
В примере выше выделены строки, которые потребуется изменить. В зависимости от ваших обстоятельств и предпочтений настройте HTTP-проверку или DNS-проверку с помощью модуля ACME.
Итоговая конфигурация Angie может выглядеть приблизительно так:
http {
resolver 127.0.0.53;
acme_client example https://acme-v02.api.letsencrypt.org/directory;
server {
listen 80;
return 444;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
root /var/www/example;
index index.html;
acme example;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
location / {
try_files $uri $uri/ =404;
}
}
}
Не забудьте перезагрузить конфигурацию после изменения:
$ sudo angie -s reload
Убедившись, что эта конфигурация работает, вы можете удалить сертификаты certbot, а также отключить или целиком удалить его с сервера, если он больше нигде не используется, например:
$ sudo rm -rf /etc/letsencrypt
$ sudo systemctl stop certbot.timer
$ sudo systemctl disable certbot.timer
$ # -- или --
$ sudo rm /etc/cron.d/certbot
$ sudo apt remove certbot
$ # -- или --
$ sudo dnf remove certbot