Настройка сертификатов от 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. Общий конфиг утилиты и конфиг аккаунта.
- example.com/getssl.cfg - domain config file. Папка с именем домена и индивидуальным под него конфигом
Прежде чем начать генерировать сертификаты, убедимся что мы работает со staging средой
~/.getssl/getssl.cfg
CA="https://acme-staging.api.letsencrypt.org"
Если сертификат генерируется для домена 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 клиенты, в поисках поддержки нужного регистратора.
Обсуждение