Особливості використання сертифікатів від let's Encrypt і спосіб налаштування nginx

image
Якщо раптом вся ця історія пройшла повз вас, let's Encrypt — центр сертифікації від некомерційної організації ISRG, існуючий за підтримки EFF та багатьох компаній, яка взяла на себе місію дати людям безкоштовні SSL/TLS сертифікати для сайтів і серверів. Сертифікати від let's Encrypt вже використовуються на більш ніж 10 мільйонів доменів.
Крім очевидної безкоштовності в сертифікатів від let's Encrypt є особливе, відсутнє у будь-яких інших комерційних сертифікаційних центрів, гідність: якщо ви одного разу отримали сертифікат від let's Encrypt, то, при інших рівних, це назавжди. Не треба раз у рік-два вручну оновлювати сертифікати. Не треба взагалі згадувати що сертифікати десь є. Отримав, налаштував і забув!
Уважний читач відразу захоче заперечити: як же так, адже відомо що сертифікати видаються з терміном дії на три місяці? Вся справа в автоматичному оновленні сертифікатів, яке можливе при повній відсутності дій з боку людини.
Організації автоматичного оновлення сертифікатів у статті приділено пильну увагу, з тим щоб ви могли повною мірою оцінити це принципова перевага let's Encrypt.
Чому ця стаття
На сайті EFF є короткі інструкції по використанню Certbot, рекомендованої програми для отримання сертифікатів, але вони скоріше розраховані на тих, хто заходить на свій сервер SSH лише за гострої необхідності. Більш докладна документація теж є, але поки всю її прочитаєш і знайдеш все те, що дійсно потрібно знати… До того ж, у ній не розглянуті деякі важливі стратегічні питання використання сертифікатів.
Очевидно, потрібна коротка і зрозуміла інструкція для тих, хто звичний до серверній консолі, але хоче в усьому розібратися без зайвих витрат часу.
Зміст
З цієї статті ви дізнаєтеся...
  1. Як встановити налаштувати Certbot для регулярного використання.
  2. Що вимагається від nginx і як налаштувати nginx для отримання сертифікатів.
  3. Як отримувати сертифікати і як перевірити отриманий сертифікат.
  4. Як встановити сертифікат від let's Encrypt в nginx.
  5. Як автоматично поновлювати сертифікати.
Caveat emptor
Все знаєте про SNI? Читайте відразу про установку.
В інструкціях нижче я виходжу з того що ваші сайти будуть використовувати SNI. Це розширення протоколу TLS дозволяє браузерам повідомити бажане ім'я сайту до отримання та перевірки SSL сертифікату від сервера. Завдяки SNI ви можете розмістити скільки завгодно сайтів за HTTPS на одному IP. Але не все так просто — інакше б навіщо я про це писав?
Є ряд старих браузерів в принципі не підтримують SNI. В їх число входять будь-які версії IE вже занедбаному Windows XP, браузер Android 2.3 і 2.2 з 2010 року, а також деякі інші більш екзотичні браузери і бібліотеки типу Java версії 1.6 і Python до версії 2.7.9.
Якщо ви все-таки хочете, щоб ваш сайт відкривався в IE в Windows XP, то одним відмовою від SNI ця проблема не вирішується. Потрібно спеціальним чином підбирати шифри, вже відмовляючись від forward secrecy і ризикуючи отримати низьку оцінку від SSL Labs. Як можна здогадатися, це питання заслуговує окремого обговорення хоча б тому що користувачам IE під XP можна поспівчувати — у них вже не відкривається половина інтернету!
Ще рік тому від переходу на SNI вас могла б утримати обмежена підтримка цієї технології деякими пошуковими ботами типу Bing, але зараз, з появою десятків сайтів з безкоштовними сертифікатами від Cloudflare, що без SNI не відкриваються, бот Bingщо легко перевірити, боти інших основних пошукових систем, прийшли до згоди з реальність. Зараз за це можна не хвилюватися. Зазначу, що у Googlebot таких проблем не було ніколи.
Іншим приводом для хвилювань можуть бути різні засоби доступу до API вашого сайту. Якщо у вас давно є API, то є невеликий шанс, що серед ваших клієнтів є якісь, використовують застарілі версії Java або Python. Якщо у вас таких нема, то нема про що переживати. Якщо ж є — мої співчуття.
Чому краще розраховувати на SNI?
  1. Це просто. Вам не потрібно постійно тримати в голові факти про видані сертифікати. Для якого домену сертифікат був виданий першим. До якого сертифікату потрібно додавати ще домени. І так далі… Ні про що такому зі SNI не потрібно думати.
  2. Секрети залишаються секретами. Якщо у вас для всіх доменів один сертифікат, то будь-хто зможе дуже легко побачити весь список, незалежно від вашого бажання. Якщо ж для кожного сайту свій сертифікат, то такої проблеми немає.
