Application: "Certbot client v.0.12/1.0" for "Let`s Encrypt" (on Python), "Nginx".
Случилось чудо - в конце 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" поддерживает автоматизацию получения сертификатов путём интеграции с 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
При каждом запуске "Certbot client" норовит самостоятельно обновиться, проверяя наличие свежей версии на сайте разработчиков, и жалуется на нехватку прав для изменения системных параметров (а при наличии таковых нежелательным образом меняет структуру привилегий) - так что следует обязательно использовать его с ключом "--no-self-upgrade".
Сразу можно проверить, нет ли на борту каких-нибудь сертификатов, возможно загруженных ранее:
# sudo -u certbot /opt/eff.org/certbot/venv/bin/certbot --no-self-upgrade certificates
Предварительная настройка web-сервера "Nginx".
Отдельно описываем виртуальную ссылку с зарезервированным 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 ~* ^/(?!(\.well-known)) {
rewrite ^ https://$host$request_uri permanent;
}
# Включение конфигурации директории верификации Let`s Encrypt
include /etc/nginx/snippets/letsencrypt.conf;
}
listen 80;
server_name example.net;
# Возможный блок перехвата трафика HTTP и перенаправления его в HTTPS
location ~* ^/(?!(\.well-known)) {
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" рассматривается отдельно.
Вариант конфигурации для "Lighttpd" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Zimbra" рассматривается отдельно.
Вариант конфигурации для "Lighttpd" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Zimbra" рассматривается отдельно.
Прежде чем приступать к запросу и получению сертификатов как таковых настоятельно рекомендую проверить корректность настройки 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
# Указываем месторасположение директории, используемой для временных верификационных файлов
# (используется при аутентификации посредством плагина "webroot")
webroot-path = /var/www/letsencrypt
# Отмечаем, что мы читали лицензионное соглашение и уже согласились с ним
agree-tos
# Отключаем автоматическое самообновление утилиты
no-self-upgrade
email = support@example.net
# Указываем месторасположение директории, используемой для временных верификационных файлов
# (используется при аутентификации посредством плагина "webroot")
webroot-path = /var/www/letsencrypt
# Отмечаем, что мы читали лицензионное соглашение и уже согласились с ним
agree-tos
# Отключаем автоматическое самообновление утилиты
no-self-upgrade
Первичный запрос сертификатов и применение их в web-сервисе.
Для каждого web-ресурса нужно осуществить первичный запрос сертификата:
# sudo -u certbot /opt/eff.org/certbot/venv/bin/certbot --config /etc/letsencrypt/cli.ini certonly --webroot --preferred-challenges http-01 -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" рассматривается отдельно.
Вариант конфигурации для "Lighttpd" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Courier Mail" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Zimbra" рассматривается отдельно.
Вариант конфигурации для "Lighttpd" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Courier Mail" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Zimbra" рассматривается отдельно.
Иногда 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" рассматривается отдельно.
Вариант конфигурации для "Lighttpd" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Courier Mail" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Zimbra" рассматривается отдельно.
Вариант конфигурации для "Lighttpd" рассматривается отдельно.
Вариант конфигурации для комбайна "GitLab" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Courier Mail" рассматривается отдельно.
Вариант конфигурации для почтового сервера "Zimbra" рассматривается отдельно.
Чем больше сертификатов и чем сильнее разброс дат получения таковых, тем чаще нужно запускать обновление. Лично я для моих пяти-десяти сайтов делаю это раз в неделю, каждый вторник:
# 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