[[ Настройка сертификатов от Let’s Encrypt ]]

Nginx

Настройка сертификатов от Let’s Encrypt

Ubuntu 22.04
nginx/1.18.0

Let’s Encrypt — центр сертификации, предоставляющий бесплатные криптографические сертификаты X.509 для SSL/TLS шифрования.

Однако есть некоторые ограничения, например сертификат выдается сроком на 90 дней.

Существует несколько ACME Client (Automated Certificate Management Environment) утилит для настройки автоматизации процесса.

Настройка GetSSL

getssl - Obtain SSL certificates from the letsencrypt.org ACME server. Реализован на bash

Создание пользователя letsencrypt

useradd letsencrypt -mU -s /bin/bash
chmod 750 /home/letsencrypt

su - letsencrypt
mkdir ~/bin
cd ~/bin/
wget https://raw.githubusercontent.com/srvrco/getssl/master/getssl
chmod +x getssl

Повторно зайти, что бы ~/bin подхватился в PATH

exit
su - letsencrypt 
getssl --help

PATH зависит от дистрибутива, можно прписать вручную

~/.bashrc

export PATH=$PATH:$HOME/bin

Создать конфиг для домена example.com

getssl -c example.com

По умолчанию конфиг размещается в ~/.getssl. В этой папке находятся:

  • getssl.cfg - main config file. Общий конфиг утилиты и конфиг аккаунта.

Нажмите, чтобы отобразить

Нажмите, чтобы скрыть

https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md

An ACME client is represented by an «account key pair». The client uses the private key of this key pair to sign all messages sent to the server. The server uses the public key to verify the authenticity and integrity of messages from the client.

  • example.com/getssl.cfg - domain config file. Папка с именем домена и индивидуальным под него конфигом



Прежде чем начать генерировать сертификаты, убедимся что мы работает со staging средой

~/.getssl/getssl.cfg

CA="https://acme-staging.api.letsencrypt.org"

Сервис имеет ограничение на кол-во запросов в prod и staging

Если сертификат генерируется для домена 2ого уровня example.com, а так же хотим работать с ним как www.example.com, то необходимо указать альтернативные имена SAN (Subject Alternative Name)

~/.getssl/example.com/getssl.cfg

SANS="www.example.com"

При получении сертификата сервис Let’s Encrypt проверяет право владения доменом(ами). Для этого он обратиться к нашему серверу по адресу(ам):

http://example.com/.well-known/acme-challenge/<token file>
http://www.example.com/.well-known/acme-challenge/<token file>

Настраиваем место хранения token файлов

~/.getssl/getssl.cfg

ACL=('/home/letsencrypt/.well-known/acme-challenge')
USE_SINGLE_ACL="true"

Т.к. у нас два домена на подтверждение, то в ACL потребуется указать столько же директорий для сохранения token файлов.
Что бы этого не делать используем опцию USE_SINGLE_ACL
Кроме подтверждения по HTTP, можно использовать FTP, SSH, … см. man настройки ACL
Скрипт сам создаст целевую директорию, если конечно сможет.

Настраиваем создание PEM файла, т.к. по умолчанию такой файл не создается

~/.getssl/getssl.cfg

DOMAIN_PEM_LOCATION="${DOMAIN}.pem" # this is the domain_key, domain cert and CA cert

Я сделал настройки ACL и DOMAIN_PEM_LOCATION в глобальном конфиге

Настройка Nginx (Этап 1)

Сделаем доступной папку acme-challenge на всех доменах

/etc/nginx/sites-enabled/example.com.conf

