Свой центр сертификации - openssl

Здесь я покажу вам, как можно создать свой центр сертификации и выпускать свои сертификаты для ваших тестовых или внутренних веб серверов.

Введение

Причины использовать само-подписанные ssl-сертификаты:

  • При работе с тестовыми веб-серверами. Когда вам требуется протокол https. Удобно иметь свой центр сертификации и для каждого тестового сайта выпускать сертификаты.
  • При работе с внутренними web-серверами. Например у компании есть внутренний сайт, доступный только из внутренней сети. Здесь также необходимо использовать https. Так как доступ к сайту есть у ограниченного числа сотрудников, то на их устройства можно добавить свой корневой ssl-сертификат. И эти устройства начнут доверять внутреннему сайту компании.

На этом скриншоте, браузер не доверяет сайту, но если нажать на кнопку Дополнительные, то вы всё равно сможете перейти на сайт:

А на этом скриншоте браузер доверяет сайту. Сайт открылся без предупреждений и виден замок в адресной строке:

В этой статье я проделаю следующее:

  • На Debian 11 установлю apache2 и настрою его работу на https (с сертификатами по умолчанию для localhost).
  • Покажу что клиенты пока не доверяют этому сертификату.
  • Создам центр сертификации на этом же сервере. А именно:
    • создам закрытый корневой ключ и открытый корневой ключ (он же корневой сертификат);
    • установлю выпущенный корневой сертификат на компьютер клиента (windows);
    • с помощью корневого ключа и сертификата, выпущу ключ и сертификат для домена (для веб-сервера).
  • Затем я настрою apache2 на использование созданных мною закрытого ключа и сертификата для веб-сервера. И продемонстрирую вам что клиентский браузер начал доверять сертификату сайта.
  • Дальше я установлю и настрою другой веб-сервер — nginx. Настрою его на работу по протоколу https. И продемонстрирую доверие браузера к сайту.

Теория

Протокол HTTPS - это объединение протоколов HTTP + SSL/TLS, протокол TLS - это асинхронное шифрование. То есть создаётся пара ключей. И то, что один ключ может зашифровать, другой может расшифровать и наоборот. В протоколе HTTPS эти ключи не равнозначные:

  • закрытый ключ — это обычный ключ шифрования применяемый в асинхронном шифровании.
  • открытый ключ — это тоже ключ шифрования. Но он дополнительно содержит некоторую информацию, например имя домена, имя организации и другое. Такой ключ называют сертификатом.

А ещё протокол TLS позволяет создавать цепочки сертификатов. То-есть, если браузер доверяет родительскому сертификату, то он автоматически будет доверять и всем дочерним сертификатам. А чтобы создать дочернюю пару ключей, нужно иметь доступ к родительской паре ключей.

Корневая пара ключей обычно не подтверждает никакой домен. А используется для создания промежуточных сертификатов или сертификатов для доменов (для web-серверов).

Обычно, когда создают ssl-сертификат для домена, то для безопасности отнимают у него право создания дочерних сертификатов.

Корневой ключ обычно защищают паролем. Это уже симметричное шифрование, когда зная один ключ (пароль) можно зашифровать и расшифровать файл закрытого ключа.

Сервер на котором создают корневые сертификаты, а затем с их помощью выпускают сертификаты для доменов называют — центр сертификации.

Устанавливаю apache2

Устанавливаю:

$ sudo apt install apache2

Настраиваю его работу по протоколу https:

$ sudo a2enmod ssl
$ sudo a2ensite default-ssl.conf
$ sudo systemctl restart apache2

Проверяю доверие к ssl-сертификату сайта, открыв его по https:

  • Как видите, доверия нет.

Создание центра сертификации

Создание корневого закрытого ключа

Для создания ssl/tls сертификатов можно использовать утилиту openssl, она не требует админских прав.

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

$ openssl genpkey -algorithm RSA -out rootCA.key -aes-128-cbc
   ....................................+++++
   ......................+++++
   Enter PEM pass phrase:
   Verifying - Enter PEM pass phrase:
  • genpkey — команда для создания закрытого ключа.
  • -algorithm RSA — алгоритм асинхронного шифрования, именно он используется для выделения открытого ключа из этого закрытого.
  • -out rootCA.key — получаемый файл закрытого ключа.
  • -aes-128-cbc — алгоритм симметричного шифрования, которым мы зашифруем файл закрытого ключа с помощью пароля.

Создание корневого сертификата

Теперь создаю корневой сертификат (открытый ключ):