Наприклад, так можна подивитися домени в сертифікаті Тематичних Медіа:
true | openssl s_client -showcerts -connect habrahabr.ua:443 2>&1 |
openssl x509 -text | grep -o 'DNS:[^,]*' | cut -f2 -d:

Установка Certbot
Якщо ви читаєте цей текст з майбутнього, коли Certbot вже є в Debian stable без натяків і застережень, то все просто:
apt-get install certbot

Або використовуйте
aptitude
або інший пакетний менеджер вашого дистрибутива.
Установка в Jessie
Якщо у вас ще в ходу актуальний на кінець 2016 року Debian stable "jessie", то все лише трохи складніше.
  1. Треба підключити Debian Backports, додавши сходинку в
    /etc/apt/sources.list
    :
    deb http://ftp.debian.org/debian/ jessie-backports main contrib non-free

  2. Тепер можна встановлювати з зазначенням джерела:
    apt-get update
    apt-get install certbot -t jessie-backports

Розділ актуальне поки тільки stretch не став stable.)
Інший дистрибутив
Якщо у вас якийсь інший дистрибутив, то додаткові інструкції по установці є на офіційному сайті Certbot. Якщо обходитися без пакетного менеджера, то зазвичай установка зводиться до...
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
.
Certbot і webroot
Ми будемо отримувати сертифікати за методом webroot без перенастроювання або зупинки веб-сервера, під яким мається на увазі nginx. Нам потрібен якийсь каталог, в який
certbot
буде писати свої файли, і якою має бути доступний з мережі засвідчує сервера згідно протоколу ACME.
Щоб не писати кожен раз довгу рядок з опцій, а ще краще — не згадувати про них, запишемо основні налаштування в файл конфігурації, який
certbot
очікує знайти у
/etc/letsencrypt/cli.ini
:
кодів = webroot
webroot-path = /var/www/html
post-hook = service nginx reload
text = True

Остання директива потрібна, щоб позбавити нас від принад і красивостей ncurses, що потрібно щоб ви могли порівняти висновок команд тут, в цій статті, і у себе.
Також нам потрібно м'яко перезавантажити nginx (без перерви в обслуговуванні) при успішне оновлення сертифікатів. Звичайно ж нічого не заважає в цей же момент перезапускати та інші сервіси на зразок Postfix, використовують отримані сертифікати (команди перераховуються як зазвичай, через крапку з комою).
Що буде робити Certbot
Очікується що
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

Реєстрація в let's Encrypt
Реєстрацію потрібно зробити лише один раз:
certbot register --email me@example.com

Тут нічого складного.
Підготуємо nginx до отримання сертифікатів
У загальному випадку для отримання сертифікату необхідно у всіх блоках
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 сервер зобов'язаний враховувати стандартну переадресацію. Детальніше про це нижче.
Перезагрузим 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

Тепер у нас все готово щоб отримати наш перший сертифікат.
Про переадресації з кодами 301 і 302
Як було вже сказано, ACME сервер Boulder враховує переадресацію з кодами 301 і 302. В цьому сенсі не має значення де, в кінцевому рахунку, знаходяться файли, необхідні для проходження перевірок. Переадресація можлива навіть на нестандартні порти, без обмежень щодо кінцевого протоколу HTTP або HTTPS. Самі let's Encrypt рекомендують використовувати переадресацію для створення єдиної точки перевірки прав на домени.
Якщо ви можете отримати ці файли за допомогою
curl
з обмеженням у десять переадресацій, то і Boulder ці файли побачить. Не повинно бути ніяких обмежень по IP адресам.
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 є ліміти на кількість звернень за сертифікатами, тому спочатку спробуємо отримати необхідний сертифікат в режимі для тестів:
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 в одному сертифікаті), то це легко зробити після отримання сертифіката. Просто запустіть команду ще раз, додавши потрібне ім'я:
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, не отримавши для вас взагалі ніякого сертифіката. Сертифікат закінчиться і ваш сайт піде в оффлайн. З цим ключем ви все ж отримаєте сертифікати хоча б для часткового набору доменів, залишивши ваші сайти в мережі.
Ось і все
Знайшли помилку? Напишіть в приват, будь ласка.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.