Ubuntu настройка nginx https

Обновлено: 05.07.2024

Сертификат сервера является публичным. Он посылается каждому клиенту, соединяющемуся с сервером. Секретный ключ следует хранить в файле с ограниченным доступом (права доступа должны позволять главному процессу nginx читать этот файл). Секретный ключ можно также хранить в одном файле с сертификатом:

при этом права доступа к файлу следует также ограничить. Несмотря на то, что и сертификат, и ключ хранятся в одном файле, клиенту посылается только сертификат.

С помощью директив ssl_protocols и ssl_ciphers можно ограничить соединения использованием только “сильных” версий и шифров SSL/TLS. По умолчанию nginx использует “ ssl_protocols TLSv1 TLSv1.1 TLSv1.2 ” и “ ssl_ciphers HIGH:!aNULL:!MD5 ”, поэтому их явная настройка в общем случае не требуется. Следует отметить, что значения по умолчанию этих директив несколько раз менялись.

SSL-операции потребляют дополнительные ресурсы процессора. На мультипроцессорных системах следует запускать несколько рабочих процессов, не меньше числа доступных процессорных ядер. Наиболее ресурсоёмкой для процессора является операция SSL handshake, в рамках которой формируются криптографические параметры сессии. Существует два способа уменьшения числа этих операций, производимых для каждого клиента: использование постоянных (keepalive) соединений, позволяющих в рамках одного соединения обрабатывать сразу несколько запросов, и повторное использование параметров SSL-сессии для предотвращения необходимости выполнения SSL handshake для параллельных и последующих соединений. Сессии хранятся в кэше SSL-сессий, разделяемом между рабочими процессами и настраиваемом директивой ssl_session_cache. В 1 мегабайт кэша помещается около 4000 сессий. Таймаут кэша по умолчанию равен 5 минутам. Он может быть увеличен с помощью директивы ssl_session_timeout. Вот пример конфигурации, оптимизированной под многоядерную систему с 10-мегабайтным разделяемым кэшем сессий:

Цепочки SSL-сертификатов

Некоторые браузеры могут выдавать предупреждение о сертификате, подписанном общеизвестным центром сертификации, в то время как другие браузеры без проблем принимают этот же сертификат. Так происходит потому, что центр, выдавший сертификат, подписал его промежуточным сертификатом, которого нет в базе данных сертификатов общеизвестных доверенных центров сертификации, распространяемой вместе с браузером. В подобном случае центр сертификации предоставляет “связку” сертификатов, которую следует присоединить к сертификату сервера. Сертификат сервера следует разместить перед связкой сертификатов в скомбинированном файле:

Полученный файл следует указать в директиве ssl_certificate:

поскольку nginx попытается использовать секретный ключ с первым сертификатом из связки вместо сертификата сервера.

Браузеры обычно сохраняют полученные промежуточные сертификаты, подписанные доверенными центрами сертификации, поэтому активно используемые браузеры уже могут иметь требуемые промежуточные сертификаты и не выдать предупреждение о сертификате, присланном без связанной с ним цепочки сертификатов. Убедиться в том, что сервер присылает полную цепочку сертификатов, можно при помощи утилиты командной строки openssl , например:

При тестировании конфигураций с SNI необходимо указывать опцию -servername , так как openssl по умолчанию не использует SNI.

Если связку сертификатов не добавили, будет показан только сертификат сервера №0.

SSL-сертификат с несколькими именами

Указание имени сервера

В SNI можно передавать только доменные имена, однако некоторые браузеры могут ошибочно передавать IP-адрес сервера в качестве его имени, если в запросе указан IP-адрес. Полагаться на это не следует.

Чтобы использовать SNI в nginx, соответствующая поддержка должна присутствовать как в библиотеке OpenSSL, использованной при сборке бинарного файла nginx, так и в библиотеке, подгружаемой в момент работы. OpenSSL поддерживает SNI начиная с версии 0.9.8f, если она была собрана с опцией конфигурации Начиная с OpenSSL 0.9.8j эта опция включена по умолчанию. Если nginx был собран с поддержкой SNI, то при запуске nginx с ключом “-V” об этом сообщается:

