Протокол HTTPS был разработан еще в 1994 году, но до сих многие сайты общаются с миром по незащищенному протоколу HTTP, главным образом из-за того, что получение SSL сертификата достаточно нетривиальный и дорогой процесс. Но сейчас ситуация изменилась: некоммерческий проект Let's Enctypt, поддерживаемый Mozilla, Cisco, Facebook, Google и другими крупными компаниями, начал автоматизированную выдачу бесплатных SSL сертификатов на 90 дней. Не стоит пугаться столь малого периода действия - сертификаты выпускаются автоматически с помощью python-скрипта, который можно запускать на регулярной основе (например, раз в месяц).
С одной стороны, понятно желание обезопасить соединение с ресурсами, которые работают c приватной информацией пользователя - пользователь не будет рад, если данные его банковской карты попадут к злоумышленнику, который вмешался в трафик, или если у него украдут логин и пароль от его учетной записи в любимой игрушке. С другой стороны неочевидно, для чего использовать HTTPS-соединение ресурсам, для которых перехват обмена между сервером и пользователем не является критичной проблемой (а это блоги, новостные сайты, сайты-визитки, файлообменники и прочее). На самом деле, есть как минимум две опасности, от которых может защитить внедрение HTTPS:
- Вставка провайдером своей рекламы на страницы ресурса (как это делает, например, оператор WiFi сети московского метрополитена). Что более интересно, провайдер даже может заменять имеющуюся рекламу на свою.
- Вставка злоумышленником вредоносного кода на страницы ресурса. Особенно часто это практикуют зловреды, заражающие WiFi-роутеры: они могут как подменять определенны категории ссылок (ссылки на файлы или известные ресурсы) на фишинговые ресурсы, так и вставлять вредоностный JavaScript.
Конечно, HTTPS не панацея от всех бед, но позволяет проявить хотя бы немного заботы о своем пользователе, тем более что сейчас это не займет много времени (и совсем не потребует денег).
У проекта Let's Encrypt есть шикарная документация и плагины для автоматизированной настройки Nginx и Apache. Я же выбрал путь автоматического получения сертификата через скрипт, запущенный в отдельном docker-контейнере, и ручную настройку Nginx. Все действия производились на Ubuntu 14.04.
Установка Docker
Первом делом нужно установить Docker (если он еще не был установлен).
sudo apt-get install linux-image-extra-`uname -r`
sudo echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" > /etc/apt/sources.list.d/docker.list
sudo aptitude update
sudo aptitude install docker-engine
Получение сертификата
Для автоматизации получения сертификата была разработана утилита letsencrypt. Код открыт, написан на Python, можно даже поизучать в случае сомнений в безопасности.
Для получение сертификата необходимо подтвердить права на владения доменом. В качестве подтверждения предлагается разместить специальный (генерируемый утилитой letsencrypt) файл в root - для этого есть несколько способов:
- Запустить letsencrypt в режиме webroot и донастроить nginx.
- Погасить на время Nginx и запустить letsencrypt в режиме standalone.
Я выбрал второй способ как более простой.
service nginx stop
docker run -it --rm -p 443:443 -p 80:80 --name letsencrypt -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" quay.io/letsencrypt/letsencrypt:latest certonly -d <domen> -d <www.domen> --email <email> --agree-tos --renew-by-default
service nginx start
Где <domen> - доменное имя сайта, для которого получают сертификат (а <www.domen> - тот же домен с www), <email> - контактный email для восстановления. Опция --agree-tos необходима для автоматического согласия с условиями использования, а --renew-by-default позволяет получить сертификат даже в том случае, если период действия старых еще не истек. Стоит обратить внимание, что для корректной работы следует заказать сертификат как для версии сайта с www и без (www.domain.com и domain.com).
После выполнения по пути /etc/letsencrypt/live/<www.domain>/ будут располагаться свежеполученные сертификаты. В моем случае это путь /etc/letsencrypt/live/www.thenno.me/.
Настройка Nginx
Правильно настроенный Nginx должен проксировать все обращения по http на https, и с www.domain.com на domain.com (либо наоборот). Т.е большинстве случаев с http://domain.com, http://www.domain.com и https://www.domain.com на https://domain.com. В противном случае можно ожидать странного поведения от поисковых систем (вплоть до того, что все эти ресурсы будут считаться разными сайтами). За основу можно взять следующий конфиг (я не настоящий Nginx-джедай).
Общие настройки :
# /etc/nginx/ssl/domain.com
ssl_certificate /etc/letsencrypt/live/www.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
Настройки обработки запросов:
# /etc/nginx/sites-available/domain.com
# проксирование с www по 443 порту на non-www версию
# стоит обратить внимание, что эта версия тоже подписана сертификатом, иначе ничего работать не будет
server {
listen 443 ssl;
server_name www.domain.com;
include /etc/nginx/ssl/domain.com;
return 301 https://domain.com$request_uri;
}
# проксирование с http на https
server {
listen 80;
server_name domain.com www.domain.com;
return 301 https://domain.com$request_uri;
}
server {
listen 443 ssl;
server_name domain.com;
include /etc/nginx/ssl/domain.com;
location {
<...>
}
}
И сделать
service nginx restart
Если все сделано правильно - при общении с сайтом будет использоваться защищенный https.
Автопродление
Я решил пойти самым простым способом - обновлением по cron раз в месяц (/etc/cron.monthly/letsencrypt):
#!/bin/sh
# letsencrypt cron monthly
set -e
service nginx stop
docker run -it --rm -p 443:443 -p 80:80 --name letsencrypt -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" quay.io/letsencrypt/letsencrypt:latest certonly -d <non-www domain> -d <www domain> --email <email> --agree-tos --renew-by-default
service nginx start
exit 0
Т.е остановить Nginx, запросить сертификат для www и non-www версий домена и стартовать Nginx опять.
Comments
comments powered by Disqus