Переехал на HTTPS, включил HTTP/2

20 комментариев

SSL, HSTS, HTTP2 Сегодня перевел свой блог на HTTPS. Зачем? Не знаю, но почему бы и нет?) Наверное это больше связано с популязацией https в интернете в целом. Поправил конфиг SSL, получив A+ в ssllabs. Добавил Strict Transport Security. Обновил nginx до последней версии 1.9.5, подключив HTTP/2. В целом неплохо так получилось.

Под катом подробнее об этом.

Как правильно настроить HTTPS?

В этом нам поможет сервис SSLLabs. Проверяем свой сайт и, глядя в мануал NGINX, исправляем выявленные недочеты до тех пор пока не исправим их все. Так например, у меня был разрешен SSLv3, который имеет уязвимости, и пара других недочетов. Получаем:Настройка SSL в nginx
В итоге у меня получился вот такой вот конфиг nginx-а:

	ssl on;
	ssl_certificate "[...].crt";
	ssl_certificate_key "[...].key";
	ssl_dhparam "[...]/dh2048.pem";

	ssl_session_timeout 1h;
	ssl_session_cache shared:SSL:16m;

	ssl_stapling on;
	ssl_stapling_verify on;
	ssl_trusted_certificate "[...].trusted.crt";
	resolver 8.8.4.4 8.8.8.8 valid=300s;
	resolver_timeout 10s;

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	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:DES-CBC3-SHA:!RC4:!aNULL:!eNULL:!MD5:!EXPORT:!EXP:!LOW:!SEED:!CAMELLIA:!IDEA:!PSK:!SRP:!SSLv:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

	ssl_prefer_server_ciphers on;

Кстати сказать плохо настроенный SSL, не даст работать протоколу HTTP/2. Так например, при использовании небезопасного шифра/протокола, не говоря уже о невалидном сертификате, Chrome откажется открывать сайт, выдавая ошибку ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY. Поэтому если вы планируете подключить HTTP2, обязательно обратите внимание на разрешенные протоколы и шифры (ssl_protocols и ssl_ciphers). Приведенная конфигурация выше — эталон, который следует брать за основу.

Хорошо бы сгенерировать ключ dhparam с 2048-битным ключом (ssl_dhparam), т.к. по дефолту используется 1024-битный ключ, а на данный момент это уже ненадежно. Кое-где рекомендуют 4096 бит, но я не советую этого делать, т.к. это фактически замедляет работу сервера.

Также рекомендую включить поддержку OSCP ответов:

	ssl_stapling on;
	ssl_stapling_verify on;
	ssl_trusted_certificate "[...].trusted.crt";
	resolver 8.8.4.4 8.8.8.8 valid=300s;
	resolver_timeout 10s;

это позволяет существенно ускорить время установления SSL соединения с сервером, а, следовательно, и время загрузки вашего сайта.

И обязательно включаем ssl_prefer_server_ciphers on — тем самым указываем, что серверные шифры были более приоритетны, чем клиентские, тем самым исключаем возможность BEAST-атаки.

Ну и включаем кеш сессий:

	ssl_session_timeout 1h;
	ssl_session_cache shared:SSL:16m;

Выполнение этих рекомендаций даст A+ оценку, чего мы собственно и добивались :)

Как включить HSTS

Кстати сказать неплохо включать HTTP Strict Transport Security для тех сайтов которые работают только по HTTPS. Добавляем в конфиг nginx:

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

Этот заголовок говорит о том что данный браузер работает только по HTTPS, и необходимо пресекать все попытки открытия его по HTTP, если проще — то всегда открывать его по HTTPS. Но википедия конечно скажет лучше меня:

механизм, активирующий форсированное защищённое соединение через протокол HTTPS. Данная политика безопасности позволяет сразу же устанавливать безопасное соединение, вместо использования HTTP-протокола. Механизм использует особый заголовок Strict-Transport-Security для принудительного использования браузером протокола HTTPS даже в случае перехода по ссылкам с явным указанием протокола HTTP (http://).

Как обновить nginx до 1.9.5 в Debian

В принципе тут проблем никаких быть не должно. Заходим на сайт nginx и выполняем пошагово их инструкцию:

Для Debian/Ubuntu, для проверки подлинности подписи репозитория nginx, и чтобы избавиться от предупреждений об отсутствующем PGP-ключе во время установки пакета nginx, необходимо добавить ключ, которым были подписаны пакеты и репозиторий nginx, в связку ключей программы apt. Загрузите этот ключ с нашего веб-сайта и добавьте его в связку ключей программы apt, выполнив команду:

sudo apt-key add nginx_signing.key

Для Debian замените codename на кодовое имя дистрибутива, и добавьте в конец файла /etc/apt/sources.list следующее:

deb http://nginx.org/packages/mainline/debian/ codename nginx
deb-src http://nginx.org/packages/mainline/debian/ codename nginx

Для Ubuntu замените codename на кодовое имя дистрибутива, и добавьте в конец файла /etc/apt/sources.list следующее:

deb http://nginx.org/packages/mainline/ubuntu/ codename nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ codename nginx

Для Debian/Ubuntu затем выполните команды:

apt-get update
apt-get install nginx

В процессе обновления у вас может возникнуть конфликт со старой версией nginx, например такая ошибка:

trying to overwrite '/etc/logrotate.d/nginx', which is also in package nginx-common

или

trying to overwrite '/usr/sbin/nginx', which is also in package nginx-full

тогда вам следует удалить эти пакеты, и после таки установить nginx:

apt-get update
apt-get remove nginx-full nginx-common nginx
apt-get install nginx

Как включить HTTP/2 в nginx?

Нормальная реализация HTTP2 появилась в версии nginx 1.9.5. Собственно поэтому и понадобилось обновиться до этой версии. Ну а подключить поддержку этого протокола еще легче. Правим конфиг nginx, добавляем http2 в listen:

...
listen 433 ssl http2;
...

Тут я наверное уже больше ничего не добавлю)

Как определить поддерживает ли сайт HTTP/2?

Открываем Chrome Developer Tools, переходим в раздел Network. Включаем в таблице ресурсов отображение столбца Protocol:
Определить поддержку сайтом протокола HTTP/2
Жмем F5, и видим протокол по которому был загружен тот или иной ресурс:
Поддерживает ли сайт HTTP2
где H2 — это HTTP/2

Итог

После всех этих действий мы будем так сказать «на гребне волны» в сфере развития HTTPS. Ну и маленьким приятным бонусом я сэкономил немножко оперативной памяти:
Оперативная память nginx 1.9.5
Немного, где то 50Мб, могу предположить что это из за обновления на nginx 1.9.5, но все таки это лучше чем если бы памяти начало потребляться больше чем было.

Ну и кстати что же дало мне включение HTTP/2? Без HTTP/2 полная загрузка главной страницы сайта со всеми элементами происходила за 1.2 сек, сейчас же всего за 0.8 сек, то есть можно сказать что скорость загрузки выросла на ~30%!

Спасибо за внимание :)

  1. Виталя

    Кстати в SslLab можно получить оценку еще выше, если отключить TLSv1 TLSv1.1, оставив только TLSv1.2

    1. Дмитрий Амиров Автор

      Да, только из-за этого некоторые старые браузеры не будут работать с вашим сайтом. Поэтому я бы не стал все таки этого делать

  2. Виталий

    Скопировал конфигурацию, подключил свои сертификаты, NGNIX 1.9.9. H2 так и не поднялся…

    1. Дмитрий Амиров Автор

      На самом деле вам достаточно указать http2 в параметре listen, чтобы HTTP/2 заработал. Приведите конфигурацию полностью, пожалуйста. Может я смогу вам помочь.

  3. Странник

    В чём смысл HTTP/2, если общепринят HTTP 1.1? Мы только лишаемся совместимости со старыми браузерами

    1. Дмитрий Амиров Автор

      Нет, вы что) HTTP/2 если можно так сказать обратно совместим со всеми браузерами. Работает по принципу — если сервер и клиент поддерживают HTTP/2 то только тогда они начинают использовать этот протокол. Если кто то не поддерживает, используется HTTP/1.1

      А смысл огромен, гляньте например вот этот тест

  4. Вячеслав

    Добрый день, Дмитрий.
    Подскажите, пожалуйста, где взять сертификат для директивы ssl_trusted_certificate?
    Его выдает Let’s Encrypt?
    Спасибо.

    1. Дмитрий Амиров Автор

      Вячеслав, здравствуйте!
      Да, его выдает Let’s Encrypt. Гляньте внимательнее Поставил сертификат Let’sEncrypt а именно вот:

      ssl_trusted_certificate "/etc/letsencrypt/live/intsystem.org/chain.pem"; #Если используете OCSP

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

  5. Sergey

    лично у меня при использовании http/2 сайт стал грузиться медленнее где то на 200ms. Давно пользуюсь nginx proxy и http/1.1 распараллеливая загрузку. Попробую воткнуть в конфиг resolver может побыстрее http/2 станет

  6. 1informer

    На сколько влияет http/2 на скорость сайта ?
    Есть ли какой то плюс при ранжирование сайта

    1. Дмитрий Амиров Автор

      http/2 увеличивает скорость загрузки. Говорят что скорость загрузки — один из факторов влияющих на ранжирование => влияет.

  7. Владимир

    Обратите внимание, что ваш сайт в последней версии chrome (55) работает по http/1.
    Причина описана в статье:
    https://victor.4devs.io/ru/architecture/nginx-http2-does-not-work.html
    или в буржунете:
    https://www.nginx.com/blog/supporting-http2-google-chrome-users
    Авторы этих статей предлагают как решение скомпилить nginx с нужной версией openssl, но я нашел решение проще для centos 7. Есть репозиторий, где nginx уже собран и слинкован с openssl 1.0.2.
    https://brouken.com/brouken-centos-7-repo/
    Достаточно добавить репозиторий и обновить из него nginx.

    1. Дмитрий Амиров Автор

      Спасибо!

      Да, я знаю уже об этой проблеме несколько месяцев, но все никак не дойдут руки у меня ее решить( У меня дебиан, и вроде как это решается только сборкой nginx из исходников с нужной версией openssl.

  8. Программист

    Добавил себе на сайте https://triptorg.ru/ http/2. Сервис «HTTP/2 Тест — онлайн сервис» показывает, что
    сайт поддерживает http/2. Но вот firebug в firefox в заголовках пишет Версия: HTTP/1.1
    В чем может быть проблема? Версия Nginx 1.11.6, в конфиге все указал: listen 443 ssl http2;

  9. Дмитрий

    Здравствуйте. Спасибо за статью. У меня возник вопрос, ответ на который я не смог найти в инете. https замедляет работу сайта, так как должен зашифровать весь трафик. Слышал, что запросов увеличивается вдвое. При этом http/2 увеличивает скорость загрузки. Но без ssl http/2 не работает. То есть палка на 2 концах: один замедляет, другой увеличивает. Установил на сайте сертификат бесплатный через админку бегета. Включился h2, но сайт на h2 загружается в 1.5-2 дольше, исходя из тестов. Вот как так?

  10. Дмитрий

    Исправьте, пожалуйста:

    listen 433 ssl http2;

    Порт 443, думаю, очепятка? :)

Добавить комментарий

Прочли запись? Понравилась? Не стесняйтесь, оставьте, пожалуйста, свой комментарий. Мне очень интересно, что вы думаете об этом. Кстати в комментарии вы можете задать мне любой вопрос. Я обязательно отвечу.

Вы можете оставить коментарий анонимно, для этого можно не указывать Имя и email. Все комментарии проходят модерацию, поэтому ваш комментарий появится не сразу.