Настройка ACME#
Модуль ACME в Angie ADC
обеспечивает автоматическое получение сертификатов с использованием протокола
ACME.
Протокол ACME предусматривает несколько способов проверки доменов
(также используется термин верификация);
модуль реализует
HTTP-проверку, DNS-проверку,
ALPN-проверку, а также
проверку с помощью хуков
через самостоятельно реализуемый внешний сервис. Общие шаги для включения запроса сертификатов в конфигурации: Настройте ACME-клиент в блоке Укажите домены, для которых запрашиваются сертификаты:
для доменных имен, перечисленных во всех директивах server_name
всех блоков IP-адреса (IPv4 или IPv6), указанные в server_name,
также являются допустимыми идентификаторами сертификата,
за исключением DNS-проверки. Обратите внимание: публичные центры сертификации могут выдавать
сертификаты для IP-адресов только в рамках определенных профилей
сертификатов; например, Let's Encrypt в настоящее время требует
профиль, допускающий IP-идентификаторы
(см. документацию по профилям).
Чтобы запросить такой профиль, задайте параметр Настройте обработку запросов и вызовов ACME:
это нужно для проверки владения доменом.
Способ настройки зависит от способа проверки доменных имен: Способ Требования к пользователю Мультидомены Домены со звездочкой Открыть порт 80 (или указанный в acme_http_port)
для входящих соединений на сервере Angie. ✔ Открыть порт 53 (или указанный в acme_dns_port)
для входящих соединений на сервере Angie. Настроить NS-запись для поддомена ✔ ✔ Открыть порт 443 (или TLS-порт, используемый сервером Angie)
для входящих соединений. ✔ Реализовать внешний сервис (скрипт или приложение),
который по команде Angie сможет внести изменения в DNS-зону
или разместить специальный ответ на веб-сервере. ✔ ✔ Настройте SSL с использованием полученного сертификата и ключа:
Модуль делает сертификаты и ключи доступными в виде
встроенных переменных,
которые можно использовать в конфигурации
для заполнения ssl_certificate и ssl_certificate_key. Совет Процесс получения и обновления сертификатов зависит от работы многих служб
и может занимать какое-то время. Запаситесь терпением,
а в случае возникновения проблем или сомнений обратитесь к
отладочному логу. По умолчанию ключи и сертификаты клиентов хранятся
в кодировке PEM
в Предупреждение При хранении сертификатов в Примечание Эти файлы сохраняются на диске между перезапусками. При запуске клиент
повторно использует сохраненный сертификат, если тот еще действителен,
вместо запроса нового, что устраняет задержку на выпуск и лишние обращения
к серверу CA, на которые могут действовать ограничения частоты запросов. Примечание Перезагрузка конфигурации заново сверяет каждый
клиент ACME с сертификатами, сохраненными на диске. Клиент, сертификат
которого в данный момент недействителен (в том числе если его предыдущий
запрос завершился ошибкой), запрашивается заново немедленно, независимо от
retry_after_error. Задержка перед повторной попыткой
(как и значение Клиенту ACME требуется учетная запись на сервере CA.
Для ее создания и управления ею клиент использует закрытый ключ
( Примечание Если у вас уже есть ключ учетной записи,
поместите его в подкаталог клиента перед запуском
для повторного использования учетной записи.
Файл ключа также можно указать с помощью параметра Некоторые CA требуют привязать учетную запись ACME к уже существующей внешней
учетной записи с помощью External Account Binding (EAB), прежде
чем выпускать сертификаты. Для этого задайте параметр Клиент ACME также использует отдельный ключ
( При запуске клиент запрашивает сертификат, если его еще нет,
подписывая и отправляя CSR для всех доменов, которыми он управляет, серверу CA.
Сервер проверяет владение доменом
путем HTTP- или DNS-проверки
и выдает сертификат,
который клиент сохраняет локально ( Как сказано выше, сертификат будет единым для всех доменных имен,
для которых используется один и тот же ACME-клиент,
то есть потенциально может быть мультидоменным.
Список всех имен, для которых выдан сертификат,
см. в разделе Subject Alternative Name (SAN) полученного сертификата.
Проверить его можно в командной строке, например: Когда приближается завершение срока действия сертификата
или изменяется список доменов,
клиент подписывает и отправляет еще один CSR на сервер CA.
Сервер снова проверяет владение и выдает новый сертификат,
который клиент устанавливает локально, заменяя предыдущий. В конфигурации полученный сертификат и соответствующий ключ
доступны через префиксные переменные
$acme_cert_<имя> и $acme_cert_key_<имя>.
Их значения — содержимое соответствующих файлов,
которое следует использовать
с директивами ssl_certificate и ssl_certificate_key, например: Примечание Клиент ACME определяет адрес сервера CA по его имени через resolver
того же контекста, который по умолчанию обращается к DNS-серверам из
Директива acme служит только для сбора доменных имен
для запросов сертификатов.
Она не определяет, где можно использовать сертификат:
любой блок Например, если у вас есть блок Чтобы точно контролировать набор доменных имен в сертификате,
не полагаясь на автоматический сбор из всех блоков Другие блоки Каждый acme_client управляет одним сертификатом. Чтобы получить
несколько независимых сертификатов (например, для несвязанных доменов, которым
не следует использовать общий сертификат), настройте отдельный
acme_client для каждого из них в блоке Проверка выполняется автоматически.
Когда Angie заказывает сертификат, ACME-сервер
запрашивает по HTTP
файл-токен по адресу Здесь ACME-клиент с именем Как уже отмечалось,
порт 80 должен быть открыт для приема вызовов ACME по HTTP.
Если ни один сервер не слушает порт HTTP-проверки,
модуль создает отдельный слушающий сокет на порту 80
(или указанном в acme_http_port). Отдельный блок
server не требуется. Проверка выполняется автоматически, но требует настройки DNS с вашей стороны.
Когда Angie заказывает сертификат, ACME-сервер отправляет DNS-запрос
TXT-записи в поддомене Чтобы запрос дошел до Angie, DNS вашего домена должен делегировать поддомен
DNS-проверка подтверждает контроль над доменным именем,
поэтому не может проверять идентификаторы в виде IP-адресов:
для клиента с Примечание Сервер Angie должен быть доступен из интернета
на UDP-порту 53 (или указанном в acme_dns_port).
Если сервер находится за межсетевым экраном,
убедитесь, что этот порт открыт для входящих соединений. Например, чтобы подтвердить домен Эта конфигурация делегирует разрешение DNS для
Предупреждение Распространение изменений NS-записей может занимать от нескольких минут
до 48 часов в зависимости от TTL и DNS-провайдера.
Рекомендуется проверить корректность настройки перед запросом сертификата. Для проверки корректности настройки DNS можно использовать следующие команды: Этот способ позволяет запрашивать wildcard-сертификаты, например сертификат,
включающий запись Предупреждение Применимость данного сценария во многом зависит от возможностей,
предоставляемых вашим DNS-провайдером;
некоторые провайдеры не позволяют выполнять такие настройки. В целом, конфигурация схожа с примером из предыдущего раздела.
Нет необходимости в настройках, специфичных для HTTP;
вместо этого достаточно установить Здесь ACME-клиент с именем Проверка работает автоматически. ACME‑сервер устанавливает TLS‑соединение и
запрашивает через ALPN протокол Чтобы использовать этот способ, задайте Конфигурация аналогична предыдущим разделам; достаточно задать
Здесь ACME-клиент с именем В отличие от предыдущих способов,
эта проверка требует дополнительных усилий.
Здесь ACME-сервер производит обычную HTTP-проверку
или DNS-проверку,
но обращается не к самому серверу Angie, а к внешнему сервису,
которым сервер Angie управляет с помощью вызовов-хуков (acme_hook).
В свою очередь, этот сервис настраивает отдельный DNS- или HTTP-сервер,
куда и направляются запросы ACME-сервера. Получив ожидаемый ответ от настроенного таким образом DNS- или HTTP-сервера,
ACME-сервер подтверждает, что домен принадлежит клиенту. Когда для выпуска или обновления сертификата требуется проверка домена,
Angie формирует внутренний запрос
к именованному Общая схема такова: Создайте именованный Настройте обработчик запроса в том же Передайте обработчику переменные ACME
с помощью поддерживаемого им механизма,
например, Обработчик должен возвращать код состояния Независимо от используемого обработчика,
При DNS-проверке обработчик должен использовать Здесь настраивается ACME-клиент Блок Именованный блок Пример соответствующего внешнего FastCGI-сервиса на Perl: Здесь Еще один пример, с использованием PHP-FPM: Переданные параметры доступны в PHP через Потоковый модуль ACME позволяет автоматизировать
выпуск и использование сертификатов для TCP-трафика.
Для его корректной работы необходимо сначала настроить HTTP-аналог:
ACME-клиент должен быть объявлен в контексте По умолчанию для получения сертификатов используется режим HTTP-проверки.
Для него, как упоминалось в разделе HTTP-проверка,
нужен HTTP-сервер, слушающий на порту 80: Также можно использовать DNS-проверку,
настроив Шаги настройки#
http
с помощью директивы acme_client,
задающей уникальное имя клиента и другие параметры;
можно настроить несколько клиентов ACME.server с директивами acme,
указывающими на один и тот же ACME-клиент,
будет выдан единый сертификат.profile=
директивы acme_client._acme-challenge.,
направив ее на свой сервер Angie.Подробности реализации#
/var/lib/angie/acme. Это местоположение можно переопределить
на /var/transfer/acme с помощью директивы acme_client_path:$ ls /var/transfer/acme/example/
account.key certificate.pem private.key
/var/transfer их возможно перезаписать.retry_after_error=off) действует, только пока Angie
работает, и не сохраняется после перезагрузки. Поэтому повторные перезагрузки
при постоянно неудачных запросах могут приводить к частым обращениям
к серверу CA, на которые действуют упомянутые выше ограничения частоты
запросов.account.key);
если ключа у него еще нет, ключ создается при запуске.
Затем клиент использует его для регистрации учетной записи на сервере.account_key
в acme_client.eab
директивы acme_client, указав идентификатор ключа и MAC-ключ,
предоставленные CA; точный синтаксис приведен в описании директивы.private.key) для запросов на подпись сертификата (CSR);
если нужно, этот ключ сертификата также создается автоматически при запуске.certificate.pem).$ openssl x509 -in certificate.pem -noout -text | grep -A5 "Subject Alternative Name"
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;
}
/etc/resolv.conf; задавайте директиву явно, только если нужны
другие серверы или параметры. На узле без поддержки IPv6 resolver может
все равно отправлять AAAA-запросы (IPv6) для сервера CA и не суметь
подключиться; отключите их параметром ipv6=off, например
resolver conf ipv6=off;.Сбор доменов и использование сертификата#
server может ссылаться на полученный сертификат
через переменную $acme_cert_<имя>,
независимо от того, содержит ли блок директиву acme.server с маской,
который уже охватывает все поддомены,
дополнительные блоки server для конкретных поддоменов
не нуждаются в директиве acme:http {
acme_client example https://acme-v02.api.letsencrypt.org/directory
challenge=dns;
# В этом блоке перечислены домены для запроса сертификата
server {
listen 443 ssl;
server_name example.com *.example.com;
acme example;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
}
# Этот блок использует тот же сертификат, но не добавляет
# свой server_name в запрос на сертификат
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
}
}
Явный список доменов#
server,
создайте отдельный блок server,
содержащий только директивы server_name и acme.
Чтобы этот блок не обрабатывал реальный трафик,
привяжите его к Unix-сокету:# Отдельный блок, определяющий список доменов сертификата
server {
listen unix:/tmp/acme_example.sock;
server_name example.com www.example.com;
acme example;
}
server могут затем использовать сертификат
через переменную $acme_cert_<имя>,
не влияя на то, какие домены запрашиваются.Отдельные сертификаты для разных доменов#
http и укажите в директиве
acme каждого блока server соответствующий клиент по имени:http {
# Два независимых клиента, каждый управляет своим сертификатом
acme_client shop https://acme-v02.api.letsencrypt.org/directory
challenge=http;
acme_client blog https://acme-v02.api.letsencrypt.org/directory
challenge=http;
server {
listen 443 ssl;
server_name shop.example.com www.shop.example.com;
acme shop;
ssl_certificate $acme_cert_shop;
ssl_certificate_key $acme_cert_key_shop;
}
server {
listen 443 ssl;
server_name blog.example.com;
acme blog;
ssl_certificate $acme_cert_blog;
ssl_certificate_key $acme_cert_key_blog;
}
}
HTTP-проверка#
/.well-known/acme-challenge/<TOKEN>.
Angie отвечает на такие запросы сам, поэтому отдавать этот путь
вручную не требуется. Получив файл, ACME-сервер сверяет токен
с выданным значением и, если они совпадают, засчитывает проверку домена.Пример конфигурации#
example управляет сертификатами для
example.com и www.example.com
(учтите, что wildcard-сертификаты не поддерживаются при HTTP-проверке):http {
acme_client example https://acme-v02.api.letsencrypt.org/directory;
server {
listen 80; # Не обязательно: если порт HTTP-проверки
# никто не слушает, модуль откроет его сам
# (см. директиву 'acme_http_port')
listen 443 ssl;
server_name example.com www.example.com;
acme example;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
}
}
DNS-проверка#
_acme-challenge. проверяемого домена.
Angie отвечает на такие запросы сам: он выступает авторитетным сервером имен
для этого поддомена и возвращает TXT-запись с тем значением, которого ждет
ACME-сервер. ACME-сервер сверяет полученную запись с выданным значением и,
если они совпадают, засчитывает проверку домена._acme-challenge. серверу Angie; нужные записи приведены ниже.
По умолчанию Angie отвечает с очень небольшим TTL, а некоторые DNS-провайдеры
отфильтровывают ответы с таким низким TTL — если проверка не завершается,
увеличьте его директивой acme_dns_ttl.challenge=dns Angie игнорирует IP-адрес
в server_name и выводит предупреждение при запуске.
Блок server, в котором указан IP-адрес, должен по-прежнему содержать
хотя бы одно доменное имя, которое клиент может проверить.example.com,
используя сервер Angie с IP-адресом 203.0.113.10,
DNS-конфигурация вашего домена должна включать следующие записи:_acme-challenge.example.com. 60 IN NS ns.example.com.
ns.example.com. 60 IN A 203.0.113.10
_acme-challenge.example.com на ns.example.com,
обеспечивая доступность ns.example.com
путем сопоставления с IP-адресом (203.0.113.10).$ dig NS _acme-challenge.example.com +short # Проверка NS-записи для поддомена _acme-challenge
ns.example.com.
$ dig A ns.example.com +short # Проверка A-записи для сервера имен
203.0.113.10
$ nc -zv 203.0.113.10 53 # Проверка доступности DNS-сервера на порту 53
*.example.com в разделе Subject Alternative Name
(SAN). Чтобы в явной форме запросить сертификат для поддомена, например
www.example.com, следует отдельно подтвердить этот поддомен описанным
выше способом.Пример конфигурации#
challenge=dns
для директивы acme_client.example управляет сертификатами для
example.com и *.example.com:http {
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;
}
}
ALPN-проверка#
acme-tls/1. Модуль отдает временный
сертификат для валидационного запроса.challenge=alpn в директиве
acme_client и убедитесь, что ваш TLS‑слушатель доступен на порту 443
(или на используемом TLS‑порту).Пример конфигурации#
challenge=alpn для директивы acme_client и убедиться, что
TLS-сервер доступен на порту 443.example управляет сертификатом для
example.com и www.example.com:http {
acme_client example https://acme-v02.api.letsencrypt.org/directory
challenge=alpn;
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;
}
}
Проверка с помощью хуков#
location, содержащему директиву acme_hook.
Способ обработки этого запроса полностью зависит
от других директив, заданных в том же location.location с директивой acme_hook.location
с помощью модуля, подходящего для вашей конфигурации:
fastcgi_pass для FastCGI,
proxy_pass для HTTP.fastcgi_param для FastCGI.2xx,
который можно передать через заголовок Status.
Любой другой код от хука add прерывает попытку обновления сертификата;
от хука remove тот же код только записывается в журнал
как предупреждение, и обновление продолжается.
Вывод обработчика игнорируется.Минимальная конфигурация#
location для хука имеет следующую структуру:location @acme_hook_location {
acme_hook example;
# Директива обработчика (fastcgi_pass, proxy_pass, ...)
# Передайте переменные ACME с помощью механизма обработчика:
# ACME_HOOK — $acme_hook_name ("add" или "remove")
# ACME_CHALLENGE — $acme_hook_challenge ("dns" или "http")
# ACME_DOMAIN — $acme_hook_domain
# ACME_TOKEN — $acme_hook_token
# ACME_KEYAUTH — $acme_hook_keyauth
}
ACME_HOOK
для определения действия:
если значение add,
создать TXT-запись для _acme-challenge.ACME_DOMAIN
со значением из ACME_KEYAUTH;
если значение remove, удалить эту запись.Пример с FastCGI#
example
для подтверждения домена при помощи DNS-вызова,
на что указывает параметр challenge=dns директивы acme_client.server применяется ко всем поддоменам example.com
(например, *.example.com)
и использует ACME-клиент example для управления сертификатами,
что указано в директиве acme.location обрабатывает вызовы хуков.
Директива 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;
}
}
#!/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-проверка.
Подробности реализации таких функций выходят за рамки этого руководства;
так, например, передавать параметры можно и через URI запроса:# ...
location @acme_hook_location {
acme_hook example uri=/acme_hook/$acme_hook_name?domain=$acme_hook_domain&key=$acme_hook_keyauth;
fastcgi_pass localhost:9000;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param ACME_CLIENT $acme_hook_client;
fastcgi_param ACME_CHALLENGE $acme_hook_challenge;
fastcgi_param ACME_TOKEN $acme_hook_token;
include fastcgi.conf;
}
Пример с PHP-FPM#
location @acme_hook_location {
acme_hook example;
root /var/www/dns;
fastcgi_pass unix:/run/php-fpm/php-dns.sock;
fastcgi_index hook.php;
fastcgi_param SCRIPT_FILENAME /var/www/dns/hook.php;
include fastcgi_params;
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;
}
[dns]
listen = /run/php-fpm/php-dns.sock
listen.mode = 0666
user = angie
group = angie
chdir = /var/www/dns
# ...
$_SERVER['...'].ACME в потоковом модуле#
http,
а сам блок stream должен располагаться после блока http
в конфигурации.Пример конфигурации#
# HTTP-часть
http {
# ACME-клиент для потоковой части
acme_client example https://acme-v02.api.letsencrypt.org/directory;
# Сервер для HTTP-проверки
server {
listen 80;
return 444;
}
}
# Потоковая часть
stream {
server {
listen 12345 ssl;
proxy_pass backend_upstream;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
server_name example.com www.example.com;
acme example; # ссылка на ACME-клиент, определенный в HTTP-части
}
upstream backend_upstream {
server 127.0.0.1:54321;
}
}
challenge=dns в директиве acme_client;
тогда сервер будет не нужен.