Debian.pro

Блог для пользователей и администраторов Debian


Nginx, настраиваем ssl.

Сегодня я поиграю в капитана Очевидность и расскажу, как настроить SSL в nginx для отдельно взятого виртуального хоста.

Шучу. На самом деле я начну потихоньку описывать рецепты того, как облегчить связку nginx+apache. А для кого-то (дада, те кто использует php-fpm/php-fcgi) они станут полезными статьями по настройке nginx. Вообще статьи будут сводиться к тому, чтобы избавиться от необходимости загружать дополнительные модули в apache (которые достаточно неплохо повышают прожорливость апача по памяти под большой нагрузкой). Сегодня мы избавимся от mod_ssl (2-4 метра памяти на каждый worker в определенных условиях).

Немного предыстории. mod_ssl в апаче умеет всё. Ему, формально, уже больше 10 лет. Он состоит из костылей для обратной совместимости со старыми протоколами. 90% его функционала сегодня уже никому не требуются. Поэтому его использование бессмысленно в свете того, что есть nginx и поддержка ssl в нем. Мы попробуем облегчить страдания apache по работе с ssl. Зачем? Затем же, зачем apache убирают за nginx. Выставлять apache на 443м порту при том, что на 80м — nginx — глупо.

Подразумевается, что вы уже умеете настраивать nginx, знаете как сгенерировать сертификат или уже купили сертификат у регистратора. У вас должно быть в наличии следующее:
- nginx более или менее свежей версии (я это проделывал на 0.7)
- файл-ключ /var/www/certs/domain.ru.key (желательно, незапароленный, иначе нужно будет вводить пароль при каждом рестарте nginx. Небезопасно, но…. В общем сами решайте.)
- файл-сертификат /var/www/certs/domain.ru.crt от регистратора
- промежуточный сертификат /var/www/certs/domain.ru_bundle.crt от регистратора
или аналогичные самоподписанные файлы.

Я опишу 2 примера:
- первый — на 80 и 443м порту мы получим одинаковый сайт (вы же используете относительные ссылки в href и src, да?)
- второй — с принудительным редиректом с http на https
Оба варианта я пишу из расчета минимальных затрат ресурсов. Можно использовать переменную $scheme, пихать её в if, и если она http — то редиректить на https. Но когда в такую конструкцию вам начнут долбится 1к реквестов в секунду — мало не покажется.

Подготавливаем наш сертификат:
root@nginx-host:~# cat /var/www/certs/domain.ru.crt > /var/www/certs/domain.ru-bundled.crt
root@nginx-host:~# cat /var/www/certs/domain.ru_bundle.crt >> /var/www/certs/domain.ru-bundled.crt

Теперь nginx сможет корректно работать с нашим подписанным сертификатом.

Первый вариант:
Создаём файл /etc/nginx/sites-available/10-domain.ru.conf
Пишем в него следующее:
server {
listen 80;
listen 443 ssl;
server_name domain.ru www.domain.ru;
ssl_certificate /var/www/certs/domain.ru-bundled.crt;
ssl_certificate_key /var/www/certs/domain.ru.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
root /var/www/domain.ru;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:81;
}
... other configuration;
}

Немного пояснений. По нашему конфигу nginx будет слушать 80й порт на всех интерфейсах по http, 443й — по https. server_name — указываем Host-ы, которые обрабатывать в этом server. ssl_certificate — указываем путь до сертификата, который мы подготовили выше. ssl_certificate_key — указываем путь до ключа. Не забывайте, что сертификат и ключ нужно хранить в безопасном месте. Директивами ssl_session_* мы снижаем нагрузку — новая ssl сессия будет устанавливаться раз в 10 минут. Дальше мы проксируем все запросы в apache на locahost, который слушает 81й порт по http. Ну и потом пишем всё остальное (locations со статикой и т.д. и т.п.).
Во всей этой конструкции не стоит забывать, что глюпый вындовзь ХыРы не умеет SNI совсем, плюс SNI не умеют некоторые версии браузеров на висте и семерке. Поэтому пока что не следует на одном IP вешать несколько ssl-сайтов — ХР пойдет за сертификатом для первого. Можно использовать listen ip1:443 ssl; listen ip2:443 ssl; для размещения нескольких сайтов с ssl. Другого варианта пока что нет.
Ещё вам следует проверить, что ваш сайт не содержит в src ссылок вида http://domain.ru/blah — тогда браузеры клиентов будут жаловаться на «небезопасное содержимое на странице».
Вот, вроде как-то так.

Ну и опишем второй вариант (с редиректом) с минимальными затратами ресурсов:
server {
listen 80;
server_name domain.ru www.domain.ru;
rewrite ^/(.*) https://domain.ru/$1 permanent;
# только не забывайте, что query_string в nginx не попадает в uri. А rewrite обрабатывает только uri = не обрабатывает query_string (то, что в ссылке после символа "?")
}

