UMGUM.COM (лучше) 

Nginx + SSL ( Инсталляция и настройка Nginx + SSL. )

26 марта 2010  (обновлено 31 января 2015)

Эта публикация отнесена в архив. Она неактуальна.
Ресурс по следующей ссылке является преемником: Web сервис на базе "Nginx", PHP-FPM, "NodeJS", "MySQL", "MongoDB", "Memcached", "mSMTP", "inCron", LXC и "Supervisord".

OS: Linux Debian Lenny/Squeeze.
Application: Nginx + SSL.

Примем меры к защите трафика между клиентом и сервером с помощью OpenSSL. Учитывая то, что "front-end" у нас для всех запросов - Nginx, нам достаточно настроить работу с SSL только для него, а "back-end", в роли которого будет работать Apache2 даже знать об этом не будет.

Было бы красиво для каждого сайта, нуждающегося в шифровании трафика, создать или приобрести свой сертификат. Ограничения (или особенности, если вдаваться в терминологию) протокола HTTPS требуют закреплять за каждым виртуальным хостом по выделенному IP. Но, в данном конкретном случае, мы не так богаты, чтобы закупать для каждого ресурса по выделенному IP адресу. Потому придётся создать для всего набора сервисов один сертификат и использовать его применительно к сервисам, нуждающимся в защите (до тех пор, пока не разживемся полноценным заверенным сертификатом).


Установим пакеты приложений работы с сертификатами и шифрованием трафика (скорее всего, они уже установлены):

# aptitude install openssl ssl-cert

Пройдем этапы создания необходимых ключевых файлов.

Создадим себе временную директорию для работы:

# mkdir /tmp/work
# cd /tmp/work

Создаем приватный ключ:

# openssl genrsa -des3 -out domain.name.key 2048

Генерация ключа сопровождается требованием ввести "парольную фразу" для доступа к ключу (её обязательно нужно будет запомнить на время проведения манипуляций с созданием ключевых файлов):

Generating RSA private key, 2048 bit long modulus
........+++
................+++
e is 65537 (0x10001)
Enter pass phrase for domain.name.key:
Verifying - Enter pass phrase for domain.name.key:

Вторым этапом создаем запрос на "самоподписанный" сертификат подлинности (никто его подтвердить не сможет, но шифровать трафик это не помешает):

# openssl req -new -key domain.name.key -out doamin.name.csr

В процессе создания запроса нам понадобится запомненная ранее "парольная фраза". Так же, нас попросят ответить на ряд вопросов о данных, включаемых в сертификат; желательно отвечать на них правдиво, хотя бы и затем, чтобы не запутаться в дальнейшем в своём положении в этом мире. Предложение защитить запрос паролем проще всего проигнорировать:

Enter pass phrase for domain.name.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KZ
State or Province Name (full name) [Some-State]:State
Locality Name (eg, city) []:City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Any
Organizational Unit Name (eg, section) []:Section
Common Name (eg, YOUR name) []:domain.name
Email Address []:support@domain.name
....
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:Company

Следующий финт, даже не этап, состоит в удалении из приватного ключа "парольной фразы", чтобы избежать запроса этой самой фразы при каждом обращении к приватному ключу:

# cp domain.name.key domain.name.key.orig
# openssl rsa -in domain.name.key.orig -out domain.name.key

Enter pass phrase for domain.name.key.orig:
writing RSA key

Последний этап - создание SSL сертификата как такового:

# openssl x509 -req -days 3650 -in domain.name.csr -signkey domain.name.key -out domain.name.crt

Signature ok
subject=/C=KZ/ST=State/L=City/O=ITS/OU=Any/CN=domain.name/emailAddress=support@domain.name
Getting Private key

Раскладываем ключ и сертификат по надлежащим им местам и удаляем все, что было нами для их создания сотворено:

# mkdir -p /var/www/ssl/certs
# mkdir -p /var/www/ssl/private
# cp domain.name.crt /var/www/ssl/certs/
# cp domain.name.key /var/www/ssl/private/
# rm -R /tmp/work

Nginx работает с правами специально созданного для этого пользователя. Соответсвенно ограничиваем доступ к сертификатам:

# chown -R root:www-nginx /var/www/ssl
# chmod -R g-w /var/www/ssl
# chmod -R o-rwx /var/www/ssl

Описание конфигурации виртуального хоста с поддержкой SSL в Nginx отличается от описания обычного наличием следующих директив:

server {
    # описываем виртуальный хост исключительно для отслеживания подключений к порту 80 (http) и перенаправления их на 443 (https)
    listen    *:80;
    server_name u000.local;
    rewrite ^/(.*)$ https://$host/$1 permanent;
}
#
server {
    # указываем серверу прослушивать соответствующий порт
    listen   *:443;
....
    # включаем механизм SSL и, следуя рекомендациям разработчиков сервера, устанавливаем следующие параметры
    ssl    on;
    ssl_protocols          SSLv3 TLSv1;
    ssl_ciphers            AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
    ssl_certificate        /var/www/ssl/certs/domain.name.crt;
    ssl_certificate_key    /var/www/ssl/private/domain.name.key;
    ssl_session_cache      shared:SSL:10m;
    ssl_session_timeout    10m;
....
    # Перенаправление на сервер "back-end"
    location / {
        proxy_pass    http://127.0.0.1:8080/;
        include       /etc/nginx/proxy.conf;
    }
....
}

Удостоверимся в том, что Nginx работает, дополнительно прослушивая ещё и заданный 443 (https) порт:

# netstat -apn | grep tcp | grep nginx

tcp  0  0 0.0.0.0:80   *:*  LISTEN  3573/nginx
tcp  0  0 0.0.0.0:443  *:*  LISTEN  3573/nginx

Попробуем подключится к порту с помощью специального SSL-клиента, проверяя, действительно ли там защищённое соединение:

# openssl s_client -connect domain.name:443

Вывод, если он будет - "говорящий".


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )