Инфраструктура открытых ключей (PKI) и создание собственного центра сертификации

OpenSSL и инфраструктура открытых ключей (PKI) лежат в основе безопасности современного интернета. С их помощью мы можем шифровать данные на лету, пока они передаются по сети. Нет необходимости вручную шифровать данные перед отправкой — шифрование происходит автоматически. Это критически важно для онлайн-коммерции, банковского дела и любой защищенной коммуникации.

Основы PKI: от SSL к TLS

Secure Sockets Layer (SSL) — это оригинальный протокол шифрования при передаче. Мы используем набор программ и библиотек OpenSSL, но не хотим использовать сам протокол SSL. Вместо этого мы теперь используем протокол Transport Layer Security (TLS). SSL полон устаревшего кода и множества уязвимостей. TLS новее и намного безопаснее. Но даже при работе с TLS мы все равно можем использовать набор OpenSSL.

Как работает шифрование сессии:

Зашифрованный сеанс SSL/TLS использует как симметричные, так и асимметричные механизмы:

  1. Для приемлемой производительности используется симметричное шифрование для шифрования данных при передаче.
  2. Но симметричное шифрование требует обмена закрытым ключом между двумя партнерами по связи.
  3. Для этого SSL/TLS сначала согласовывает асимметричный сеанс, используя механизм обмена открытыми ключами.
  4. После настройки асимметричного сеанса партнеры безопасно обмениваются симметричным ключом.

Коммерческие центры сертификации (CA)

Чтобы это работало, вам нужно установить сертификат безопасности на ваш веб-сервер. Сертификат служит двум целям:

  • Он содержит открытый ключ, необходимый для настройки сеанса асимметричного обмена ключами.
  • Опционально, он может проверять подлинность вашего веб-сайта.

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

ТипПроверкаИспользование
DV (Domain Validation)Только проверка доменаБазовое шифрование, тестирование
OV (Organization Validation)Проверка организацииБизнес-сайты
EV (Extended Validation)Расширенная проверкаБанки, финансовые учреждения

Let’s Encrypt — бесплатный автоматизированный CA, который выдает сертификаты DV. Отлично подходит для публичных сайтов, но не для внутренней инфраструктуры.

Почему нужно создавать свой CA?

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

  • Разработчикам нужны клиентские сертификаты для доступа к серверам разработки.
  • Внутренние сервисы (GitLab, Jenkins, мониторинг) не обязаны иметь публичные доменные имена.
  • Микросервисная архитектура требует безопасного взаимодействия между сервисами.
  • IoT-устройства в локальной сети должны безопасно связываться с сервером.

Покупка коммерческого сертификата для каждого такого случая была бы дорогой и технически сложной. Решение — создать свой частный центр сертификации (CA).

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

Прежде чем настраивать CA, научимся создавать ключи и запросы на сертификаты.

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

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

openssl req -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.crt

Разбор команды:

  • req — подкоманда для управления запросами
  • -newkey rsa:2048 — создаем пару ключей RSA 2048 бит
  • -nodes — не шифруем закрытый ключ (no DES)
  • -keyout domain.key — имя файла для ключа
  • -x509 — создаем самоподписанный сертификат вместо запроса
  • -days 365 — срок действия
  • -out domain.crt — имя файла для сертификата

Создание самоподписанного сертификата с ключом ECC (рекомендуется)

Ключи на эллиптических кривых (ECC) превосходят RSA практически во всех отношениях: они быстрее, безопаснее при меньшей длине и обеспечивают Perfect Forward Secrecy.

openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name secp384r1) -keyout eckey.pem -out eckey.crt -days 365

Часть ec:<(openssl ecparam -name secp384r1) — это подстановка результата одной команды в другую, что позволяет создать ключ ECC одной строкой.

Создание ключа RSA и запроса на сертификат (CSR)

Для получения сертификата от CA (коммерческого или своего) нужно создать ключ и запрос:

openssl req -new -newkey rsa:2048 -nodes -keyout private.key -out request.csr

В интерактивном режиме вас попросят ввести:

  • Country Name (2 letter code)
  • State or Province Name
  • Locality Name
  • Organization Name
  • Organizational Unit Name
  • Common Name (важнейшее поле — доменное имя сервера!)
  • Email Address

Common Name (CN) должно точно совпадать с доменным именем, которое пользователи будут вводить в браузере.

Создание ключа ECC и CSR

ECC требует двух шагов:

# 1. Создание ключа
openssl genpkey -algorithm EC -out eckey.pem -pkeyopt ec_paramgen_curve:P-384 -pkeyopt ec_param_enc:named_curve

# 2. Создание CSR
openssl req -new -key eckey.pem -out eckey.csr

Создание локального центра сертификации (CA)

Существует несколько подходов к созданию своего CA. Мы рассмотрим два основных:

  1. Easy-RSA — простой скриптовый инструмент (используется в OpenVPN)
  2. Dogtag PKI — полноценная система с веб-интерфейсом (корпоративный уровень)

Вариант 1: Easy-RSA (простой, для небольших проектов)

Easy-RSA — это набор скриптов-оберток над openssl, упрощающих создание и управление CA.

Практическое занятие — Настройка CA с Easy-RSA (подходит для Ubuntu, Fedora, CentOS)

Шаг 1: Установка Easy-RSA

# Fedora/CentOS Stream
sudo dnf install easy-rsa

# Ubuntu
sudo apt install easy-rsa

Шаг 2: Инициализация PKI

# Создаем директорию для CA (в домашнем каталоге)
mkdir ~/myca
cd ~/myca

# Инициализируем структуру PKI
/usr/share/easy-rsa/easyrsa init-pki

Шаг 3: Создание корневого CA

Сначала нужно задать параметры по умолчанию. Создайте файл vars:

cat > vars << 'EOF'
set_var EASYRSA_REQ_COUNTRY     "RU"
set_var EASYRSA_REQ_PROVINCE    "Moscow"
set_var EASYRSA_REQ_CITY        "Moscow"
set_var EASYRSA_REQ_ORG         "Strategy RA"
set_var EASYRSA_REQ_EMAIL       "ca@strategyra.ru"
set_var EASYRSA_REQ_OU          "IT Security"
set_var EASYRSA_ALGO            "ec"
set_var EASYRSA_CURVE            "secp384r1"
EOF

Теперь создаем корневой CA:

/usr/share/easy-rsa/easyrsa build-ca

Вас попросят ввести пароль для защиты корневого ключа и Common Name (можно оставить по умолчанию). Будут созданы:

  • pki/ca.crt — публичный сертификат корневого CA
  • pki/private/ca.key — закрытый ключ CA (хранить в безопасном месте!)

Шаг 4: Создание сертификата для сервера

# Создаем запрос и ключ для сервера
/usr/share/easy-rsa/easyrsa gen-req server1

# Подписываем запрос корневым CA
/usr/share/easy-rsa/easyrsa sign-req server server1

Шаг 5: Создание сертификата для клиента

# Для клиента (например, для разработчика Игоря)
/usr/share/easy-rsa/easyrsa gen-req igor
/usr/share/easy-rsa/easyrsa sign-req client igor

Преимущества Easy-RSA:

  • Простота
  • Не требует отдельного сервера
  • Идеально для небольших команд и VPN

Недостатки:

  • Нет веб-интерфейса
  • Все операции через командную строку
  • Сложнее управлять большим количеством сертификатов

Вариант 2: Dogtag PKI (корпоративный уровень)

Dogtag PKI — полноценная система управления сертификатами с веб-интерфейсом, поддержкой ролей и автоматизацией.

Практическое занятие — Настройка Dogtag CA на CentOS Stream 10 / Fedora 43

Шаг 1: Подготовка системы

Установите Fully Qualified Domain Name (FQDN):

sudo hostnamectl set-hostname ca.strategyra.local

Отредактируйте /etc/hosts, добавив:

192.168.1.100 ca.strategyra.local

Увеличьте лимит открытых файлов (редактируем /etc/security/limits.conf):

root            hard    nofile          4096
root            soft    nofile          4096

Перезагрузитесь для применения изменений.

Шаг 2: Установка пакетов

