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

Дата: 20.08.2015Метки:

Ранее я уже описывал процесс установки сертификата StartSSL и приводил пример минимального набора параметров необходимого для использования SSL в Nginx. В этой статье речь пойдет о более тонкой настройке. Сайт, настроенный по рекомендациям в данной статье, проходит проверку SSL на А+.

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

Настройку SSL в Nginx лучше начинать с минимальных рабочих параметров:

server {
    listen 443 ssl;
    server_name domain.net;

    ssl_certificate /etc/nginx/ssl/domain_com/domain.pem;
    ssl_certificate_key /etc/nginx/ssl/domain_com/domain.key;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
    }
}

Далее привожу краткое описание используемых директив.

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

# cat ssl.crt sub.class1.server.ca.pem > domain.pem
ssl_certificate /etc/nginx/ssl/domain.pem;

Необходимо расшифровать приватный ключ и указать путь к его файлу:

# openssl rsa -in ssl.key -out private.key;
ssl_certificate_key /etc/nginx/ssl/domain.key;

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

Для использования набора шифров DHE, необходимо создать ключ Диффи-Хеллмана и указывать путь к файлу в настройка Nginx:

# openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

С включенным SSL сервер использует дополнительные ресурсы процессора. Для снижения количества операций необходимо задать размер кэша и время хранения SSL-сессий. В 1 мегабайт кэша помещается около 4000 сессий.

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;

Дополнительно для снижения нагрузки, мы обрабатываем сразу несколько запросов в рамках одного keepalive-соединения:

keepalive_timeout 70;

Указываем поддерживаемые сервером протоколы SSL:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

Указываем, что серверные шифры имеют больший приоритет, чем клиентские шифры. Рекомендуемый набор шифров можно взять с официально сайта MozillaWiki. Можно сразу использовать использовать генератор конфига для Nginx.

ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DES";

Для уменьшая время загрузки страниц, разрешаем серверу для валидации сертификата прикреплять OCSP-ответы. Для работы функции необходимо указать путь к файлу сертификата издателя и DNS-сервер.

ssl_stapling on;
ssl_trusted_certificate /etc/nginx/ssl/ca.pem;
resolver 8.8.8.8;

Что бы указать браузеру, что сайт доступен только по HTTPS, необходимо указать заголовок:

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

Заголовок запрещает браузеру показывать сайт в фрейме:

add_header X-Frame-Options DENY;

Чтобы предотвратить MITM атаки с поддельными сертификатами, указываем заголовок Public-Key-Pins:

add_header Public-Key-Pins 'pin-sha256="base64+info1="; max-age=31536000' always;

Для директивы pin-sha256 используем одну из команд ниже:

openssl rsa  -in domain.key -outform der -pubout | openssl dgst -sha256 -binary | base64
openssl req  -in domain.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | base64
openssl x509 -in domain.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | base64

Указываем браузеру что бы он использовал отданный сервером Сontent-type, вместо автоматического его определения:

add_header X-Content-Type-Options nosniff;

Заголовок активирует XSS-защиту:

add_header X-XSS-Protection "1; mode=block";

Используем переадресацию на защищенное соединение:

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

        server_name domain.net;
        return 301 https://domain.com;
}

Пример конфигурационного файла: