19.04.2023

Создание самоподписанных SSL-сертификатов для работы по HTTPS

Существуют ограничения между работой по http и https. Например, если произойдет попытка на странице с https загрузить контент по http, то эта попытка будет заблокирована.

Это значит, если у вас разработка на машине с http, а основная версия по https, то при разработке и тестировании, например, может что-то из скриптов отвалиться запущенных на http, хотя все будет прекрасно работать на версии с https. Поэтому возникает необходимость - использовать https на локальном хосте. 

Сертификаты, в которых не указан атрибут SAN (SubjectAltName), будут приводить к ошибке «Ваше соединение не защищено». Проверка атрибута SAN пошла с версии Chrome 58 и Firefox 48.

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

В этом материале речь пойдет о создании собственного самоподписанного SSL сертификата и включение его в доверенные источники.

Корневой сертификат

Для того чтобы выпустить сертификат для вашего домена, понадобится корневой сертификат. Именно на его основе будут выпускаться все остальные сертификаты. 

Для удобства в дальнейшем, создадим файл rootCA.sh, с содержимым:

#!/bin/bash

# Создаем корневой CA и приватный ключ
openssl req -x509 \
            -sha256 -days 365 \
            -nodes \
            -newkey rsa:2048 \
            -subj "/CN=LocalHub/C=RU/L=Moscow" \
            -keyout rootCA.key -out rootCA.crt

Cоздается корневой сертификат rootCA.crt. Команда openssl req в данном случае включает следующие ключи:

  • -x509 - говорит о том, чтобы на выходе создался сразу самоподписанный сертификат, а не создавался запрос на выпуск сертификата (CSR)
  • -sha256 - алгоритм шифрования
  • -days - на сколько дней сертификат выпускается
  • -nodes - опция позволяет не шифровать закрытый ключ при создании
  • -newkey rsa:2048 - говорит о том, что ключ будет создан новый, т.е. перезаписан. Ключ будет создан размером в 2048 бита. Нельзя делать ключи меньше 512 бита.
  • -subj - атрибуты сертификата, которые в него включаются. Список:
    • CN - Общее имя (CommonName)
    • O - Организация (Organization)
    • OU - Подразделение (OrganizationalUnit)
    • L - Местонахождение (Locality)
    • S - Штат или провинция (StateOrProvinceName)
    • C - Страна (CountryName)
  • -keyout - место куда сохранять приватный ключ
  • -out - место куда сохранять сертификат

Сделаем файл исполняемым и запустим его:

chmod +x ./rootCA.sh && ./rootCA.sh

Получим 2 файла:

./rootCA.crt - Корневой сертификат
./rootCA.key - Приватный ключ корневого сертификата

Сертификат доменного имени

В сертификат обычно входит домен с www и без www (можно убрать или добавить свои DNS). Сделаем также все через скрипт для дальнейшего использования.

Создаем файл domain.sh с содержимым:

#!/bin/bash


# Сделаем проверку на то, пришел ли домен в виде аргумента или нет
if [ "$#" -ne 1 ]
then
  echo "Ошибка: Не указан домен в передаваемом аргументе"
  echo "Как пользоваться: Укажите доменное имя в передаваемом аргументе"
  exit 1
fi

DOMAIN=$1

# Создаем файл конфигурации сертификата
cat > cert.conf <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = ${DOMAIN}
DNS.2 = www.${DOMAIN}
EOF

# Создаем файл конфигурации запроса на выпуск сертификата CSR
cat > csr.conf <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = RU
ST = Moscow
L = Moscow
O = LocalHub
OU = LocalHub Dev
CN = ${DOMAIN}

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = ${DOMAIN}
DNS.2 = www.${DOMAIN}

EOF

# Создаем приватный ключ
openssl genrsa -out ${DOMAIN}.key 2048

# Создаем запрос на выпуск сертификата CSR
openssl req -new \
            -key ${DOMAIN}.key \
            -out ${DOMAIN}.csr \
            -config csr.conf

# Создаем сертификат
openssl x509  -req \
              -in ${DOMAIN}.csr \
              -CA rootCA.crt -CAkey rootCA.key \
              -CAcreateserial -out ${DOMAIN}.crt \
              -days 365 \
              -sha256 -extfile cert.conf

Алгоритм следующий:

  • Вначале идет проверка, передан ли домен или нет. Если не передан, то завершаем скрипт и выводим ошибку
  • Если домен был передан, то вытаскиваем его из первого аргумента в переменную DOMAIN и формируем файлы:
    • Создаем файл конфигурации сертификата cert.conf, куда заносим DNS.1 = ${DOMAIN} и DNS.2 = www.${DOMAIN};
    • Создаем файл конфигурации запроса на выпуск сертификата CSR, куда также заносим:
      • default_bits - размер 2048 бит, 
      • default_md - ставим алгоритм шифрования sha256, 
      • [ dn ] - указываем атрибуты сертификата:
        • CN - Общее имя (CommonName)
        • O - Организация (Organization)
        • OU - Подразделение (OrganizationalUnit)
        • L - Местонахождение (Locality)
        • ST - Штат или провинция (StateOrProvinceName)
        • C - Страна (CountryName)
      • [ alt_names ] - заносим DNS.1 = ${DOMAIN} и DNS.2 = www.${DOMAIN};
  • Создаем приватный ключ для домена. Количество бит можно не ставить (оно по-умолчанию - 2048, но нельзя менее 512)
# Создаем приватный ключ# Создаем приватный ключ
openssl genrsa -out ${DOMAIN}.key 2048
  • Создаем запрос на выпуск сертификата CSR, говоря что это новый запрос ключом -new, какой приватный ключ использовать -key, куда выводить запрос -out, наш конфиг для выпуска сертификата -config 
# Создаем запрос на выпуск сертификата CSR
openssl req -new \
            -key ${DOMAIN}.key \
            -out ${DOMAIN}.csr \
            -config csr.conf
  • Создаем сертификат командой openssl x509. Ключом -req говорим, что будет использоваться запрос на выпуск сертификата, т.е. мы говорим, что подсунем .csr на вход. Соответственно ключом -in подсовываем файл с запросом (-in ${DOMAIN}.csr). Далее нужно указать корневой сертификат и его приватный ключ, которые будут использоваться для подписи (-CA rootCA.crt -CAkey rootCA.key). Опцией -CAcreateserial создаем серийный номер сертификата, если его не существует. Ключ -out говорит о том, куда кладем сертификат для домена. Ключ -days используется для ограничения срока действия сертификата. Ключ -sha256 - указывается алгоритм шифрования. Для того чтобы подсунуть конфиг, используется настройка -extfile (-extfile cert.conf).
# Создаем сертификат
openssl x509  -req \
              -in ${DOMAIN}.csr \
              -CA rootCA.crt -CAkey rootCA.key \
              -CAcreateserial -out ${DOMAIN}.crt \
              -days 365 \
              -sha256 -extfile cert.conf

Сделаем файл исполняемым:

chmod +x ./domain.sh

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

./domain.sh domain.ru

И после этого получить 2 файла (попутно конечно будут созданы файлы с конфигами и запросом на выпуск, но наша цель - это сертификат и ключ):

./domain.ru.crt - Доменный сертификат
./domain.ru.key - Приватный ключ доменного сертификата

Теперь можно брать сертификаты домена и вставлять в nginx/apache-конфиги виртуальных хостов. А для того чтобы браузер не ругался после их подключения, нужно добавить корневой сертификат в доверенные источники.

Добавление корневого сертификата в доверенные источники

Далее, пример добавления будет приведен для Windows

Чтобы добавить корневой сертификат в доверенные источники, скачиваем сертификат rootCA.crt. Кликаем по нему 2 раза правой левой кнопкой мыши. Появится сведения о сертификате (рис. 1). Нажимаем на кнопку "Установить сертификат..."

01.png
Рис. 1. Сведения о сертификате

Запустится мастер импорта сертификатов, нужно становить "Расположение хранилища" в значение "Локальный компьютер" (рис. 2) и нажать на кнопку "Далее".

02.png
Рис. 2. Выбор расположения хранилища

Появится новое окно того же мастера импорта сертификатов, но с выбором куда помещать сертификат (рис. 3). Нужно выбрать "Поместить все сертификаты в следующее хранилище" и нажать на кнопку "Обзор...", чтобы выбрать какие хранилища использовать.

03.png
Рис. 3. Вариант локального расположения сертификатов

Выбираем "Доверенные корневые центры сертификации" (рис. 4) и жмем "ОК".

04.png
Рис. 4. Выбор хранилища сертификата "Доверенные корневые центры сертификации"

После выбора хранилища, оно отобразится в поле "Хранилище сертификатов" (рис. 5). Жмем кнопку "Далее"

05.png
Рис. 5. Выбранное хранилище для сертификата

Последний шаг - завершение мастера импорта сертификатов (рис. 6). На нем, просто жмем кнопку "Готово".

06.png
Рис. 6. Завершение мастера импорта сертификатов

После нажатия на кнопку "Готово" мастера импорта сертификатов запустит импорт. Результат импорта появится на экране. После успешного импорта (рис. 7.) жмем на кнопку "ОК", сертификат добавлен в систему.

07.png
Рис. 7. Успешный импорт сертификатов