$ openssl req -x509 -new -key rootCA.key -sha256 -days 3650 -out rootCA.crt
   Enter pass phrase for rootCA.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]:RU
   State or Province Name (full name) [Some-State]:Moscow
   Locality Name (eg, city) []:Moscow
   Organization Name (eg, company) [Internet Widgits Pty Ltd]:Sysadminium
   Organizational Unit Name (eg, section) []:.
   Common Name (e.g. server FQDN or YOUR name) []:Sysadminium
  • req* — создаёт сертификаты или запросы на сертификаты.
  • -x509 — создаёт сертификат а не запрос.
  • -new — создаёт новый сертификат (нужно будет ввести значения некоторых полей в сертификате).
  • -key rootCA.key — используемый закрытый ключ, из которого нужно создать открытый.
  • -sha256 — алгоритм хеширования, чтобы создать подпись ключа.
  • -days 3650 — выпускаем сертификат на 10 лет (обратите внимание что закрытые ключи не имеют срока жизни а сертификаты имеют).
  • -out rootCA.crt — получаемый сертификат.

Итак, я создал пару ключей:

$ ls -l root*
-rw-r--r-- 1 alex alex 1306 сен  9 11:26 rootCA.crt
-rw------- 1 alex alex 1874 сен  9 11:19 rootCA.key

Когда мы будем создавать дочерние сертификаты для доменов, нам понадобится файл с порядковым номером выпускаемых сертификатов. Он должен быть с тем же именем что и корневой ключ, но иметь расширение srl.

Создаю файл порядковых номеров для выпуска сертификатов, в нём следует указать два нуля:

$ nano rootCA.srl
00

Дальше нужно передать корневой сертификат на клиентские компьютеры и установить его в доверенные корневые центры сертификации.

Установка корневого сертификата на Winows

Установить сертификаты на Windows очень просто. Дважды щелкаем по сертификату, открывается окно с его свойствами. Дальше нажимаем на кнопку Установить сертификат:

Установить можно для текущего пользователя или для всего компьютера - я выберу Текущий пользователь:

После нажатия на кнопку Далее нужно выбрать Поместить все сертификаты в следующее хранилище и нажать Обзор:

В открывшемся окне выбираем Доверенные корневые центры сертификации:

Затем нажимаем кнопку ОК, Далее и Готово. И наконец, подтверждаем установку сертификата:

И затем нужно будет ещё раз нажать кнопку ОК.

Если вы еще раз откроете свойства сертификата (двойным щелчком по нему), то увидите что система начала ему доверять:

Подготовка конфига для создания ключей для домена

Теперь, с помощью корневых ключей мы можем создать ключи для домена. У меня будет домен — site.sysadminium.ru.

Утилита openssl не может без конфигурационного файла добавлять некоторые поля. А нам нужно будет в сертификат добавить поле subjectAltName. Без этого поля браузер Chrome не доверяет сертификату.

Поэтому вначале я создаю следующий конфиг:

$ nano sysadminium.cnf

[ req ]
default_bits = 2048
distinguished_name  = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]
countryName                  = Country Name (2 letter code)
countryName_default          = RU
stateOrProvinceName          = State or Province Name (full name)
stateOrProvinceName_default  = Moscow
localityName                 = Locality Name (eg, city)
localityName_default         = Moscow
organizationName             = Organization Name (eg, company)
organizationName_default     = Sysadminium
commonName                   = Common Name (eg, YOUR name or FQDN)
commonName_max               = 64
commonName_default           = site.sysadminium.ru

[ req_ext ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName          = DNS:site.sysadminium.ru

В блоке [ req ] — настраивается команда req:

  • default_bits = 2048 — длина ключа по умолчанию.
  • distinguished_name = req_distinguished_name — это поля в сертификате, например Common Name, organizationName и другие. Для этих полей мы создадим блок req_distinguished_name ниже.
  • req_extensions = req_ext — расширение для req, здесь мы можем добавить дополнительные поля в сертификат. А в этом параметре мы просто указываем что ниже будет блок req_ext с дополнительными полями.

Блок [ req_distinguished_name ] — служит для конфигурации полей сертификата.

А в блок [ req_ext ] — можно добавить некоторые расширяющие свойства сертификата:

  • basicConstraints = CA:FALSE — полученные сертификаты нельзя будет использовать как центр сертификации. Другими словами, забираем у сертификатов для доменов право создавать дочерние сертификаты.
  • keyUsage = nonRepudiation, digitalSignature, keyEncipherment — созданный ключ будет иметь следующие свойства: 
    • неотказуемость (если ключом что-то подписали то аннулировать подпись невозможно), 
    • цифровая подпись (сертификат можно использовать в качестве цифровой подписи), 
    • шифрование ключей (сертификат можно использовать для симметричного шифрования).
    • Об этих свойствах на английском написано  здесь .
  • subjectAltName = DNS:site.sysadminium.ru — указываем поле subjectAltName и его значение. Как я уже говорил, без этого поля браузер не доверяет сертификату.

Создание закрытого ключа и сертификата для домена

Теперь создадим закрытый ключ для домена:

$ openssl genpkey -algorithm RSA -out site.key
   .......................................+++++
   .............+++++

С помощью закрытого ключа создадим файл запроса на сертификат:

$ openssl req -new -key site.key -config sysadminium.cnf -reqexts req_ext -out site.csr

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) [RU]:
State or Province Name (full name) [Moscow]:
Locality Name (eg, city) [Moscow]:
Organization Name (eg, company) [Sysadminium]:
Common Name (eg, YOUR name or FQDN) [site.sysadminium.ru]:
  • Обратите внимание, все параметры были использованы из конфига, вручную мне не пришлось ничего вписывать.

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