sudo dnf install 389-ds-base pki-ca

Шаг 3: Создание экземпляра LDAP Directory Server

Dogtag хранит информацию о сертификатах в LDAP. Создайте файл конфигурации /root/instance.inf:

[general]
config_version = 2
[slapd]
root_password = StrongPassword123!
[backend-userroot]
sample_entries = yes
suffix = dc=ca,dc=strategyra,dc=local

Создайте экземпляр:

sudo dscreate from-file /root/instance.inf

Шаг 4: Создание CA

sudo pkispawn

Принимайте значения по умолчанию. Когда спросит пароль Directory Server, введите тот, что указали в instance.inf.

После завершения удалите файл с паролем:

sudo shred -u -z /root/instance.inf

Шаг 5: Настройка firewall

sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --reload

Шаг 6: Доступ к веб-интерфейсу

На клиентской машине откройте браузер и перейдите по адресу:

https://ca.strategyra.local:8443

Вы увидите предупреждение о самоподписанном сертификате — это нормально, временно примите его.

Шаг 7: Импорт сертификата администратора

На сервере Dogtag:

sudo su -
cd /root/.dogtag/pki-tomcat
scp ca_admin_cert.p12 user@client-machine:/home/user/
exit

На клиентской машине импортируйте этот сертификат в Firefox (Настройки → Приватность и защита → Сертификаты → Импорт).

Шаг 8: Работа с CA через веб-интерфейс

Теперь вы можете:

  • Управлять профилями сертификатов
  • Принимать запросы от пользователей
  • Выпускать сертификаты
  • Отзывать сертификаты

Добавление корневого CA в доверенные

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

Linux (системное хранилище)

Практическое занятие — Добавление CA в системное хранилище (Ubuntu/Fedora)

# Копируем корневой сертификат
sudo cp ca.crt /usr/local/share/ca-certificates/strategyra-ca.crt

# Обновляем хранилище (Ubuntu)
sudo update-ca-certificates

# Для Fedora (формат немного другой)
sudo cp ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust

Firefox (отдельное хранилище)

Firefox использует собственное хранилище, не зависимое от системного.

  1. Откройте Настройки → Приватность и защита → Сертификаты → Просмотр сертификатов
  2. Вкладка “Центры сертификации”
  3. “Импорт” → выберите ваш ca.crt
  4. Отметьте доверие для веб-сайтов и email-пользователей

Windows

  1. Дважды щелкните файл ca.crt
  2. “Установить сертификат”
  3. Выберите “Локальный компьютер” → “Поместить все сертификаты в следующее хранилище”
  4. Выберите “Доверенные корневые центры сертификации”

Настройка веб-серверов с использованием собственного CA

Apache с сертификатом от своего CA

Практическое занятие — Настройка Apache на Ubuntu с сертификатом от своего CA

Шаг 1: Установка Apache

sudo apt update
sudo apt install apache2
sudo a2enmod ssl
sudo a2ensite default-ssl

Шаг 2: Копирование сертификатов

Предположим, вы создали для сервера web01.strategyra.local ключ и сертификат с помощью Easy-RSA или получили их через Dogtag.

sudo cp web01.key /etc/ssl/private/
sudo cp web01.crt /etc/ssl/certs/
sudo chmod 600 /etc/ssl/private/web01.key

Шаг 3: Настройка виртуального хоста

Отредактируйте /etc/apache2/sites-available/default-ssl.conf:

<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerAdmin admin@strategyra.local
        ServerName web01.strategyra.local

        DocumentRoot /var/www/html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        SSLEngine on
        SSLCertificateFile /etc/ssl/certs/web01.crt
        SSLCertificateKeyFile /etc/ssl/private/web01.key

        # Современные настройки безопасности
        SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
        SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
        SSLHonorCipherOrder off
        SSLSessionTickets off
    </VirtualHost>
</IfModule>

Шаг 4: Перезапуск Apache

sudo systemctl restart apache2

Шаг 5: Проверка

На клиентской машине, где импортирован корневой CA, откройте https://web01.strategyra.local — браузер должен доверять сертификату.

Nginx с сертификатом от своего CA

