UMGUM.COM (лучше) 
 • Карта сайта

Let‘s Encrypt ( Настройка подсистемы получения и автоматического обновления криптографических сертификатов X.509 для TLS шифрования в протоколе HTTPS. )

24 марта 2017

OS: Debian Wheezy/Jessie, Ubuntu LTS 14/16, Fedora 23/24/25.
Application: "Certbot client v.0.12.0" for Let`s Encrypt, on Python.

Случилось чудо - в конце 2016 года группой "Internet Security Research Group (ISRG)" был запущен сервис простой автоматической и бесплатной выдачи криптографических сертификатов X.509 для TLS шифрования (HTTPS) под названием "Let’s Encrypt". Зачиналось всё с внутреннего инструментария Mozilla, а сейчас в проекте полноценно участвуют Linux Foundation, Google, Microsoft, Apple, Akamai, Cisco и ещё и ещё. Задачи идентификации сайта в проекте не ставится - цель в обеспечении технической возможности шифрования соединения между web-браузером пользователя и web-сервисом для исключения вмешательства в процесс обмена данных, несанкционированного доступа к ним или подмены таковых. Сертификаты X.509 выдаются всего на три месяца и их, естественно, приходится непрерывно обновлять, запрашивая новые - это составляющая базовой стратегии, направленной в сторону развития технологий защиты данных с максимальной автоматизацией, полностью исключающей ручной труд по валидации и проверке предоставляемых пользователю сведений о защищаемом web-ресурсе.

Автоматическое обновление, да и вообще получение сертификатов для web-сайтов, удобно осуществлять с помощью специально для этого предназначенной утилиты "Certbot client", рекомендуемой ISRG. Разработка ведётся здесь: https://github.com/certbot/certbot , а получить в адаптированном для целевой операционной системы виде эту утилиту можно тут: https://certbot.eff.org/ .

Утилита написана на языке программирования Python и, хотя на сайте разработчиков представлено обилие выбора реализации для разных современных дистрибутивов Linux, вполне достаточно загрузить подходящий большинству автоматически подстраиваемый вариант:

# mkdir -p /opt/letsencrypt
# cd /opt/letsencrypt
# wget https://dl.eff.org/certbot-auto
# chmod a+x certbot-auto

Скрипт норовит самостоятельно обновиться при каждом его запуске, проверяя наличие свежей версии на сайте разработчиков, так что размещать его в "/usr/bin" или "/usr/local/bin" мне не хотелось бы - оставим его в месте для всякой всячины.


Вот типичное действие при запуске скрипта - он автоматически обновляется и доустанавливает недостающие программные пакеты:

Upgrading certbot-auto 0.11.1 to 0.12.0...
Replacing certbot-auto...
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Saving debug log to /var/log/letsencrypt/letsencrypt.log

Чтобы избежать повреждения в процессе автоматического обновления существующей нетиповой конфигурации программного обеспечения на сервере утилиту есть смысл использовать с ключом "--no-self-upgrade".

Сразу можно запустить утилиту и посмотреть, нет ли на борту каких-нибудь сертификатов, возможно загруженных ранее:

# ./certbot-auto --no-self-upgrade certificates

"Certbot client" поддерживает автоматизацию получения сертификатов путём интеграции с web-серверами через соответствующие плагины, но для начала и вообще понимания сути происходящего есть смысл настроить всё непосредственной правкой конфигурационных файлов, а запускать утилиту в режиме "webroot" (с размещением временных валиадционных данных в файловой системе сайта, для которого запрашивается сертификат). Далее рассмотрим эту конфигурацию для Nginx.

Создаём локальную директорию, которая доступна для чтения web-серверу, куда утилита "Certbot client" будет укладывать временные валидационные файлы, укладывая туда заодно тестовую HTML-страничку:

# mkdir -p /var/www/letsencrypt/.well-known/acme-challenge/
# echo "Let\`s Encrypt" > /var/www/letsencrypt/.well-known/acme-challenge/index.html
# chown www-data:www-data -R /var/www/letsencrypt

Отдельно описываем виртуальную ссылку с зарезервированным именем для web-сервера, которую связываем с локальной директорией для валидационных файлов:

# touch /etc/nginx/letsencrypt.conf

location ~* /.well-known/acme-challenge/ {
  default_type "text/plain";
  root /var/www/letsencrypt;
  break;
}

Во всех конфигурациях web-серверов включаем описания виртуальной ссылки в блоке для HTTP, примерно таким образом:

# cat /etc/nginx/sites-enabled/example.net

server {
  listen 80;
  server_name example.net;

  # Возможный блок перехвата трафика HTTP и перенаправления его в HTTPS
  location / {
    rewrite ^ https://$host$request_uri permanent;
  }

  # Включение конфигурации директории верификации Let`s Encrypt
  include letsencrypt.conf;
}

# /etc/init.d/nginx reload

Прежде чем приступать к запросу и получению сертификатов как таковых настоятельно рекомендую проверить корректность настройки web-сервера - элементарно удостовериться доступности специально для этого размещённого ".well-known/acme-challenge/index.html" из интернета. На практике в каждой второй конфигурации приходится ещё донастроить web-сервисы, чтобы схема сработала как было задумано.

"Certbot client" складывает актуальные сертификаты в директорию "/etc/letsencrypt/live", а предыдущие в директорию "/etc/letsencrypt/archive". В специальной настройке современная версия клиента практически не нуждается - в первый раз сертификат запрашивается в ручном режиме с указанием параметров сайта, а в последующие запуски с указанием на необходимость обновления сертификатов скрипт будет перебирать все уже имеющиеся и обновлять их при необходимости.

Ряд неизменных параметров запуска утилиты есть смысл вынести в конфигурационный файл:

# touch /etc/letsencrypt/cli.ini

# Задаём адрес почтового ящика, который может быть использован для связи с сервисом
email = support@example.net

# Задаём используемый тип аутентификации
authenticator = webroot

# Указываем тип соединения обмена данными при аутентификации
preferred-challenges = http

# Указываем месторасположение директории, используемой для временных верификационных файлов
webroot-path = /var/www/letsencrypt

# Отключаем автоматическое самообновление утилиты, производимое по умолчанию при каждом её запуске
no-self-upgrade

Для каждого web-ресурса нужно сделать первичный запрос сертификата:

# ./certbot-auto --config /etc/letsencrypt/cli.ini certonly -d example.net

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.net
Using the webroot path /var/www/letsencrypt for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0005_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0005_csr-certbot.pem

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.net/fullchain.pem. Your cert will
   expire on 2017-06-19. To obtain a new or tweaked version of this
   certificate in the future, simply run certbot-auto again. To
   non-interactively renew *all* of your certificates, run
   "certbot-auto renew"

В результате мы получаем примерно такую файловую структуру:

/etc/letsencrypt/live/
  ../example.net/
    ../cert.pem
    ../chain.pem
    ../fullchain.pem
    ../privkey.pem

Теперь, когда сертификаты готовы, их можно применить в настройках web-сервиса. Для Nginx это делается примерно так:

# cat /etc/nginx/sites-enabled/example.net

....
server {
  listen  443 ssl;
  server_name example.net;
  ....

  # Рекомендуемые обобщённые настройки протокола
  ssl_dhparam          /etc/nginx/ssl/dhparam.pem;
  ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers          AES256-SHA:RC4:HIGH:!aNULL:!MD5:!kEDH;
  ssl_session_cache    shared:SSL:10m;
  ssl_session_timeout  5m;
  ssl_prefer_server_ciphers  on;

  # Сертификаты Let`s Encrypt
  ssl_certificate      /etc/letsencrypt/live/example.net/fullchain.pem;
  ssl_certificate_key  /etc/letsencrypt/live/example.net/privkey.pem;
  ....
}

Естественно, после изменения конфигурации web-сервера таковому необходимо дать указание перечитать настройки:

# /etc/init.d/nginx reload

Иногда web-сервисы запускают от имени специализированного пользователя, вроде "nginx". В таком случае я включаю этого пользователя в группу "www-data", для унификации:

# usermod --append --groups www-data nginx

Как уже упоминалось, сертификаты выдаются только на три месяца - потом их необходимо продлевать. Элементарно запускаем утилиту с соответствующим ключом:

# ./certbot-auto --config /etc/letsencrypt/cli.ini renew

Скриптом перебираются и обновляются все обнаруженные в директории утилиты "/etc/letsencrypt/" сертификаты, которым до истечения осталось меньше одного месяца. Можно обновить конкретный сертификат, указав его имя, но для автоматизации удобнее прогонять сразу все скопом. Так же удобно запускать утилиту в режиме тестирования, без применения изменений, с помощью ключа "--dry-run". Ключик "--force-renewal" велит обновить сертификаты немедленно, не дожидаясь условного порога в один месяц до истечения срока действия.

С учётом особой умности утилиты "Certbot client" автоматизация обновления сертификатов заключается в её элементарном регулярном запуске. Удобно создать отдельный скрипт, в котором отрабатывать команды использующим сертификаты приложениям перечитать и применить их:

# touch /opt/letsencrypt/cert-renew.sh
# chmod +x /opt/letsencrypt/cert-renew.sh

# cat /opt/letsencrypt/cert-renew.sh

#!/bin/bash

# Запускаем утилиту с указанием обновить имеющиеся сертификаты
/opt/letsencrypt/certbot-auto --non-interactive --quiet --config /etc/letsencrypt/cli.ini renew

# Даём указание использующему сертификаты web-сервису перечитать конфигурацию
nginx -s reload

exit 0

Чем больше сертификатов и чем сильнее разброс дат получения таковых, тем чаще нужно запускать обновление. Лично я для моих пяти сайтов делаю это раз в неделю, каждый вторник:

# cat /etc/crontab

....
# Certificates renew using Let`s Encrypt "Certbot client"
0 0  * * 2  root /opt/letsencrypt/cert-renew.sh &

По хорошему, после объяснения общих принципов работы и приведения примеров эксплуатации, надо бы рассмотреть методы изоляции сервиса от несущей системы и соседствующих приложений - чаще это элементарный запуск от имени специально созданного непривилегированного пользователя. Беда в том, что на данный момент скрипт официально рекомендуемой утилиты "Certbot client" требует для своей работы полноценных прав суперпользователя, обращаясь к разного рода системным службам, и наотрез отказывается запускаться в ограниченной среде. Это нехорошо, и даже странно - но с этим придётся пока пожить.


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )