Настройка mTLS в NGINX на Linux

Обновлено Обновлено: Опубликовано Опубликовано:

Используемые термины: mTLSNGINX, Linux.

В данной инструкции мы рассмотрим:

  • Создание сертификатов сервера и клиента.
  •  Настройку NGINX для аутентификации клиента.
  • Создание и настройку инфраструктуры отзыва сертификатов.

Изучим работу с mTLS в NGINX по шагам.

Настройка mTLS на NGINX

В рамках данной инструкции мы не будем рассматривать установку и базовую настройку NGINX, а сосредоточим внимание на mTLS. Процесс разобьем на этапы.

Настройка HTTPS

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

mkdir /etc/ssl/server

И сами ключи:

openssl req -new -x509 -days 1461 -nodes -out /etc/ssl/server/cert.crt -keyout /etc/ssl/server/cert.key -subj "/CN=mtls.dmosk.local"

* это простой способ создать сертификат с открытым и закрытым ключами в каталоге /etc/ssl/server.

Редактируем файл виртуального домена NGINX. Данных файлов может быть несколько, как правило, они расположены в каталогах:

  • /etc/nginx/sites-enabled (sites-available).
  • /etc/nginx/conf.d.

Или можно открыть конфигурационный файл с доменом по умолчанию. Он также может иметь различное расположение, например:

vi /etc/nginx/conf.d/default.conf

Для настройки https должны быть настроены директивы:

  • listen — указать порт, на котором слушать запросы (для https, как правило, 443), а также опцию ssl.
  • ssl_certificate — путь до файла с открытым ключом.
  • ssl_certificate_key — путь до файла с закрытым ключом.

В моем случае конфигурация имела такие значения вышеописанных опций:

server {
    ...
    listen       443 ssl;
    ...
    ssl_certificate     /etc/ssl/server/cert.crt;
    ssl_certificate_key /etc/ssl/server/cert.key;
    ...
}

Проверяем корректность конфигурации и перечитываем конфигурацию nginx:

nginx -t && nginx -s reload

Для проверки можно выполнить curl-запрос:

curl -k https://127.0.0.1

Сервер должен вернуть html для страницы вашего сайта. HTTPS настроен — переходим к настройке mTLS.

Настройка аутентификации клиента

Завершаем настройку mTLS, указав, что веб-сервер NGINX должен проверять клиента. Нам нужно сформировать клиентский сертификат. Мы также будем использовать самозаверенные ключи.

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

mkdir /etc/ssl/client

cd /etc/ssl/client

Сформируем ключи для центра сертификации:

openssl req -newkey rsa:2048 -nodes -keyout ca.key -x509 -days 3650 -subj "/C=RU/ST=SPb/L=SPb/O=Global Security/OU=IT Department/CN=ca" -out ca.crt

Этого достаточно для настройки NGINX — открываем конфигурационный файл (в нашем примере мы работали с доменом по умолчанию):

vi /etc/nginx/conf.d/default.conf

Добавил такие директивы:

server {
    ...
    ssl_client_certificate /etc/ssl/client/ca.crt;
    ssl_verify_client on;
    ...
}

* где:

  • ssl_client_certificate — путь до открытого ключа центра сертификации, который будет использоваться для проверки клиентов.
  • ssl_verify_client — включает или отключает проверку сертификатов. В нашем случае, включает.

Проверяем корректность конфигурации веб-сервера и перезапускаем его:

nginx -t && nginx -s reload

Теперь пробуем сделать http-запрос:

curl -k https://127.0.0.1

Мы должны получить ошибку:

<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.25.2</center>
</body>
</html>

mTLS работает.

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

Подключение клиента к веб-серверу

Теперь рассмотрим, как создать клиентский сертификат и использовать его.

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

Предполагается, что мы по-прежнему, находимся в каталоге с клиентскими сертификатами:

cd /etc/ssl/client

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

export CLIENT_NO=01

Создадим файл запроса сертификата:

openssl req -newkey rsa:2048 -keyout client${CLIENT_NO}.key -out client${CLIENT_NO}.csr -nodes -days 731 -subj "/CN=client${CLIENT_NO}"

* в результате мы получим файл закрытого ключа client01.key и файл запроса client01.csr.

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

openssl x509 -req -in client${CLIENT_NO}.csr -out client${CLIENT_NO}.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 731

* будет сформирован ключ client01.crt. Мы используем ключи центра сертификации ca.crt и ca.key, которые сформировали ранее, а открытый ключ указали в nginx для аутентификации клиентов.

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

curl -k --key client${CLIENT_NO}.key --cert client${CLIENT_NO}.crt https://127.0.0.1

На этот раз, мы должны увидеть html-код, сформированный сервером.

Настройка клиента Windows

В качестве примера, рассмотрим настройку системы Windows.

Если мы попробуем перейти на веб-страницу с настроенным mTLS, браузер должен вернуть ошибку 400:

Ошибка 400 при попытке перейти на страницу, требующую аутентификацю клиента

Идем на наш сервер в каталог, где лежат созданные клиентские сертификаты.

Сконвертируем pfx-файл:

openssl pkcs12 -inkey client${CLIENT_NO}.key -in client${CLIENT_NO}.crt -export -out client${CLIENT_NO}.pfx

Обязательно, придумываем и вводим пароль для экспорта закрытого ключа (например, 12345678).

Полученный файл (в нашем случае, client01.pfx) копируем на компьютер с Windows (например, с помощью WinSCP) и выполняем импорт в браузер (в настройках конкретного браузера).

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

Отзыв сертификата

Рассмотрим как процесс настройки сервера, так и отзыва сертификата.

Подготовка сервера

Наш сервер должен быть настроен для возможности отозвать сертификат.

Мы должны быть в каталоге с клиентскими сертификатами:

cd /etc/ssl/client

Создадим каталог demoCA и в нем 2 файла:

mkdir ./demoCA

touch ./demoCA/index.txt

echo 1000 > ./demoCA/crlnumber

* где:

  • index.txt — файл с перечнем отозванных сертификатов.
  • crlnumber — файл с регистром номера CRL.

** расположение, имя каталога и файлов определяется конфигурационным файлом openssl.cnf. В данной инструкции предполагаются стандартные настройки, но если у вас свои настройки, то ориентироваться нужно на них.

Настраиваем nginx:

vi /etc/nginx/conf.d/default.conf

server {
    ...
    ssl_crl /etc/ssl/client/crl.pem;
    ...
}

* мы указали веб-серверу учитывать ключ с перечнем отозванных сертификатов.

Так как ключа crl.pem пока нет, NGINX перезагружать нельзя.

Переходим к отзыву сертификата.

Отзыв сертификата

Предположим, что нам нужно отозвать сертификат client03. Вводим команду:

openssl ca -revoke client03.crt -keyfile ca.key -cert ca.crt

И формируем актуальный файл crl:

openssl ca -keyfile ca.key -cert ca.crt -gencrl -out crl.pem

Готово. Теперь можно перезапустить nginx:

nginx -t && nginx -s reload

Проверим отправку http-запроса с помощью отозванного сертификата:

curl -k --key client03.key --cert client03.crt https://127.0.0.1

Мы должны получить ошибку с кодом 400.

Пример работы с FreeIPA

Дополнительно, рассмотрим пример получения и использования сертификатов от FreeIPA.

Запрос пользовательского сертификата

Сначала нам нужно сформировать запрос на получение сертификата. Это можно сделать на любом компьютере. Мы рассмотрим пример на Linux с помощью утилиты openssl.

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

export CLIENT_NAME=user1

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

openssl req -newkey rsa:2048 -keyout ${CLIENT_NAME}.key -out ${CLIENT_NAME}.csr -nodes -days 731 -subj "/CN=${CLIENT_NAME}"

Выводим на экран последовательность для запроса:

cat ${CLIENT_NAME}.csr

Полученные строки копируем. Они нам понадобятся чуть позже.

Открываем веб-интерфейс FreeIPA и переходим в настройки пользователя. Кликаем Действия - Новый сертификат:

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

В открывшемся окне заполняем данные формы. В качестве запроса вставляем ту последовательность, которую получили на сервере nginx:

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

Нажимаем Выдать. Сертификат должен сформироваться и стать доступным для просмотра. В соответствующем разделе кликаем Действия - Получить:

Выводим на экран полученный сертификат пользователя

На экране появится сертификат. Копируем его и возвращаемся на компьютер, где у нас находится закрытый ключ.

Создадим файл сертификата:

vi ${CLIENT_NAME}.crt

Копируем в него последовательность пользовательского сертификата, которую получили в веб-интерфейсе FreeIPA.

Мы можем протестировать полученный сертификат:

curl -k --key ${CLIENT_NAME}.key --cert ${CLIENT_NAME}.crt https://127.0.0.1

Запрос должен нам вернуть страницу без ошибки с кодом 400.

Если нам нужно импортировать сертификат на компьютер с Windows, получаем PFX командой:

openssl pkcs12 -inkey ${CLIENT_NAME}.key -in ${CLIENT_NAME}.crt -export -out ${CLIENT_NAME}.pfx

Отзыв сертификата в FreeIPA

FreeIPA позволяет администратору легко отозвать сертификат в веб-интерфейсе.

Но наш сервер nginx не получит соответвующую информацию по отзыву. Чтобы решить эту проблему, можно написать небольшой скрипт:

#!/bin/bash
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

IPA_SERVER=ipa-server.dmosk.ru

curl -o /tmp/MasterCRL.crl -L "https://${IPA_SERVER}/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL"
openssl crl -in /tmp/MasterCRL.crl -inform DER -out /etc/ssl/client/crl.pem
rm -f /tmp/MasterCRL.crl
nginx -t && nginx -s reload

Данный скрипт выполнит запрос к серверу FreeIPA и получит сертификат отзыва в формате DER. После мы конвертируем DER в PEM и размещаем файл по пути, где nginx ожидает найти сертификат отзыва (в нашем примере это /etc/ssl/client/crl.pem). Последнее, скрипт проверит конфигурацию nginx и перезапустит его.

Наш скрипт можно поместить в cron, чтобы обновлять информацию по отзывам в автоматическом режиме.

Читайте также

Дополнительная информация, которая может оказаться полезной.

1. NGINX на CentOS 7 — установка и настройка.

2. Правильная настройка SSL в NGINX.

3. Настройка NGINX для HTTP/2 по шагам.

4. Сертификат для Linux в центре сертификации Active Directory Certificate Services.

5. Установка и использование FreeIPA на Rocky Linux или CentOS.

# Linux # NGINX # Безопасность # Интернет # Серверы
Дмитрий Моск — частный мастер
Была ли полезна вам эта инструкция?

Да            Нет