Практическое занятие — Настройка Nginx на Fedora с сертификатом от своего CA

Шаг 1: Установка Nginx

sudo dnf install nginx

Шаг 2: Копирование сертификатов

sudo cp web01.key /etc/nginx/ssl/
sudo cp web01.crt /etc/nginx/ssl/
sudo chmod 600 /etc/nginx/ssl/web01.key

Шаг 3: Настройка сервера

Создайте конфигурацию /etc/nginx/conf.d/web01.conf:

server {
    listen 443 ssl http2;
    server_name web01.strategyra.local;

    ssl_certificate /etc/nginx/ssl/web01.crt;
    ssl_certificate_key /etc/nginx/ssl/web01.key;

    # Современные настройки TLS
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

server {
    listen 80;
    server_name web01.strategyra.local;
    return 301 https://$server_name$request_uri;
}

Шаг 4: Проверка конфигурации и перезапуск

sudo nginx -t
sudo systemctl restart nginx

Самописный сервер на Rust (actix-web) с сертификатом от своего CA

Для современных приложений на Rust часто требуется HTTPS даже на этапе разработки. Использование собственного CA позволяет иметь доверенные сертификаты без покупки коммерческих.

Практическое занятие — Rust-сервер с сертификатом от своего CA

Шаг 1: Создание проекта

cargo new rust-https-server
cd rust-https-server

Добавьте зависимости в Cargo.toml:

[dependencies]
actix-web = "4"
openssl = "0.10"

Шаг 2: Подготовка сертификатов

Скопируйте сертификаты в директорию проекта:

mkdir certs
cp web01.key certs/
cp web01.crt certs/
cp ca.crt certs/  # корневой сертификат (опционально)

Шаг 3: Код сервера

Создайте src/main.rs:

use actix_web::{web, App, HttpServer, HttpResponse, Responder};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use std::io;

async fn greet() -> impl Responder {
    HttpResponse::Ok().body("Привет от защищенного Rust-сервера!")
}

#[actix_web::main]
async fn main() -> io::Result<()> {
    println!("Запуск HTTPS сервера на https://web01.strategyra.local:8443");

    // Настройка SSL
    let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())
        .expect("Ошибка создания SSL контекста");

    builder
        .set_private_key_file("certs/web01.key", SslFiletype::PEM)
        .expect("Ошибка загрузки приватного ключа");

    builder
        .set_certificate_chain_file("certs/web01.crt")
        .expect("Ошибка загрузки сертификата");

    // Для проверки клиентских сертификатов (взаимная аутентификация)
    // builder.set_ca_file("certs/ca.crt").expect("Ошибка загрузки CA");
    // builder.set_verify(openssl::ssl::SslVerifyMode::PEER);

    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(greet))
            .route("/health", web::get().to(|| async { "OK" }))
    })
    .bind_openssl("0.0.0.0:8443", builder)?
    .run()
    .await
}

Шаг 4: Запуск сервера

cargo run

Шаг 5: Проверка

На клиентской машине откройте https://web01.strategyra.local:8443 — браузер должен доверять сертификату.

Взаимная аутентификация (mTLS) на Rust

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

Практическое занятие — mTLS клиент на Rust

Создайте отдельный проект rust-https-client с зависимостями:

[dependencies]
reqwest = { version = "0.11", features = ["rustls-tls"] }
tokio = { version = "1", features = ["full"] }

Код клиента с клиентским сертификатом:

use reqwest::{Certificate, Identity};
use std::fs;
use std::io::BufReader;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Загрузка корневого сертификата CA
    let ca_cert = fs::read("certs/ca.crt")?;
    let ca_cert = Certificate::from_pem(&ca_cert)?;

    // Загрузка клиентского сертификата и ключа (в формате PKCS#12)
    let client_cert = fs::read("certs/client.p12")?;
    let identity = Identity::from_pkcs12_der(&client_cert, "password")?;

    let client = reqwest::Client::builder()
        .add_root_certificate(ca_cert)
        .identity(identity)
        .build()?;

    let response = client
        .get("https://web01.strategyra.local:8443")
        .send()
        .await?;

    println!("Статус: {}", response.status());
    println!("Тело: {}", response.text().await?);

    Ok(())
}

Управление сертификатами и автоматизация

Продление сертификатов

Срок действия сертификатов ограничен. Для своего CA можно создавать сертификаты на любой срок, но рекомендуется не более 1 года для серверных и 2-3 лет для корневого.

Создание сертификата с указанием срока (Easy-RSA):

# При создании запроса указываем срок в днях
/usr/share/easy-rsa/easyrsa --days=365 gen-req server2
/usr/share/easy-rsa/easyrsa --days=365 sign-req server server2

Отзыв сертификатов (CRL)

Certificate Revocation List (CRL) — список отозванных сертификатов.

Создание CRL в Easy-RSA:

# Отзыв сертификата
/usr/share/easy-rsa/easyrsa revoke server2

# Генерация CRL
/usr/share/easy-rsa/easyrsa gen-crl

Веб-серверы нужно настроить на проверку CRL. Для Nginx:

ssl_crl /etc/nginx/ssl/crl.pem;
ssl_stapling on;
ssl_stapling_verify on;

Автоматизация с Ansible

Для управления большим количеством сертификатов удобно использовать Ansible.

Пример плейбука для генерации сертификата:

- name: Генерация сертификата для сервера
  hosts: ca-server
  tasks:
    - name: Создать директорию для сертификатов
      file:
        path: "/opt/certs/{{ item }}"
        state: directory
      loop: "{{ servers }}"

    - name: Генерировать ключ и CSR
      openssl_csr:
        path: "/opt/certs/{{ item }}/{{ item }}.csr"
        privatekey_path: "/opt/certs/{{ item }}/{{ item }}.key"
        common_name: "{{ item }}.strategyra.local"
        country_name: RU
        organization_name: "Strategy RA"
      loop: "{{ servers }}"

    - name: Подписать сертификат корневым CA
      openssl_certificate:
        path: "/opt/certs/{{ item }}/{{ item }}.crt"
        csr_path: "/opt/certs/{{ item }}/{{ item }}.csr"
        ownca_path: /etc/pki/CA/ca.crt
        ownca_privatekey_path: /etc/pki/CA/ca.key
        ownca_privatekey_passphrase: "{{ ca_password }}"
        provider: ownca
      loop: "{{ servers }}"

Усиление безопасности веб-серверов

Apache: отключение устаревших протоколов

Ubuntu (редактируем /etc/apache2/mods-enabled/ssl.conf):

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCompression off
SSLSessionTickets off

CentOS/RHEL/Fedora (редактируем /etc/httpd/conf.d/ssl.conf):

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
SSLHonorCipherOrder on

Nginx: современная конфигурация

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

Криптографические политики в Fedora/CentOS Stream

В современных дистрибутивах можно использовать системные криптополитики:

# Просмотр текущей политики
sudo update-crypto-policies --show

# Установка более строгой политики
sudo update-crypto-policies --set FUTURE

# Режим FIPS (для госсектора)
sudo fips-mode-setup --enable

Важно: Режим FIPS рекомендуется включать при установке ОС, а не после.

Подведем итоги

Создание собственного центра сертификации — это не просто техническая необходимость, а стратегическое решение для организации:

  1. Безопасность: Полный контроль над всей цепочкой сертификатов
  2. Экономия: Нет необходимости покупать сертификаты для каждого внутреннего сервиса
  3. Гибкость: Можно выпускать сертификаты для любых целей (серверы, клиенты, код, email)
  4. Автоматизация: Интеграция с CI/CD, Ansible, Kubernetes

Выбор инструмента:

  • Easy-RSA — для небольших проектов, VPN, простых сценариев
  • Dogtag PKI — для крупных организаций с множеством сервисов и пользователей
  • OpenSSL напрямую — для скриптов и автоматизации

Помните о безопасности корневого ключа:

  • Храните корневой ключ оффлайн, на зашифрованном носителе
  • Используйте аппаратные токены (HSM, YubiKey) для особо важных CA
  • Регулярно создавайте резервные копии
  • Настройте мониторинг истечения сертификатов