server {
        server_name example.com www.example.com;
...
        ### letsencrypt
        location /.well-known/acme-challenge {
                allow all;
                root /home/letsencrypt;
        }
...

Не забудем про права, файлы должны быть доступны для Nginx'a, который запущен под пользователем www-data

chown :www-data /home/letsencrypt

Перезагружаем

/etc/init.d/nginx reload


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

su - letsencrypt
getssl example.com

Если появляются ошибки - смотрим и исправляем:

  • Неправильно настроен web сервер, token файл недоступен

getssl: for some reason could not reach http://example.com/.well-known/acme-challenge/Pfommk2UwBNwYWcizkuzZeZHybAztSQ5jcrf9ZIMxn8 - please check it manually

  • Это не ошибка, просто сейчас у меня самоподписанный сертификат, да и пока мы еще в тестовом режиме

getssl: example.com - certificate obtained but certificate on server is different from the new certificate

Тестовые сертификаты сгенерировались

$ ls -la ~/.getssl/example.com/
-rw-r--r-- 1 letsencrypt letsencrypt 2139 Jan 24 18:11 example.com.crt
-rw-r--r-- 1 letsencrypt letsencrypt 1651 Jan 24 18:11 example.com.csr
-rw------- 1 letsencrypt letsencrypt 3243 Jan 24 18:11 example.com.key
-rw-r--r-- 1 letsencrypt letsencrypt 2139 Jan 24 18:11 example.com.pem

Посмотрим на них

openssl rsa -noout -check -in example.com.key
openssl req -noout -text -in example.com.csr
openssl x509 -noout -text -in example.com.crt 
Сертификаты как сертификаты, только издатель не валидный
CN=Fake LE Intermediate X1

Теперь как мы проверили, что все у нас работает, сертификаты получились, переключаемся на prod, для получения валидных

/home/letsencrypt/.getssl/getssl.cfg

#CA="https://acme-staging.api.letsencrypt.org"
CA="https://acme-v01.api.letsencrypt.org"

Генерируем

getssl example.com

Посмотрим на новый сертификат

$ openssl x509 -noout -text -in example.com.crt | grep Iss
Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3

То что нужно!


Настройка Nginx (Этап 2)

Настроим пути к сертификатам

/etc/nginx/sites-enabled/example.com.conf

server {
...
        ssl_certificate     /home/letsencrypt/.getssl/example.com/example.com.pem;
        ssl_certificate_key /home/letsencrypt/.getssl/example.com/example.com.key;

...

Перезагружаем

/etc/init.d/nginx reload

Проверяем через браузер. Так же проверяем через какой-нибудь сервис, например https://www.ssllabs.com/


Настройка CRON

Настроим автоматическое обновление сертификата(ов) по cron'y.

Выданный сертификат годен 3 месяца.

RENEW_ALLOW - количество дней, оставшихся до окончания срока действия сертификата, в этот период getssl будет обновлять сертификат. Т.е. будет 30 дней на обновление.
RELOAD_CMD - команда, которая будет выполнена после обновления файлов сертификата. Перезагрузить nginx нужно для их применения.

su - letsencrypt

~/.getssl/getssl.cfg

RENEW_ALLOW="30"
RELOAD_CMD="sudo /bin/systemctl reload nginx"

Права в sudo

/etc/sudoers.d/letsencrypt

# init.d
letsencrypt ALL=(root) NOPASSWD: /etc/init.d/nginx reload
# systemd
letsencrypt ALL=(root) NOPASSWD: /bin/systemctl reload nginx

Проверим как работает

$ getssl -a
Check all certificates
example.com: certificate is valid for more than 30 days (until Apr 25 18:03:06 2018 GMT)

Срок сертификата еще не вышел и обновляться он не будет, что логично, но все такие проверим через --force

$ getssl -f example.com
Registering account
Verify each domain
Verifying example.com
example.com is already validated
Verification completed, obtaining certificate.
Certificate saved in /home/letsencrypt/.getssl/example.com/example.com.crt
The intermediate CA cert is in /home/letsencrypt/.getssl/example.com/chain.crt
reloading SSL services
 * Reloading nginx configuration [ OK ]
example.com - certificate installed OK on server
certificate obtained for example.com

Перезагрузка сработала. Добавляем в cron

/etc/cron.d/letsencrypt

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/home/letsencrypt/bin
MAILTO="root"

0 9  * * 1  letsencrypt /home/letsencrypt/bin/getssl -a -q


Cертификаты для внутренних сервисов и wildcard

Для ситуации, когда web сервис не доступен из интернета и/или имеет адрес приватной сети,
существует проверка через TXT запись для домена, называемая DNS-01 сhallenge.
Этот метод используется и при подтверждении wildcard сертификатов.
Запись должна называться _acme-challenge и содержать специальный hash код для проверки.

Настройка

~/.getssl/internal-service.example.com/getssl.cfg

VALIDATE_VIA_DNS="true"
DNS_ADD_COMMAND="echo DNS_ADD_COMMAND:"
DNS_DEL_COMMAND="echo DNS_DEL_COMMAND:"

Вместо команды (скрипта) для добавления и удаления записи _acme-challenge, я указал просто echo
т.к. запись _acme-challenge.internal-service.example.com буду создавать руками, через web панель моего регистратора.
Значение хэша, я скопирую из вывода, во время работы скрипта.

Registering account
Verify each domain
Verifying internal-service.example.com
DNS_ADD_COMMAND: internal-service.example.com yyB-EmYONKtLV-RwrrOGz_eMJebXdallCCriieoAG5Y
checking DNS at ns1.nameself.com
checking DNS at ns1.nameself.com for _acme-challenge.internal-service.example.com. Attempt 1/100 gave wrong result,  waiting 10 secs before checking again
 
sleeping 60 seconds before asking the ACME server to check the dns

Затем иду в панель регистратора, вот так будет выглядеть запись

dig ANY _acme-challenge.internal-service.example.com @ns1.nameself.com
 
;; ANSWER SECTION:
_acme-challenge.internal-service.example.com. 7200 IN TXT   "yyB-EmYONKtLV-RwrrOGz_eMJebXdallCCriieoAG5Y"

Через 90 дней, нужно будет снова подтверждать право на пользование домена, т.е. проверка TXT записи с новым хэшем, что бы иметь возможность выпускать сертификаты.
Для автоматизации процесса, есть готовые скрипты https://github.com/srvrco/getssl/tree/master/dns_scripts

Так же можно посмотреть и на другие ACME клиенты, в поисках поддержки нужного регистратора.








Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
209᠎ -14​ =
 
howto/nginx/nginx_letsencrypt.txt · Последнее изменение: 2024/03/14 17:44 — lexa
Gentoo Linux Gentoo Linux Driven by DokuWiki