server {
listen 443;
ssl on;
server_name domain.ru www.domain.ru;
ssl_certificate /var/www/certs/domain.ru-bundled.crt;
ssl_certificate_key /var/www/certs/domain.ru.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
root /var/www/domain.ru;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:81;
}
... other configuration;
}

В общем-то сложное позади. Делаем симлинк:
root@nginx-host:~# ln -s /etc/nginx/sites-available/10-domain.ru.conf /etc/nginx/sites-enabled/10-domain.ru.conf
рестартим nginx (именно restart, а не reload):
root@nginx-host:~# /etc/init.d/nginx restart

Теперь радостно выключаем mod_ssl у apache (a2dismod ssl, вроде), удаляем все куски конфигурации.


Комментарии (19):

  1. Убей Apache, спаси конкистадора!
    Серьёзно — давно использую последнюю (последнюю!) версию nginx + php-fpm и с искренним недоумением смотрю на тех, кто использует nginx 0.7 и 0.6, держа за ним апач.
    Большое спасибо за пост, давно хотел попробовать — теперь буду думать на счёт ключа, при переносе сервера на 11.10 до кучи настрою и https.

  2. Собственно, убивать апач не обязательно — если ему поотрубать всё лишнее — он будет быстро бегать. А вообще — лень всему причина. Апач остается, потому что rewrite-директивы переписывать лениво, nginx старый — потому что таких версий он в main-репозиториях squeeze и lenny.

  3. rewrite переписать — абсолютно никаких трудностей. Абсолютно. Ты потратишь пять минут на первую и двадцать секунд на любую последующую строчку, которую нужно переписать.
    А на счёт версии — http://nginx.org/packages/ — нужно просто скачать и dpkg -i один файлик.
    Почитай changelog, тебе захочется освоить кунг-фу конфигурирования nginx, чтобы попробовать хотя бы часть тех плюшек, что они имплементировали.

  4. > rewrite переписать – абсолютно никаких трудностей
    При условии, что ты понимаешь, что написано в исходных реврайтах. Для многих это задача нетривиальная. А некоторые .htaccess и в рассылке с Сысоевым во главе разобрать не могут сутками.

    > А на счёт версии
    При условии достаточного функционала гоняться за версиями не стоит. А за предложенный вами способ — нужно бить по голове, честно. Сидишь потом и за такими «ах, да пакетик легко из dpkg -i поставить» разбираешься часами, чтобы не поломать ничего. В backports лежит 1.1.0 версия, http://nginx.org/packages/ можно подключить как репозиторий, если нужны совсем последние версии.

  5. Установленный один пакет, или, тем более, репозитарий последних версий этого пакета — никак не может превратиться в «разбираться часами», это не arch какой-нибудь, а Debian, всё-таки!
    А на счёт версий — всё-таки почитай changelog, тебе точно будет интересно.

  6. Установленный один пакет может поломать кучу всего в будущем (когда спустя год понадобится сделать aptitude update).

    Changelog я читаю, ничего такого уж революционного из «must have» я там давно не видел. Наверное, с 0.8.х.

  7. Надо таки сделать над собой усилие и разобраться в nginx :)

  8. Charon :

    По-моему, у вас ошибка. В Виндоус ХР только ИЕ не умеет SNI совсем — Фаерфокс и Хром последние умеют. В семёрке ИЕ8 и выше умеют SNI. Про Оперу вот не знаю

  9. XP в принципе не умеет SNI. Если только хром и ФФ используют свои ssl-библиотеки.
    В любом случае — даже IE под XP — достаточно большая аудитория, чтобы не включать SNI.

  10. http://www.startssl.com/ — тут после регистрации дают бесплатный ssl сертификат на год на домен и один поддомен. Лично я, за неимением www, сделал на st. — вдруг надумаю статику выводить на другой сервер или сервис.

  11. Tyler :

    Насколько затратно по ресурсам HTTPS, относительно HTTP? Хочу на форум на логин и регу попробовать этот самый StartSSL, но всё боязно руки не доходят..

  12. Для логина и регистрации вы этого не заметите. Если включать для всего сайта — в полтора-два раза подскакивает нагрузка на процессор, если не кешировать сессии.

  13. Михаил :

    Добрый день, подскажите такую вещь , поставил VestaCP и заметил что SSL настроен и для конфига nginx и apache (то-есть фронт nginx с ссл и на бекенде апач тоже с тем же ссл), можно ли с апача выпилить ссл и поставить хедер https on? и как скажется по нагрузке? Спасибо

  14. Лучше у разработчиков этого адского отродия выясняйте

  15. Дима :

    Влад, либо потри мои комментарии, либо переделай ссылку на https://terrty.net — старый домен я не использую, он утёк к чёрт знает кому, мало ли кто кликнет.

  16. > потри мои комментарии
    Написал аноним )

    В каких ветках-то ?

  17. Дима :

    Чувак, ты почту мою видишь. Вот везде, где эта почта, и сайт *realmfpa.ru

  18. ох, ёпрст %) Пойду в базе поправлю сегодня

  19. Заапдейтил по урлу просто

Написать комментарий