Главная > HOWTO > Усиливаем безопасность HTTPS в nginx

Усиливаем безопасность HTTPS в nginx

В данной статье мы рассмотрим как значительно усилить безопасность HTTPS на примере веб-сервера nginx, настроенного в качестве фронтенда.

Введение

Проверить работу SSL/TLS на сервере можно при помощи специализированного ресурса. Определяются слабые, небезопасные и анонимные шифры, а также уязвимости к атакам типа Heartbleed, Poodle и т.д.

С настройками nginx по умолчанию тестер показывает F (ужасно). После нашей настройки будет A+ (отлично).

Отключаем устаревшие протоколы

Из соображений безопасности следует полностью отключить устаревшие протоколы: SSLv2 и особенно SSLv3, который давно подвержен атаке Poodle.

Разрешим в конфиге nginx только TLS версий 1.0, 1.1 и 1.2:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

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

Включаем механизм TLS-FALLBACK-SCSV

Данный механизм предотвращает ослабление шифрования за счёт перехода на уязвимый SSL. Механизм появился во всех новых версиях библиотеки openssl, поэтому требуется обновить:

  • OpenSSL 1.0.1 до версии 1.0.1j и выше;
  • OpenSSL 1.0.0 до версии 1.0.0o и выше;
  • OpenSSL 0.9.8 до версии 0.9.8zc и выше.

Отключаем небезопасные и анонимные шифры

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

Если необходимо обеспечить совместимость только с современными браузерами (Firefox 24+, Chrome/Chromium 32+), пропишем в конфиге nginx:

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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK;

Если необходима и поддержка клиентов с более старыми браузерами (IE7+, Firefox 3.x, Opera 12.x), пропишем такую строку вместо предыдущей:

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_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;

Порядок в строке ssl_ciphers имеет значение: чем ближе он к началу, тем выше его приоритет. Если на клиенте не окажется шифров, разрешённых на сервере, последний закроет с ним соединение.

Включаем механизм Forward Secrecy

Принцип работы этого механизма достаточно прост: клиент и сервер в момент TLS рукопожатия обмениваются особыми одноразовыми ключами, которые уничтожаются по окончании TLS сессии, либо по таймауту. Для обмена ключами используется механизм Диффи-Хеллмана. Ключ, полученный таким способом, используется для шифрования передаваемых в обе стороны данных.

Даже если злоумышленник сможет украсть секретный ключ сервера, он не сможет расшифровать предыдущий TLS трафик, т.к. секретный ключ сервера используется только для подписи рукопожатия DH.

Индивидуальные сессионные ключи клиента и сервера не покидают их и не могут быть получены посредством MITM-атак ни при каком условии.

Веб-сервер nginx начиная с версии 1.4.4 уже использует механизм Диффи-Хеллмана для обмена ключами, однако длина ключа всего 1024 бит, что очень мало по современным меркам. Нам необходимо сгенерировать свой собственный с длиной ключа 4096 бит:

cd /etc/nginx/keys/
openssl dhparam -out dhparam.pem 4096

Процесс займёт достаточно много времени из-за сбора дополнительной энтропии и на выходе мы получим файл dhparam.pem. Теперь нам нужно включить его в конфиге nginx:

ssl_dhparam /etc/nginx/keys/dhparam.pem;

Включаем HTTP Strict Transport Security

Расширение HTTP Strict Transport Security предназначено для сохранения настройки в браузере «этот сайт работает только посредством HTTPS».

Атаковать такой ресурс при помощи «человек посередине» (MITM) уже не получится, т.к. в случае подмены сертификата браузер сразу закроет соединение и не даст возможности продолжить работу с поддельным сертификатом.

Включим поддержку HSTS:

add_header Strict-Transport-Security max-age=31536000;

В параметре max-age указывается на сколько секунд следует кэшировать заголовок HSTS в браузере. Рекомендуется указывать 31536000 (1 год) и выше.

Включаем HTTP Public Key Pinning Extension

Firefox начиная с версии 35.0 начал поддерживать расширение HTTP Public Key Pinning, поэтому включим и его, т.к. безопасности много не бывает.

При помощи данного расширения администратор ресурса может указать какой удостоверяющий центр может использоваться для подписания его сертификатов. В совокупности с уже описанным HSTS, это на 100% исключает возможность MITM-атаки.

Чтобы включить данное расширение, нам необходимо получить отпечаток удостоверяющего центра, выдавшего наш сертификат и закодировать его в base64. Проще всего это сделать так:

openssl x509 -in cert.pem -pubkey -noout | \
openssl rsa -pubin -outform der | \
openssl dgst -sha256 -binary | openssl enc -base64

Здесь cert.pem — это первый в цепочке сертификат, принадлежащий удостоверяющему центру. На выходе мы получим строку в base64.

Включаем расширение и прописываем отпечаток нашего УЦ (не забудьте указать свой base64 отпечаток):

add_header Public-Key-Pins 'pin-sha256="5C8kvU039KouVrl52D0eZSGf4Onjo4Khs8tmyTlV3nU="; max-age=1512000';

В параметре max-age указывается на сколько секунд следует кэшировать отпечаток в кэше браузера. Рекомендуется указывать не слишком большое значение, т.к. в случае смены УЦ клиенты не смогут зайти на ваш ресурс до истечения таймаута.

Дополнительная литература

При написании данной статьи использовалась литература из следующих источников:

Категории:HOWTO Метки:, , , , ,
  1. Пока что нет комментариев.
Представьтесь, пожалуйста! Если ваш комментарий предполагает ответ, мы ответим на него в ближайшее время. Адрес электронной почты должен быть действительным.


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