$ openssl x509 -req -days 730 -CA rootCA.crt -CAkey rootCA.key -extfile sysadminium.cnf -extensions req_ext -in site.csr -out site.crt
  • x509 — создание сертификата путём подписывания.
  • -req — если подписывать будем файл запроса, то нужно использовать эту опцию.
  • -days 730 — сертификат на 2 года.
  • -CA rootCA.crt -CAkey rootCA.key — указываю корневую пару ключей.
  • -extfile sysadminium.cnf — файл, содержащий расширения сертификатов.
  • -in site.csr -out site.crt — файл запроса и файл сертификата.

После проделанного у меня появились три файла связанных с сертификатом для домена:

$ ls -l site.*
-rw-r--r-- 1 alex alex 1257 сен  9 14:27 site.crt # сертификат
-rw-r--r-- 1 alex alex 1098 сен  9 14:17 site.csr # запрос
-rw------- 1 alex alex 1704 сен  9 14:15 site.key # ключ

Настройка apache2

Кинем сертификат и ключ в следующие каталоги:

$ sudo cp site.crt /etc/ssl/certs/
$ sudo cp site.key /etc/ssl/private/

Настроим apache2 на использование этих ключей:

$ sudo nano /etc/apache2/sites-enabled/default-ssl.conf

   SSLCertificateFile      /etc/ssl/certs/site.crt
   SSLCertificateKeyFile /etc/ssl/private/site.key

Применим изменения:

$ sudo systemctl reload apache2

Проверим как открывается наш сайт с устройства на котором установлен корневой сертификат:

  • Браузер начал доверять тестовому сайту.

Смотрим на сертификат из Chrome

Нажмите на замочек возле адреса сайта. Дальше нажмите на Безопасное подключение / Действительный сертификат. Откроются свойства сертификата:

На вкладке Подробнее вы можете изучить и остальные свойства. Например, помните мы указывали алгоритм ассиметричного шифрования — RSA:

А помните, мы создали файл для серийных номеров выпускаемых сертификатов и записали в нём 00:

А в расширениях видно альтернативное имя:

Настраиваем веб-сервер Nginx

Я покажу как настроить Nginx на использование наших сертификатов. Для начала выключу apache2 и установлю nginx:

$ sudo systemctl stop apache2.service
$ sudo apt install nginx

И настрою его. Нужно рас-комментировать и поменять значения некоторых полей:

$ sudo nano /etc/nginx/sites-enabled/default

   listen 443 ssl default_server;
   listen [::]:443 ssl default_server;
   ssl_certificate     /etc/ssl/certs/site.crt;
   ssl_certificate_key /etc/ssl/private/site.key;

Применю изменения:

$ sudo systemctl reload nginx

Проверю доверие к ssl-сертификату сайта, обновив страничку в браузере.

Здесь apache2 создал свою индексную страничку, поэтому оба веб сервера (nginx и apache2) используют одну и туже страницу. Но как вы помните, я отключил apache2, так что у меня точно отвечает nginx.

Итог

Надеюсь я смог объяснить, как сделать свой центр сертификации и начать выпускать свои собственные сертификаты для доменов. Мы создали следующие файлы:

  • rootCA.key — корневой закрытый ключ. Используется для создания дочерних сертификатов. Обычно лежит на сервере центра сертификации и зашифрован с помощью пароля.
  • rootCA.srl — корневой сертификат. Используется для создания дочерних сертификатов. Его нужно распространить на все ваши компьютеры и установить в хранилище корневых сертификатов. Его тоже можно защитить паролем, но я этого не делал.
  • site.key — ключ для домена (для веб сервера). Его можно было сгенерировать на веб-сервере и не передавать на сервер центра сертификации. Но в моём примере был один сервер и для веб-сервера и для центра сертификации.
  • site.csr — файл запроса на сертификат для домена. Его также можно было сделать на веб-сервере и передать в центр сертификации, чтобы там выпустить сертификат.
  • site.crt — сертификат для домена (для веб сервера). Этот файл создаётся из файла запроса на сертификат с помощью пары корневых ключей.

Также я показал, как использовать созданные сертификаты для настройки веб серверов: apache2 и nginx.


Если понравилась статья, подпишись на мой канал в  VK  или  Telegram .