Антон Рябов bio photo

Антон Рябов

Не люблю бриться и у меня умный взгляд.

Email Twitter Telegram Github PGP RSS

HTTPS в Nginx с сертификатом от Let's Encrypt

Обзор

За свою карьеру я собрал большой багаж опыта работы с веб-сервером Nginx и некоторые моменты освещал в данном блоге. Для навигации по теме используйте страницу Nginx 101




Let’s Encrypt это новый Центр сертификации (CA) который предоставляет простой способ для получения и установки бесплатных TLS/SSL сертификатов, позволяя включить HTTPS шифрование на веб серверах.

Предварительные требования

Перед тем как начать вам потребуется несколько вещей.

  • Виртуальный или выделенный сервер с установленной Debian based системой, например Ubuntu (не ниже 14.04).
  • Привилегированный доступ т.е. учетная запись root или возможность использовать sudo без ограничений.
  • Вы должны быть владельцем домена, для которого выпускаете сертификат и иметь возможность им управлять.
  • A запись домена должна вести на ваш сервер.

Установка клиента Let’s Encrypt

Во-первых нужно установить программное обеспечение Let’s Encrypt. На данный момент лучший способ это сделать это склонировать официальный git репозиторий на Github. Надеемся в будущем будет доступна адекватная установка через пакетные менеджеры (такие как apt/dpkg и yum/rpm).

Установка необходимых зависимостей

$ sudo apt-get update && sudo apt-get -y install git bc

Клонирование репозитория

$ sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

После выполнения этой команды у нас должна появится рабочая версия ПО Let’s Encrypt в каталоге /opt/letsencrypt

Получение сертификата

Let’s Encrypt предоставляет разные способы получения сертификата. Для Apache например имеется модуль, который “делает все сам”, для Nginx такого плагина нет, поэтому мы будем только получать сертификат, а настраивать его самостоятельно. Для получения сертификата мы будем использовать функцию Webroot доступную в Let’s Encrypt.

Использование Webroot

Плагин Webroot размещает специальный файл в каталоге /.well-known внутри вашего document root.

Document root - это полный путь до каталога, в котором располагаются ваши файлы сайта. В большинстве случаев это /var/www/mysite.

Именно этот файл будет проверяться системой Let’s Encrypt во время валидации при получении сертификата. В зависимости от вашей конфигурации, может понадобиться разрешить доступ к каталогу /.well-known.

Если вы еще не установили Nginx, cделать это можно командой:

$ sudo apt-get install nginx

Чтобы убедиться что у системы Let’s Encrypt будет доступ к каталогу, добавим в дефолтный конфиг /etc/nginx/sites-available/default следующие строки внутри блока server:

location ~ /.well-known {
  allow all;
}

По умолчанию в Nginx установлен Document root - /usr/share/nginx/html, можете проверить это в конфиге во избежании несоответствий, после чего можно сохранить конфиг и применить его командой:

$ sudo nginx -s reload

Когда мы знаем webroot-path, можем запросить SSL сертификат. В команде для получения сертификата мы используем ключ -d чтобы указать список доменных имен, если вам нужен сертификат не только на основной домен но и на поддомены, будьте уверены что включили все необходимые доменные имена.

Важное замечание, Let’s Encrypt не выдают, так называемые, wildcard сертификаты. Поэтому нужно внимательно отнеститесь к флагу -d.
UPD: с 2018 года выдают.

Будьте внимательны при выполнении команды, проверьте что webroot-path и доменные имена указаны верно.

$ cd /opt/letsencrypt
$ ./letsencrypt-auto certonly -a webroot --webroot-path=/usr/share/nginx/html -d 'example.com,www.example.com'

После запуска Let’s Encrypt установит и сконфигурирует некоторые программы, написанные по большей части на языке программирования Python, а потом запросит дополнительную информацию для генерации сертфикат, обычно это e-mail администратора:




И пользовательское соглашение:




Если все прошло как надо, то вы увидите что-то вроде:

IMPORTANT NOTES:
 - If you lose your account credentials, you can recover through
   e-mails sent to [email protected]
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your
   cert will expire on 2016-03-15. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - Your account credentials have been saved in your Let's Encrypt
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Let's
   Encrypt so making regular backups of this folder is ideal.
 - If like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Файлы сертификата

После успешного получения сертификата вам будут доступны следующие PEM-encoded файлы:

  • cert.pem - сертификат домена
  • chain.pem - сертификат цепочки
  • fullchain.pem - объединенные cert.pem и chain.pem
  • privkey.pem - приватный ключ вашего сертификата

Важно знать куда сохраняются данные файлы, так как мы будем настраивать Nginx. Сами файлы складываются в каталог /etc/letsencrypt/archive. Однако, Let’s Encrypt создает символические ссылки на них вида /etc/letsencrypt/live/your_domain_name. Таким образом ссылки всегда будут указывать на самые актуальные сертификаты.

Генерация группы Диффи — Хеллмана

Для повышения градуса безопасности нам нужно сгенерировать группу Диффи — Хеллмана (Diffie-Hellman Group), для этого используем команду:

$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Это может занять какое-то время, но по завершении команды вы будете иметь сильную ДХ группу по пути /etc/ssl/certs/dhparam.pem.

Настройка TLS/SSL в Nginx

Теперь когда у нас есть SSL сертификат, снова пойдем в конфиг Nginx и изменим настройки.

$ sudo nano /etc/nginx/sites-available/default

Найдем следующие строки внутри блока server:

listen 80 default_server;
listen [::]:80 default_server ipv6only=on;

И заменим их на:

listen 443 ssl;

server_name example.com www.example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

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

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;

Также перед нашим блоком server использующим SSL, добавим еще один блок server, который будет перенаправлять все обычные, не зашифрованные запросы на SSL:

server {
  listen 80;
  server_name example.com www.example.com;
  return 301 https://$host$request_uri;
}

Сохраняем, выходим и применяем нашу конфигурацию.

sudo nginx -s reload

Теперь все на своих местах. Можем проверить уровень нашей безопасности на сайт SSL Labs (вместо example.com нужно подставить свое доменное имя):

https://www.ssllabs.com/ssltest/analyze.html?d=example.com

В отчете должна светиться оценка - A+.

Автообновление сертифката

Сертификаты Let’s Encrypt действительны только в течение 90 дней, это одна из политик, также направленная на обеспечение безопасности. Чтобы обновить, или правильнее сказать, перевыпустить сертификат, нужно выполнить некоторые действия, похожие на получение сертификата.

На самом деле Let’s Encrypt сделает все сам, нужно только запустить команду:

$ /opt/letsencrypt/letsencrypt-auto renew

Чтобы не забыть про перевыпуск сертификата, нужно автоматизировать запуск данной команды, для этого воспользуемся cron’ом.

$ sudo crontab -e

Добавим следующие строки:

30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log
35 2 * * 1 /etc/init.d/nginx restart

Сохраняем файл и выходим, после этого команда будет выполняться каждый понедельник в 2.30 ночи, после чего в 2.35 будет перезапускаться Nginx.

Обновление клиента Let’s Encrypt

Если для установки вы использовали клонирование репозитория то обновление сводится к выкачиванию изменений из репозитория. Это можно сделать с помощью команд:

$ cd /opt/letsencrypt
$ sudo git pull

Повышаем градус безопасности

В принципе на этом можно остановиться, у нас уже есть шифрование на сайте. Однако для более полной безопасности нашего приложения стоит установить некоторые заголовки:

resolver            8.8.8.8;

add_header          X-Xss-Protection "1";
add_header          X-Frame-Options SAMEORIGIN;
add_header          X-Content-Type-Options nosniff;
add_header          Strict-Transport-Security "max-age=31557600";

# Read about this before including!
add_header          Content-Security-Policy "default-src 'self' googleapis.com";

Проверить заголовки можно тут.

Заключение

Данный метод был протестирован и применен мной на нескольких проектах, на таких операционных системах как Debian, Ubuntu, Centos. Например, теперь мы шифруем все в магазине беспроводного оборудования isbis.ru. Чтобы разобраться в вопросе я перечитал много всего, но наиболее полезными оказались следующие статьи:

#Nginx #Letsencrypt #TechAndDev