Однако если nginx, собранный с поддержкой SNI, в процессе работы подгружает библиотеку OpenSSL, в которой нет поддержки SNI, nginx выдаёт предупреждение:

Повествование будет вестись с учетом того, что веб-сервером выступает nginx (и в одном месте будет параметр для php-fpm).

Сертификат

У меня уже был сертификат от StartSSL. О нем уже писали на хабре, так что на этом шаге задерживаться не буду. Скажу только, что в течении первых двух-трех дней браузеры, проверяющие сертификат на сервере, могут на него ругаться (у меня такое происходило с Opera 12 и Firefox), видимо у StartCom кеши валидных сертификатов обновляются не так часто. Про установку же будет сказано ниже

О вариантах настройки

О Forward Secrecy можно почитать скажем тут. В двух словах, суть заключается в том, что для актуального на данный момент алгоритма RC4 ключи сессии генерируются на основе приватного ключа сервера. Таким образом, если приватный ключ будет скомпрометирован, появится возможность расшифровать все сессии (если они были записаны). В случае же использования DH-кодировок, каждая сессия имеет свой набор ключей, которые сессии никак не зависят от приватного ключа. Однако в этом случае тратится гораздо больше процессорного времени на хендшейк, что увеличивает нагрузку и время открытия страницы.

Настройка nginx

В результате настройки у меня сформировался приблизительно такой конфиг, суть параметров поясню ниже.


Секция server же получится приблизительно такая:


В данном примере не используются DH-алгоритмы, т.е. нет Forward Secrecy. Из улучшений тут можно опустить поддержку SSLv3 (убрав его из ssl_ciphers), таким образом перестанет поддерживаться IE 6 и ниже, поскольку он не поддерживает TLS, а так же увеличить время STS, но об этом ниже.
Без SSLv3 такая настройка дает оценку 100-95-100-90 в тесте SSL.

Пройдемся по параметрам

4000 сессий, таким образом при этих настройках можно хранить до 40 тысяч сессий), 5m — таймаут сессии в кеше (5 минут).

ssl_stapling on;
Позволяет серверу прикреплять OCSP-ответы, тем самым уменьшая время загрузки страниц у пользователей. ЗДесь имеются ввиду ответы о валидности сертификата (при проверке на отозванность). С точки зрения безопасности пользователя не важно, кто передает ответы — веб-сервер или сервер CA — ведь ответ в любом случае подписан и валидность ответа тоже можно проверить, а ответ включает в себя свой срок действия.
Для работы этой функции нужно указать DNS-сервер, что и делается директивой resolver.

keepalive_timeout — думаю в описании не нуждается, не стоит выключать или ставить слишком малым для уменьшения нагрузки из-за повторного установления соединения.

ssl_certificate и ssl_certificate_key указывают на файл сертфиката и файл приватного ключа для него. Так как я рассказываю на примере сертификата от StartSSL, то здесь допущу небольшой комментарий относительно инструкций StartSSL по установке сертификата — не нужно добавлять сертификат Root CA в обобщенный файл сертификата, поскольку это не имеет смысла и только увеличивает, хоть и не на много, размер передаваемых данных. Достаточно иметь в файле последовательно личный сертификат и сертификат промежуточного центра сертификации. Готовый файл сертификата для nginx (для сетификата StartSSL) можно получить следующей командой:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
Указывает поддерживаемые протоколы. SSLv2 и v3 имеют критические уязвимости.

ssl_ciphers «HIGH:!RC4:!aNULL:!MD5:!kEDH»;
Указывает используемые шифры. Собственно за счет изменения набора шифров и настраивается Forward Secrecy. От стандартного набора, предлагаемого nginx, отличается только параметром !kEDH,

Forward Secrecy

Для включения Forward Secrecy можно использовать например такой набор шифров:


Кроме того, необходимо настроить приоритет шифров OpenSSL:

В данном варианте не запрещается использование RC4 для сохранения совместимости с некоторыми браузерами, однако не так давно обнаружились уязвимости и в нем, хоть и практически трудно реализуемые.

Для усиления шифрования можно увеличить стойкость DH-шифров, создав файл параметров DH-шифров (создание файла займет некоторое время!), скажем длинной 4096 бит:

И добавив в конфиг nginx директиву

Это можно делать для скажем для веб-интерфейсов управления сервером/службами, однако хендшейк будет происходить еще дольше, поэтому не стоит делать это на обычном сайте.

Про CDN-сервисы

В обсуждении инструкций по настройке Forward Secrecy было замечено, что по крайней мере CDN Amazon CloudFront не поддерживает обмен с вашим сервером в DH-кодировках, да и RC4 вроде тоже, что не радует. Возможно что и с другими CDN тоже не все идеально, но я лично пока с ними не сталкивался, поэтому ничего сказать не могу.

В последнее время сделать это не очень сложно, потому что все популярные веб-серверы его поддерживают, а получить сертификат можно абсолютно бесплатно. В сегодняшней статье мы поговорим о том как настроить SSL в Nginx с сертификатом Lets Encrypt.

Настройка SSL в Nginx с Lets Encrypt

Я предполагаю, что у вас уже установлен веб-сервер Nginx. Дальше мы рассмотрим как создать виртуальный хост, установить все необходимые компоненты для получения сертификатов, а также настроить само SSL соединение.

Шаг 1. Настройка виртуального хоста

sudo vi /etc/nginx/conf.d/vps-losst-ru.conf

Затем проверьте конфигурацию Nginx:


И если всё верно, перезапустите веб-сервер:

sudo systemctl restart nginx

Убедиться что всё работает можно с помощью браузера или утилиты curl:


2. Установка Certbot

Для получения сертификатов LetsEncrypt официально рекомендовано использовать клиент Certbot. Установить программу можно из официальных репозиториев:

sudo apt install certbot certbot-python-nginx

Первый пакет устанавливает саму программу, а второй добавляет модуль для работы с Nginx. После установки можно его использовать.

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

Мы не будем устанавливать сертификат автоматически, а только сгенерируем его с помощью этой утилиты, а потом добавим вручную в Nginx. Для генерации и подписи сертификата используйте такую команду:



4. Настройка виртуального хоста для SSL

  • cert.pem - файл сертификата, использовать его мы не будем;
  • chain.pem - файл цепочки сертификата, тоже не будем использовать;
  • privkey.pem - приватный ключ сертификата, надо прописать в параметре ssl_certificate_key;
  • fullchain.pem - в нём объединено содержимое cert.pem и chain.pem, надо прописать в параметре ssl_certificate.

Для SSL надо создать отдельный файл виртуального хоста, в котором порт прослушивания будет 443, и будут присутствовать несколько директив настройки SSL:

sudo vi /etc/nginx/conf.d/vps-losst-ru-ssl.conf

После создания файла останется перезапустить Nginx:

sudo systemctl restart nginx

Уже на этом этапе всё должно работать.


5. Дополнительная безопасность

Чтобы сделать соединение SSL более безопасным надо отключить небезопасные протоколы и включить только надежные шифры. Для настройки протоколов используйте директиву ssl_protocols. На сегодняшний день самым безопасным считается TLS:

sudo vi /etc/nginx/conf.d/vps-losst-ru-ssl.conf

ssl_protocols TLSv1.2 TLSv1.3;

В примере я разрешаю только TLSv1.2 и TLSv1.3 для хорошей оценки от ssllabs, но в производственной системе возможно стоит разрешить всю линейку протоколов TLS, если вам нужна поддержка устройств не поддерживающих современные методы шифрования. Затем надо добавить шифры, которые мы хотим использовать:

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

После завершения настроек не забудьте перезапустить Nginx.

6. Проверка

Проверить параметры работы SSL можно с помощью сайта SSLlabs. Просто откройте такую ссылку в браузере, заменив домен сайта на свой:


Как видите, всё хорошо, и сайт получил оценку A. Сертификат SSL Nginx установлен и работает.

7. Обновление сертификата

Минус сертификатов от Lets Encrypt в том, что они актуальны только 90 дней. За 30 дней до истечения этого срока их рекомендуется перевыпускать. Для этого существует специальная команда:

Она проверяет все сертификаты, установленные в системе и перевыпускает те, что скоро будут просрочены. Чтобы настроить автоматический перевыпуск сертификатов просто добавьте эту команду в crontab:

30 2 * * 1 /usr/bin/certbot renew >> /var/log/le-renew.log

Эта команда будет выполнятся каждый понедельник в 2:30 и записывать свой вывод в файл /var/log/le-renew.log.

Выводы

В этой небольшой статье мы рассмотрели как выполняется настройка SSL Nginx с Lets Encrypt. Как видите, всё вполне выполнимо, несмотря на определённую сложность. А вы уже используете SSL? Планируете использовать? Напишите в комментариях!

Категория А при проверке безопасности сервисом ssllabs

Для достижения результата мы рассмотрим:

1. Правильный сертификат

Под этим подразумевается выполнение двух условий:

  1. Сертификат должен быть выпущен доверенным центром.
  2. Сертификат должен быть выдан для домена, к которому идет подключение.

Доверенный центр

Есть список центров сертификации, внесенные в общий реестр доверенных узлов, которые могут выпускать ключи безопасности. Данным центрам по умолчанию доверяют все основные операционные системы.

И наоборот, сертификат может быть выпущен не доверенным центром или локально на компьютере (самоподписанный). В таком случае мы получим ошибку при проверке подлинности.

Сертификат для домена

2. Использование всей цепочки сертификатов

Ошибка при проверке сертификата, если загружена не вся цепочка ключей безопасности

В случае покупки сертификата, нам отправляют все ключи в отдельных файлах. Цепочка сертификатов, как правило, идет в файле chain. Мы должны скопировать последовательность в данном файле и добавить ее к содержимому в файле с сертификатом домена — получиться файл, содержащий как последовательность для домена, так и всех центров. Назвать его можно fullchain.pem.

И так, при настройке виртуального домена в NGINX, необходимо указать путь до файла, содержащего в себе все ключи, например:

Не забываем перезапустить nginx:

systemctl restart nginx

3. Отключение устаревших протоколов

В случае, если наш веб-сервер поддерживает подключение с использованием устаревших протоколов безопасности, например, TLS 1.0, мы получим ошибку This server supports TLS 1.0 and TLS 1.1:

Ошибка при проверке безопасности сайта, если разрешены подключения по устаревшим протоколам

В NGINX нам необходимо перечислить протоколы, по которым разрешено подключение. Лучше всего это сделать в основном конфигурационном файле:

* в данном примере мы указали, что разрешены подключения только по TLS версии 1.2.

Не забываем перезапустить nginx:

systemctl restart nginx

4. Задаем приоритет для серверных шифров

Нам необходимо указать, чтобы при использовании протокола TLS серверные шифры были приоритетнее, чем клиентские. В противном случае мы увидим ошибку This server does not support Forward Secrecy with the reference browsers:

Неправильная настройка Forward Secrecy

Не забываем перезапустить nginx:

systemctl restart nginx

5. Настройка более стойкого ключа Диффи-Хилмана

Для шифрования сессий NGINX использует DH-шифры. Если последовательность не достаточно стойкая (ниже 2048 бит), мы увидим ошибку This server supports weak Diffie-Hellman (DH) key exchange parameters:

Ошибка при использовании слабого шифра Diffie-Hellman

openssl dhparam -out /etc/nginx/dh2048.pem 2048

Не забываем перезапустить nginx:

systemctl restart nginx

(Опционально) Перенаправление с 80 на 443

Читайте также: