HTTP/2 в nginx при помощи Let's Encrypt
Итак, был конец 2015 года, я смотрел на свой давний проект spaceismine.org, на котором всякие картинки-статика, и тут в голову ударило: “Вообще-то всю статику можно грузить по одному TCP-соединению гораздо эффективнее! Какого чёрта у меня до сих пор не поддерживается модный и красивый HTTP/2
?!” Что ж, вопрос требовал скорее действий, чем ответа, поэтому недолго думая, я начал копать, как же там всё у nginx
с этим обстоит. Я в течение всего года наблюдал, как постепенно в этом веб-сервере пилится поддержка HTTP/2
в версиях 1.9.x. И действительно, поддержка уже есть, но она всё ещё обкатывается, о чём свидетельствует название PPA, который мне пришлось добавить:
sudo add-apt-repository ppa:nginx/development
В ppa:nginx/stable
всё ещё версия 1.8.0. Но, как я всегда говорю, жизнь меня ничему не учит мои пет-проекты вовсе никакие не супер-важные, поэтому я решил обновиться. Почему нет. Итак, поддержка HTTP/2
у меня была в кармане.
Немного проглядев информацию про сам протокол, стало понятно, что он может работать только в шифрованном режиме. Получать через пень-колоду бесплатный долгосрочный сертификат через китайцев, как я это делал прошлой весной, вовсе не хотелось. Хотелось попробовать что-то новое. И тут очень кстати мне вспомнился проект Let’s Encrypt.
Let’s Encrypt и бесплатный HTTPS всем
Этот амбициозный проект был начат двумя сотрудниками Mozilla, но теперь он уже существенно вырос и обзавёлся поддержкой многих гигантов (таких как Akamai, Cisco, Facebook). Центр сертификации Let’s Encrypt вошёл в стадию открытой беты в начале декабря 2015 года и с тех пор раздаёт бесплатные сертификаты. Сертификаты выдаются всего на 3 месяца, но процесс их получения заключается в запуске всего лишь одного скрипта с указанием e-mail’а и доменов. Мне сходу понравилась эта простота после китайцев, да и бесплатность была тоже очень кстати.
Этот скрипт, который вам придётся поставить на сервер, проверяет, что вы являетесь владельцем домена. Это возможно в нескольких режимах:
apache
– его я не пробовал, у меня жеnginx
, но, поговаривают, этот режим весь такой красивый и полностью автоматизированныйstandalone
– через запуск встроенного веб-сервера на 80-м порту, что мне тоже не подошло, у меня жеnginx
на нём висит и работает в любой момент времениwebroot
– выбрал именно этот вариант, проверка осуществляется созданием специального файла в корневой директории сайта, которую вы укажете в параметре--webroot
Я склонировал репозиторий себе:
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
Разобравшись с параметрами, у меня в итоге получилась примерно такая команда для получения сертификата:
./letsencrypt-auto certonly --webroot -w /var/www/spaceismine/html/ --email [email protected] -d spaceismine.org -d www.spaceismine.org
Вероятно, понадобится sudo-пароль, потому что скрипт будет записывать сертификаты в /etc
. Но у меня sudo
уже торчал в сессии, не помню, чтобы мне приходилось вводить пароль. После того, как команда успешно отработала, в директории /etc/letsencrypt/live/spaceismine.org
аккуратным образом появились симлинки на ключ, сертификат, цепочки.
nginx ~ HTTP/2 ~ HTTPS
Далее нужно было настроить nginx
. Прикладываю свой конфиг:
server {
listen 80;
server_name spaceismine.org www.spaceismine.org;
rewrite ^(.*) https://spaceismine.org$1 permanent;
}
server {
listen 443 ssl http2;
server_name spaceismine.org;
root /var/www/spaceismine/html;
index index.html;
ssl_certificate /etc/letsencrypt/live/spaceismine.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/spaceismine.org/privkey.pem;
add_header Strict-Transport-Security 'max-age=604800';
}
Суть первых строк в том, что мы HTTP
будем всегда кидать на HTTPS
. Ну и для верности добавим хидер add_header Strict-Transport-Security 'max-age=604800';
, чтобы браузерам было попроще и попонятнее перекидывать пользователя на нужный вариант протокола. Как видите, конфиг вышел на удивление простой, что не может не радовать.
Подвохи и рейтинг A на ssllabs
Затем у меня были некоторые проблемы с тем, что сайт открывался только в Safari. Я долго пытался понять, с чем это может быть связано. Но в итоге вспомнил, что слабые алгоритмы в последнее время активно выпиливаются браузерами, поэтому нашёл способ, как можно было настроить более “качественный” HTTPS
в nginx
.
Прикладываю конфиг секции http
главного конфига nginx.conf
, который позволил добиться мне A на тесте ssllabs:
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_dhparam ssl/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_dhparam ssl/dhparam.pem;
. Да, пришлось сгенерить свой dhparam
на 2048 бит:
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
Учтите, что директория /etc/nginx/ssl
должна существовать, иначе openssl
ничего не сделает.
Далее service nginx restart
и всё стало хорошо во всех браузерах, а в ssllabs начала красоваться A:
Что ж, на этом всё, таков был мой опыт настройки HTTP/2
на своём проекте. Так что если вам это интересно, конечно берите и пробуйте, всё можно использовать уже сейчас.