- PVSM.RU - https://www.pvsm.ru -
Если вдруг вся эта история прошла мимо вас, Let's Encrypt [1] — центр сертификации от некоммерческой организации ISRG, существующий при поддержке EFF [2] и многих компаний, взявшей на себя миссию дать людям бесплатные SSL/TLS сертификаты для сайтов и серверов. Сертификаты от Let's Encrypt уже используются на более чем 10 миллионах доменов [3].
Кроме очевидной бесплатности у сертификатов от Let's Encrypt есть особое, отсутствующее у любых других коммерческих сертификационных центров, достоинство: если вы однажды получили сертификат от Let's Encrypt, то, при прочих равных, это навсегда. Не нужно раз в год-два вручную обновлять сертификаты. Не нужно вообще вспоминать что сертификаты где-то есть. Получил, настроил и забыл!
Внимательный читатель сразу захочет возразить: как же так, ведь известно что сертификаты выдаются со сроком действия в три месяца? Всё дело в автоматическом обновлении сертификатов, которое возможно при полном отсутствии действий со стороны человека.
Организации автоматического обновления сертификатов в статье уделено пристальное внимание, с тем чтобы вы могли в полной мере оценить это принципиальное преимущество Let's Encrypt.
На сайте EFF есть краткие инструкции по использованию Certbot [4], рекомендуемой программы для получения сертификатов, но они скорей рассчитаны на тех, кто заходит на свой сервер по SSH лишь по острой необходимости. Более подробная документация тоже есть [5], но пока всю ее прочитаешь и найдешь всё то, что действительно нужно знать… К тому же, в ней не рассмотрены некоторые важные стратегические вопросы использования сертификатов.
Очевидно, нужна короткая и понятная инструкция для тех, кто привычен к серверной консоли, но хочет во всём разобраться без излишних трат времени.
Из этой статьи вы узнаете...
Всё знаете про SNI? Читайте сразу про установку. [6]
В инструкциях ниже я исхожу из того что ваши сайты будут использовать SNI. Это расширение протокола TLS позволяет браузерам сообщить желаемое имя сайта до получения и проверки SSL сертификата от сервера. Благодаря SNI вы можете разместить сколько угодно сайтов за HTTPS на одном IP. Но не всё так просто — иначе бы зачем я об этом писал?
Есть ряд старых браузеров в принципе не поддерживающих SNI. В их число входят любые версии IE в уже заброшенном Windows XP [12], встроенный браузер в Android 2.3 и 2.2 из 2010 года [13], а также некоторые другие более экзотические браузеры и библиотеки типа Java версии 1.6 [14] и Python до версии 2.7.9 [15].
Если вы всё-таки хотите чтобы ваш сайт открывался в IE в Windows XP, то одним отказом от SNI эта проблема не решается. Нужно специальным образом подбирать шифры [16], уже отказываясь от forward secrecy [17] и рискуя получить низкую оценку от SSL Labs [18]. Как можно догадаться, этот вопрос заслуживает отдельного обсуждения хотя бы потому что пользователям IE под XP можно посочувствовать — у них уже не открывается половина интернета!
Еще год назад от перехода на SNI вас могла бы удержать ограниченная поддержка этой технологии некоторыми поисковыми ботами типа Bing, но сейчас, с появлением десятков сайтов с бесплатными сертификатами от Cloudflare, что без SNI не открываются, бот Bing (что легко проверить [19]), и боты других основных поисковиков [20], пришли в согласие с реальность. Сейчас за это можно не волноваться. Отмечу, что у Googlebot таких проблем не было никогда.
Другим поводом для волнений могут быть различные средства доступа к API вашего сайта. Если у вас давно есть API, то есть небольшой шанс что среди ваших клиентов есть какие-то, использующие устаревшие версии Java или Python. Если у вас таких нет, то не о чем переживать. Если же есть — мои соболезнования.
Это просто. Вам не нужно постоянно держать в голове факты о выданных сертификатах. Для какого домена сертификат был выдан первым. К какому сертификату нужно добавлять еще домены [21]. И так далее… Ни о чем таком со SNI не нужно думать.
Например, так можно посмотреть домены в сертификате Тематических Медиа:
true | openssl s_client -showcerts -connect habrahabr.ru:443 2>&1 |
openssl x509 -text | grep -o 'DNS:[^,]*' | cut -f2 -d:
Если вы читаете этот текст из будущего, когда Certbot уже есть в Debian stable без обиняков и оговорок, то всё просто:
apt-get install certbot
Либо используйте aptitude
или другой пакетный менеджер вашего дистрибутива.
Если у вас еще в ходу актуальный на конец 2016 года Debian stable "jessie", то всё лишь немного сложнее.
Нужно подключить Debian Backports, добавив строчку в /etc/apt/sources.list
:
deb http://ftp.debian.org/debian/ jessie-backports main contrib non-free
Теперь можно устанавливать с указанием источника:
apt-get update
apt-get install certbot -t jessie-backports
(Раздел актуален пока только stretch не стал stable.)
Если у вас какой-то другой дистрибутив, то дополнительные инструкции по установке есть на официальном сайте Certbot [4]. Если обходиться без пакетного менеджера, то обычно установка сводится к...
wget -O /usr/local/bin/certbot-auto https://dl.eff.org/certbot-auto
chmod +x /usr/local/bin/certbot-auto
ln -s /usr/local/bin/certbot-auto /usr/local/bin/certbot
Везде ниже вместо команды certbot
можно использовать команду certbot-auto
.
Мы будем получать сертификаты по методу webroot без перенастройки или остановки веб-сервера, под которым подразумевается nginx. Нам нужен какой-то каталог, в который certbot
будет писать свои файлы, и какой должны быть доступен из сети удостоверяющему серверу согласно протокола ACME [22].
Чтобы не писать каждый раз длинную строку из опций, а еще лучше — не вспоминать о них, запишем основные настройки в файл конфигурации, который certbot
ожидает найти в /etc/letsencrypt/cli.ini
:
authenticator = webroot
webroot-path = /var/www/html
post-hook = service nginx reload
text = True
Последняя директива нужна чтобы избавить нас от прелестей и красивостей ncurses, что нужно чтобы вы могли сравнить вывод команд здесь, в этой статье, и у себя.
Также нам нужно мягко перезагрузить nginx (без перерыва в обслуживании) при успешном обновлении сертификатов. Конечно же ничего не мешает в этот же момент перезапускать и другие сервисы вроде Postfix, использующие полученные сертификаты (команды перечисляются как обычно, через точку с запятой).
Ожидается что certbot
будет создавать необходимые для проверки прав на домен файлы в подкаталогах ниже по иерархии к указанному. Вроде таких:
/var/www/html/.well-known/acme-challenge/example.html
Эти файлы должны будут быть доступны из сети на целевом домене по крайней мере по HTTP:
http://www.example.com/.well-known/acme-challenge/example.html
Для следующих проверок создадим какой-то такой файл:
mkdir -p /var/www/html/.well-known/acme-challenge
echo Success > /var/www/html/.well-known/acme-challenge/example.html
Регистрацию нужно сделать только один раз:
certbot register --email me@example.com
Здесь ничего сложного.
В общем случае для получения сертификата необходимо во всех блоках server
добавить следующий блок до других блоков location
:
location /.well-known {
root /var/www/html;
}
Понятно, что вписывать для каждого сайта такой блок явно — это моветон, потому создадим файл /etc/nginx/acme
с содержанием блока выше.
# cat /etc/nginx/acme
location /.well-known {
root /var/www/html;
}
Затем для каждого домена и поддомена, для которых нужно получить сертификаты, в блоке server
перед всеми блоками location
укажем:
include acme;
Хосты-редиректоры (например, с голого домена на www) можно пропустить. ACME сервер обязан учитывать стандартную переадресацию. Подробней об этом ниже. [23]
Перезагрузим nginx и проверим что наш тестовый файл виден:
# service nginx reload
# curl -L http://www.example.com/.well-known/acme-challenge/example.html
Success
После проверки лучше удалить тестовый файл — certbot
любит удалять за собой всё лишнее, а такой файл будет мешать и вызывать сообщение об ошибке (Unable to clean up challenge directory).
rm /var/www/html/.well-known/acme-challenge/example.html
Теперь у нас всё готово чтобы получить наш первый сертификат [8].
Как было уже сказано, ACME сервер Boulder учитывает переадресацию с кодами 301 и 302 [24]. В этом смысле не имеет значения где, в конечном счете, находятся файлы, требуемые для прохождения проверок. Переадресация возможна даже на нестандартные порты [25], без ограничений по конечному протоколу HTTP или HTTPS. Сами Let's Encrypt рекомендуют использовать переадресацию для создания единой точки проверки прав на домены [26].
Если вы можете получить эти файлы с помощью curl
с ограничением в десять переадресаций, то и Boulder эти файлы увидит. Не должно быть никаких ограничений по IP адресам [27].
curl --location --max-redirs 10 http://example.com/.well-known/acme-challenge/example.html
Это удобно если у вас сложная структура переадресаций между разными версиями сайтов. Должно быть достаточно подключить тот блок с location
только на основном сайте для получения сертификатов для всех остальных.
$ curl --head --silent --location --max-redirs 10 http://somewhere.example.net/... | grep ^HTTP
HTTP/1.1 301 Moved Permanently
HTTP/1.1 301 Moved Permanently
HTTP/1.1 200 OK
Проверка всегда начинается с запроса по протоколу HTTP на 80 порту.
Если у вас уже все сайты работают по HTTPS, то вся схема будет работать если у вас настроен переадресующий сервер на 80 порту, сохраняющий $request_uri
в ответе.
Другое дело что можно сократить путь и подключить наш блок с location
в умолчальном сервере для 80 порта, который делает переадресацию на HTTPS. Тогда не нужно будет ничего дописывать в конфиги отдельных сайтов.
Пример конфигурации такого переадресующего всё-подряд-на-HTTPS сервера:
server {
listen server.example.com:80 default_server;
include acme;
location / {
return 301 https://$host$request_uri;
}
}
Такой конфиг стоит определить в /etc/nginx/conf.d/default.conf
, в стороне от конфигов конкретных сайтов.
Сервер запускаем явно на внешнем IP чтобы не перенастраивать Apache на другой порт. Если для вас это не проблема, то указание имени сервера в директиве listen
можно пропустить.
Типичный пример — сертификат для SMTP или IMAP серверов. Либо используйте универсальный переадресатор что выше, либо...
server {
server_name smtp.example.com imap.example.com;
listen server.example.com:80;
include acme;
location / {
return 404;
}
}
К сожалению, протокол ACME требует чтобы такой сервер был доступен во время каждой проверки. Это практически эквивалентно постоянной доступности, ввиду требования получения и обновления сертификатов без перезагрузки сервера. Не удаляйте такой конфиг после получения сертификата.
У Let's Encrypt есть лимиты на количество обращений за сертификатами [28], потому сначала попробуем получить необходимый сертификат в режиме для тестов:
certbot certonly --dry-run -d example.com -d www.example.com
В конце программа должна отчитаться об успешной работе:
The dry run was successful.
Теперь можно смело получать сертификат уже в самом деле. Не забудьте явно указать все необходимые поддомены, такие как www.
# certbot certonly -d example.com -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.com
http-01 challenge for www.example.com
Using the webroot path /var/www/html for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0001_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0001_csr-certbot.pem
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/example.com/fullchain.pem. Your cert will
expire on 2017-04-01. 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"
Ура! С получением сертификата закончено!
Если вы вдруг забыли указать поддомен www
, или вам нужно добавить другой домен или поддомен в сертификат (которых может быть до 100 в одном сертификате [28]), то это легко сделать после получения сертификата. Просто запустите команду еще раз, добавив требуемое имя:
certbot certonly -d example.com -d www.example.com -d shop.example.com
Вам будет безальтернативно предложено добавить этот домен в сертификат. Если хочется избежать вопросов, то можно сразу указать одобряющий такое поведение ключ:
certbot certonly --expand -d example.com -d www.example.com -d shop.example.com
Операцию можно повторять.
Убедимся что полученный сертификат — именно тот, что нам нужен:
# openssl x509 -text -in /etc/letsencrypt/live/example.com/cert.pem
Certificate:
Signature Algorithm: ...
Validity
Not Before: Jan 3 06:00:00 2017 GMT
Not After : Apr 3 06:00:00 2017 GMT
X509v3 extensions:
...
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
Или, если подробности вам не нужны:
cat /etc/letsencrypt/live/*/cert.pem | openssl x509 -text |
grep -o 'DNS:[^,]*' | cut -f2 -d:
Команда должна вывести список доменов в сертификате.
Certbot не перезаписывает сертификаты, а заменяет их ссылками на самые актуальные варианты сертификатов в определенном каталоге, одноименном с первым доменом сертификата (т.е. CN
).
Давайте посмотрим что за файлы у нас есть:
# find /etc/letsencrypt/live/ -type l
/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/chain.pem
/etc/letsencrypt/live/example.com/privkey.pem
/etc/letsencrypt/live/example.com/cert.pem
С этим знанием мы можем задать настройки SSL для nginx:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
Как видите, cert.pem
нигде в конфиге не используется, и это не ошибка. Для nginx он не нужен.
Полный рабочий пример конфига:
server {
server_name www.example.com;
listen www.example.com:443 ssl; # default_server;
# выше можно добавить default_server для клиентов без SNI
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
resolver 127.0.0.1 8.8.8.8;
# исключим возврат на http-версию сайта
add_header Strict-Transport-Security "max-age=31536000";
# явно "сломаем" все картинки с http://
add_header Content-Security-Policy "block-all-mixed-content";
# далее всё что вы обычно указываете
#location / {
# proxy_pass ...;
#}
}
Конфиг для переадресации с голого домена без www:
server {
server_name example.com;
listen example.com:443 ssl;
access_log off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
resolver 127.0.0.1 8.8.8.8;
add_header Strict-Transport-Security "max-age=31536000";
expires max;
return 301 https://www.example.com$request_uri;
}
Подразумевается что вы используете какой-то локальный сервер для кеширования DNS запросов. Если это не так, то 127.0.0.1
в директиве resolver
нужно заменить на IP используемого DNS сервера.
Настройки шифров и прочее подобное (ssl_dhparam
, ssl_session_cache
) лучше держать вне конфигов отдельных серверов.
Сертификаты выдаются на три месяца. Не на полгода, не на год, а лишь на три месяца. Естественно это вызывает вопросы. Нужно ли проходить всю эту процедуру через три месяца? Нужно ли это делать всегда до искончания веков? Может стоит всё-таки вложиться в платный сертификат чтобы забыть об этом всем и не воспоминать пару лет?
Но нет, не спешите искать платежные средства! Как и было обещано в начале статьи, с обновлением сертификатов проблем нет.
Если у вас Debian, то нужно лишь дописать к вызову certbot
в /etc/cron.d/certbot
ключ --allow-subset-of-names
:
# последняя строка в /etc/cron.d/certbot
# было certbot -q renew, а надо
certbot -q renew --allow-subset-of-names
Если у вас не Debian или нет файла, то добавим в crontab
от root
одну лишь строчку (sudo crontab -e
):
42 */12 * * * certbot renew --quiet --allow-subset-of-names
Согласно рекомендаций Let's Encrypt следует пытаться обновить сертификаты два раза в день. Делать это нужно в случайным образом выбранную минуту того часа, а значит вам нужно заменить 42
в этой строке на другое число в диапазоне между 0
и 59
. Либо вы можете поступить так как это делается в /etc/cron.d/certbot
.
В этой команде ключ --allow-subset-of-names
нужен чтобы Certbot пытался получить сертификаты для частичного набора доменов.
Например, были у вас на сервере были сайты www.example.com и shop.example.com, проходящие под одним сертификатом, но потом вы перенесли shop.example.com на другой сервер. Если такой ключ не указать, то Certbot упадет с ошибкой при попытке подтвердить владение shop.example.com, не получив для вас вообще никакого сертификата. Сертификат истечет и ваш сайт уйдет в оффлайн. С этим ключем вы всё же получите сертификаты хотя бы для частичного набора доменов, оставив ваши сайты в сети.
Нашли ошибку? Напишите в личку, пожалуйста. [29]
Автор: alexkbs
Источник [30]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/nginx/229757
Ссылки в тексте:
[1] Let's Encrypt: https://letsencrypt.org/
[2] при поддержке EFF: https://www.eff.org/ru/deeplinks/2014/11/certificate-authority-encrypt-entire-web
[3] на более чем 10 миллионах доменов: https://letsencrypt.org/stats/
[4] краткие инструкции по использованию Certbot: https://certbot.eff.org/
[5] подробная документация тоже есть: https://certbot.eff.org/docs/using.html#
[6] настроить Certbot: #ustanovka-certbot
[7] как настроить nginx для получения сертификатов: #podgotovim-nginx-k-polucheniyu-sertifikatov
[8] Как получать сертификаты: #poluchaem-sertifikaty
[9] как проверить полученный сертификат: #proverim-poluchennyy-sertifikat
[10] Как установить сертификат: #ustanovka-i-ispolzovanie-sertifikatov
[11] обновлять сертификаты: #prodlenie-sertifikatov
[12] уже заброшенном Windows XP: https://support.microsoft.com/en-us/help/14223/windows-xp-end-of-support
[13] Android 2.3 и 2.2 из 2010 года: https://ru.wikipedia.org/wiki/%D0%98%D1%81%D1%82%D0%BE%D1%80%D0%B8%D1%8F_%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D0%B9_Android
[14] Java версии 1.6: http://bugs.java.com/view_bug.do?bug_id=6985179
[15] Python до версии 2.7.9: https://docs.python.org/2/library/ssl.html#ssl.HAS_SNI
[16] подбирать шифры: https://github.com/client9/sslassert/wiki/IE-Supported-Cipher-Suites#internet-explorer-7-8-windows-xp
[17] forward secrecy: https://ru.wikipedia.org/wiki/Perfect_forward_secrecy
[18] низкую оценку от SSL Labs: https://www.ssllabs.com/ssltest/
[19] что легко проверить: https://www.bing.com/webmaster
[20] боты других основных поисковиков: https://www.ssllabs.com/ssltest/clients.html
[21] добавлять еще домены: #esli-nuzhno-dobavit-poddomen-ili-domen-v-sertifikat
[22] ACME: https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment
[23] Подробней об этом ниже.: #o-pereadresacii-s-kodami-301-i-302
[24] с кодами 301 и 302: https://github.com/letsencrypt/boulder/blob/d4902820ca212aeb0f4e14aea72a2b2d410d1a46/va/va.go#L217
[25] на нестандартные порты: https://github.com/letsencrypt/boulder/blob/d4902820ca212aeb0f4e14aea72a2b2d410d1a46/va/va.go#L231
[26] Let's Encrypt рекомендуют использовать переадресацию для создания единой точки проверки прав на домены: https://letsencrypt.org/docs/integration-guide/#picking-a-challenge-type
[27] никаких ограничений по IP адресам: https://letsencrypt.org/docs/integration-guide/#lets-encrypt-ips
[28] лимиты на количество обращений за сертификатами: https://letsencrypt.org/docs/rate-limits/
[29] Напишите в личку, пожалуйста.: https://habrahabr.ru/conversations/alexkbs/
[30] Источник: https://habrahabr.ru/post/318952/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.