Application: "Certbot client v.0.12/0.26" for "Let`s Encrypt" (on Python), "Nginx".

"Let’s Encrypt" от ISRG - простой и удобный HTTPS.
Случилось чудо - в конце 2016 года группой "Internet Security Research Group (ISRG)" был запущен сервис простой автоматической и бесплатной выдачи криптографических сертификатов X.509 для SSL/TLS шифрования (HTTPS) под названием "Let’s Encrypt". Зачиналось всё с внутреннего инструментария Mozilla, а сейчас в проекте полноценно участвуют Linux Foundation, Google, Microsoft, Apple, Akamai, Cisco и ещё и ещё. Задачи идентификации сайта в проекте не ставится - цель в обеспечении технической возможности шифрования соединения между web-браузером пользователя и web-сервисом для исключения вмешательства в процесс обмена данных, несанкционированного доступа к ним или подмены таковых. Сертификаты X.509 выдаются всего на три месяца и их, естественно, приходится непрерывно обновлять, запрашивая новые - это составляющая базовой стратегии, направленной в сторону развития технологий защиты данных с максимальной составляющей автоматизации, полностью исключающей ручной труд по валидации и проверке предоставляемых пользователю сведений о защищаемом web-ресурсе.
Первичное получение и последующее автоматическое обновление SSL/TLS-сертификатов для web-сайтов удобно осуществлять с помощью специально для этого предназначенного набора утилит "Certbot client", рекомендуемого ISRG. Разработка ведётся здесь: https://github.com/certbot/certbot , а получить в адаптированном для целевой операционной системы виде это программное обеспечение можно тут: https://certbot.eff.org/
На сайте разработчиков представлено обилие выбора реализаций для разных современных дистрибутивов Linux, но на практике нет смысла выискивать что-то подходящее конкретно под целевую операционную систему, а вполне достаточно загрузить инсталлятор "certbot-auto", представляющий собой обёртку для "certbot" как такового и предназначенный для удовлетворения системных зависимостей (вроде установки и обновления необходимого "Python v3" и "OpenSSL v1") и загрузки набора Python-скриптов самого "certbot". По идее, "certbot-auto" нужно запускать один раз для установки "certbot" и возвращаться к этой процедуре лишь при плановом обновлении ПО web-сервера.
Установка и первичная проверка.
Набор утилит "Certbot client" по умолчанию устанавливается в директорию "/opt/eff.org/certbot/venv", определяемую переменной окружения "$VENV_PATH" в BASH-скрипте "certbot-auto" - при желании её можно переопределить, но я ничего против этого месторасположения не имею:
# mkdir -p /opt/eff.org/certbot-auto
# cd /opt/eff.org/certbot-auto
# wget https://dl.eff.org/certbot-auto
# chmod a+x ./certbot-auto
# cd /opt/eff.org/certbot-auto
# wget https://dl.eff.org/certbot-auto
# chmod a+x ./certbot-auto
Запускаем инсталляцию:
# cd /opt/eff.org/certbot-auto
# ./certbot-auto --install-only
# ./certbot-auto --install-only
Типичный вывод результатов успешной установки:
Bootstrapping dependencies for Debian-based OSes...
....
Fetched 323 kB in 2s (122 kB/s)
....
The following additional packages will be installed:
libssl1.0.0 python-minimal zlib1g-dev
....
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Certbot is installed.
....
Fetched 323 kB in 2s (122 kB/s)
....
The following additional packages will be installed:
libssl1.0.0 python-minimal zlib1g-dev
....
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Certbot is installed.
Кстати, очень и очень рекомендую обратить внимание на возможное предложение установить интеграционные плагины и отказаться от него - мы собираем схему с точными настройками взаимосвязей всех компонентов, где использование автоматических помощников не предполагается:
....
To use the Apache Certbot plugin, augeas needs to be installed from wheezy-backports.
Would you like to enable the wheezy-backports repository [Y/n]? n
....
To use the Apache Certbot plugin, augeas needs to be installed from wheezy-backports.
Would you like to enable the wheezy-backports repository [Y/n]? n
....
Проверяем, запустится ли приложение:
# /opt/eff.org/certbot/venv/bin/certbot --version
На серверах я предпочитаю по возможности удерживать каждую подсистему в изолированном, созданном специально для него пользовательском окружении - также поступим и сейчас:
# useradd --system --home-dir /opt/eff.org/certbot --shell /bin/false --gid www-data certbot
Передаём во владение свежесозданного специализированного пользователя директорию с его программным обеспечением:
# chown -R certbot:root /opt/eff.org/certbot
# chmod -R o-rwx /opt/eff.org/certbot
# chmod -R o-rwx /opt/eff.org/certbot
Заготовим место для хранения настроек и сертификатов:
# mkdir -p /etc/letsencrypt
# chown -R certbot:www-data /etc/letsencrypt
# chown -R certbot:www-data /etc/letsencrypt
Создаём директории для сохранения промежуточных данных и журналов событий:
# mkdir -p /var/lib/letsencrypt
# chown -R certbot:root /var/lib/letsencrypt
# mkdir -p /var/log/letsencrypt
# chown -R certbot:root /var/log/letsencrypt
# chown -R certbot:root /var/lib/letsencrypt
# mkdir -p /var/log/letsencrypt
# chown -R certbot:root /var/log/letsencrypt
При каждом запуске "Certbot client" норовит самостоятельно обновиться, проверяя наличие свежей версии на сайте разработчиков, и жалуется на нехватку прав для изменения системных параметров (а при наличии таковых нежелательным образом меняет структуру привилегий) - так что следует обязательно использовать его с ключом "--no-self-upgrade".
Сразу можно проверить, нет ли на борту каких-нибудь сертификатов, возможно загруженных ранее:
# sudo -u certbot /opt/eff.org/certbot/venv/bin/certbot --no-self-upgrade certificates
Предварительная настройка web-сервера "Nginx".
"Certbot client" поддерживает автоматизацию получения сертификатов путём интеграции с web-серверами через соответствующие плагины, но для понимания сути происходящего есть смысл настроить всё непосредственной правкой конфигурационных файлов, а запускать утилиту в режиме "webroot" (с размещением временных валиадционных данных в файловой системе сайта, для которого запрашивается сертификат).
Создаём локальную директорию, которая доступна для чтения 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 certbot:www-data -R /var/www/letsencrypt
# echo "Let\`s Encrypt" > /var/www/letsencrypt/.well-known/acme-challenge/index.html
# chown certbot:www-data -R /var/www/letsencrypt
Отдельно описываем виртуальную ссылку с зарезервированным ISRG путём к ресурсам "/.well-known/acme-challenge/" для web-сервера "Nginx", которую связываем с локальной директорией для валидационных файлов:
# mkdir -p /etc/nginx/snippets
# vi /etc/nginx/snippets/letsencrypt.conf
# vi /etc/nginx/snippets/letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/letsencrypt;
break;
}
default_type "text/plain";
root /var/www/letsencrypt;
break;
}
В описании каждого сайта, которому требуется поддержка "Let`s Encrypt", внедряем заготовленный блок конфигурации ресурсов:
# vi /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 /etc/nginx/snippets/letsencrypt.conf;
}
listen 80;
server_name example.net;
# Возможный блок перехвата трафика HTTP и перенаправления его в HTTPS
location / {
rewrite ^ https://$host$request_uri permanent;
}
# Включение конфигурации директории верификации Let`s Encrypt
include /etc/nginx/snippets/letsencrypt.conf;
}
Проверяем синтаксическую корректность конфигурации и указываем web-серверу её принять:
# nginx -t
# /etc/init.d/nginx reload
# /etc/init.d/nginx reload
Вариант конфигурации для "Apache2" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Прежде чем приступать к запросу и получению сертификатов как таковых настоятельно рекомендую проверить корректность настройки web-сервера - элементарно удостовериться доступности специально для этого размещённого ".well-known/acme-challenge/index.html" из интернета. На практике в каждой второй конфигурации приходится ещё донастроить web-сервисы, чтобы схема сработала как было задумано:
$ wget -nv -O - http://example.net/.well-known/acme-challenge/index.html
Настройка утилиты "Certbot client".
"Certbot client" складывает актуальные сертификаты в директорию "/etc/letsencrypt/live", а предыдущие в директорию "/etc/letsencrypt/archive". В специальной настройке современная версия клиента практически не нуждается - в первый раз сертификат запрашивается в ручном режиме с указанием параметров сайта, а в последующие запуски с указанием на необходимость обновления сертификатов скрипт будет перебирать все уже имеющиеся и обновлять их при необходимости.
Ряд неизменных параметров запуска утилиты есть смысл вынести в конфигурационный файл:
# vi /etc/letsencrypt/cli.ini
# Задаём адрес почтового ящика, который может быть использован для связи с сервисом
email = support@example.net
# Задаём используемый тип аутентификации
authenticator = webroot
# Указываем тип соединения обмена данными при аутентификации
preferred-challenges = http
# Указываем месторасположение директории, используемой для временных верификационных файлов
webroot-path = /var/www/letsencrypt
# Отключаем автоматическое самообновление утилиты, производимое по умолчанию при каждом её запуске
no-self-upgrade
email = support@example.net
# Задаём используемый тип аутентификации
authenticator = webroot
# Указываем тип соединения обмена данными при аутентификации
preferred-challenges = http
# Указываем месторасположение директории, используемой для временных верификационных файлов
webroot-path = /var/www/letsencrypt
# Отключаем автоматическое самообновление утилиты, производимое по умолчанию при каждом её запуске
no-self-upgrade
Первичный запрос сертификатов и применение их в web-сервисе.
Для каждого web-ресурса нужно осуществить первичный запрос сертификата:
# sudo -u certbot /opt/eff.org/certbot/venv/bin/certbot --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 again. To
non-interactively renew *all* of your certificates, run
"certbot renew"
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 again. To
non-interactively renew *all* of your certificates, run
"certbot renew"
В результате мы получаем примерно такую файловую структуру:
# tree -ug /etc/letsencrypt/live/
/etc/letsencrypt/live/
└── [certbot www-data] example.net
├── [certbot www-data] cert.pem -> ../../archive/example.net/cert1.pem
├── [certbot www-data] chain.pem -> ../../archive/example.net/chain1.pem
├── [certbot www-data] fullchain.pem -> ../../archive/example.net/fullchain1.pem
├── [certbot www-data] privkey.pem -> ../../archive/example.net/privkey1.pem
└── [certbot www-data] README
└── [certbot www-data] example.net
├── [certbot www-data] cert.pem -> ../../archive/example.net/cert1.pem
├── [certbot www-data] chain.pem -> ../../archive/example.net/chain1.pem
├── [certbot www-data] fullchain.pem -> ../../archive/example.net/fullchain1.pem
├── [certbot www-data] privkey.pem -> ../../archive/example.net/privkey1.pem
└── [certbot www-data] README
Для полноты представлений о сути происходящего перед использованием сгенерированного "Certbot"-ом сертификата можно полюбопытствовать его параметрами:
# openssl x509 -text -noout -in /etc/letsencrypt/live/example.net/fullchain.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
03:c6:...:cf:fc
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
Validity
Not Before: Oct 15 03:19:15 2018 GMT
Not After : Jan 13 03:19:15 2019 GMT
Subject: CN=example.net
....
Data:
Version: 3 (0x2)
Serial Number:
03:c6:...:cf:fc
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
Validity
Not Before: Oct 15 03:19:15 2018 GMT
Not After : Jan 13 03:19:15 2019 GMT
Subject: CN=example.net
....
Теперь, когда SSL/TLS-сертификаты готовы, их можно применить в настройках web-сервиса. Для "Nginx" это делается примерно так:
# vi /etc/nginx/sites-enabled/example.net
....
# Перехват запросов к имени нежелательного формата и перенаправление к нужному
server {
listen 443 ssl;
server_name www.example.net;
access_log off;
error_log off;
location / {
rewrite ^ https://example.net$request_uri permanent;
}
# Рекомендуемые обобщённые настройки протокола
ssl on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES256-SHA:RC4:HIGH:!aNULL:!MD5:!kEDH;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:30m;
ssl_session_timeout 1h;
# Сертификаты Let`s Encrypt
ssl_certificate /etc/letsencrypt/live/www.example.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.net/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/www.example.net/chain.pem;
}
# Описание рабочего окружения доступного по HTTPS web-сайта как такового
server {
listen 443 ssl;
server_name example.net;
....
# Рекомендуемые обобщённые настройки протокола
ssl on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES256-SHA:RC4:HIGH:!aNULL:!MD5:!kEDH;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:30m;
ssl_session_timeout 1h;
# Сертификаты Let`s Encrypt
ssl_certificate /etc/letsencrypt/live/example.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.net/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.net/chain.pem;
....
}
# Перехват запросов к имени нежелательного формата и перенаправление к нужному
server {
listen 443 ssl;
server_name www.example.net;
access_log off;
error_log off;
location / {
rewrite ^ https://example.net$request_uri permanent;
}
# Рекомендуемые обобщённые настройки протокола
ssl on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES256-SHA:RC4:HIGH:!aNULL:!MD5:!kEDH;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:30m;
ssl_session_timeout 1h;
# Сертификаты Let`s Encrypt
ssl_certificate /etc/letsencrypt/live/www.example.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.net/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/www.example.net/chain.pem;
}
# Описание рабочего окружения доступного по HTTPS web-сайта как такового
server {
listen 443 ssl;
server_name example.net;
....
# Рекомендуемые обобщённые настройки протокола
ssl on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES256-SHA:RC4:HIGH:!aNULL:!MD5:!kEDH;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:30m;
ssl_session_timeout 1h;
# Сертификаты Let`s Encrypt
ssl_certificate /etc/letsencrypt/live/example.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.net/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.net/chain.pem;
....
}
Естественно, после изменения конфигурации web-сервера таковому необходимо дать указание перечитать настройки:
# nginx -t
# /etc/init.d/nginx reload
# /etc/init.d/nginx reload
Вариант конфигурации для "Apache2" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Иногда web-сервисы запускают от имени специализированного пользователя, вроде "nginx". В таком случае я включаю этого пользователя в группу "www-data", для унификации:
# usermod --append --groups www-data nginx
Автоматизация продления сертификатов.
Как уже упоминалось, сертификаты выдаются только на три месяца - потом их необходимо продлевать. Элементарно запускаем утилиту с соответствующим ключом:
# sudo -u certbot /opt/eff.org/certbot/venv/bin/certbot --config /etc/letsencrypt/cli.ini renew
Скриптом перебираются и обновляются все обнаруженные в директории утилиты "/etc/letsencrypt/" сертификаты, которым до истечения осталось меньше одного месяца. Можно обновить конкретный сертификат, указав его имя, но для автоматизации удобнее прогонять сразу все скопом. Так же удобно запускать утилиту в режиме тестирования, без применения изменений, с помощью ключа "--dry-run". Ключик "--force-renewal" велит обновить сертификаты немедленно, не дожидаясь условного порога в один месяц до истечения срока действия.
С учётом особой умности утилиты "Certbot client" автоматизация обновления сертификатов заключается в её элементарном регулярном запуске. Удобно создать отдельный скрипт, в котором отрабатывать команды использующим сертификаты приложениям перечитать и применить их:
# touch /opt/eff.org/cert-renew.sh
# chmod +x /opt/eff.org/cert-renew.sh
# vi /opt/eff.org/cert-renew.sh
# chmod +x /opt/eff.org/cert-renew.sh
# vi /opt/eff.org/cert-renew.sh
#!/bin/bash
# Запускаем утилиту с указанием обновить имеющиеся сертификаты
sudo -u certbot /opt/eff.org/certbot/venv/bin/certbot --non-interactive --quiet --config /etc/letsencrypt/cli.ini renew
# Даём указание использующему сертификаты web-сервису перечитать конфигурацию
[ -x "$(command -v nginx)" ] && nginx -t > /dev/null 2>&1 && { nginx -s reload; }
exit ${?}
# Запускаем утилиту с указанием обновить имеющиеся сертификаты
sudo -u certbot /opt/eff.org/certbot/venv/bin/certbot --non-interactive --quiet --config /etc/letsencrypt/cli.ini renew
# Даём указание использующему сертификаты web-сервису перечитать конфигурацию
[ -x "$(command -v nginx)" ] && nginx -t > /dev/null 2>&1 && { nginx -s reload; }
exit ${?}
Вариант конфигурации для "Apache2" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Чем больше сертификатов и чем сильнее разброс дат получения таковых, тем чаще нужно запускать обновление. Лично я для моих пяти-десяти сайтов делаю это раз в неделю, каждый вторник:
# vi /etc/crontab
....
# Certificates renew using Let`s Encrypt "Certbot client"
0 0 * * 2 root /opt/eff.org/cert-renew.sh &
# Certificates renew using Let`s Encrypt "Certbot client"
0 0 * * 2 root /opt/eff.org/cert-renew.sh &
Успешный полёт схемы более полутора лет - надеюсь, дальше будет только лучше.
31 марта 2017 в 16:22
31 марта 2017 в 16:22
31 марта 2017 в 20:20