Как стать автором
Поиск
Написать публикацию
Обновить

Настройка авторизации через ssl сертификат на уровне nginx

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров16K

Привет уважаемые, хабровчане!

Иногда возникает потребность выдать доступ пользователям только к одному веб ресурсу в компании. Самый очевидный вариант сделать это через урезанный VPN, но тут возникают препятствия в виде девайсов, с которых подключаются пользователи, и качество интернета, которым они пользуются. OpenVPN, который мы пробовали использовать для этих целей, не дал желаемого результата, подключение было медленным и нестабильным.

В поисках более стабильного решения для нашей проблемы мы наткнулись на статью Авторизация с помощью сертификата ssl на nginx + Let's Encrypt.

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

После анализа обнаружили проблему, что алгоритм шифрования который используется в статье, не подходит для нашей конфигурации nginx 1.18.0 + Ubuntu 20.04.4 LTS + Let`s Encrypt, он считается небезопасным. Решением этой ситуации было использование шифрования на эллиптических кривых.

Собственно сама настройка

  1. Перед началом настройки стоит создать следующую структуру конфиг-файлов:

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

mkdir /etc/nginx/example.com #создаем папку, в которой будут лежать наши кофиги и сертификаты
cd /etc/nginx/example.com #переходим в нее
mkdir users_certs certs newcerts #создаем необходимые поддиректории
touch index.txt root.config serial #создаем необходимые кофиг-файлы
echo "01" > serial #записываем первое значение в serial от него система начнет отсчет номеров сертификатов
chmod 700 ./
Итоговая файловая структура
Итоговая файловая структура
  1. Создаем собственный самоподписанный доверенный сертификат (в командах отмечены поля которые нужно заполнить), с алгоритмом шифрования на эллиптических кривых:

openssl ecparam -out /etc/nginx/example.com/certs/root.key -name secp384r1 -genkey
openssl req -new -x509 -days 500 -sha512 -key /etc/nginx/example.com/certs/root.key -subj /O={Название вашей компании}/emailAddress={email создателя сертификата} -out /etc/nginx/example.com/certs/root.crt
  1. В nginx добавляем строки с корневым сертификатом для агентов:

Строки добавляются в конфигурацию nginx целевого ресурса, которая обычно лежит в папке /etc/nginx/sites‑enabled/имя_веб_ресурса.
Данные добавляются в раздел server, где слушается 443 https порт.

ssl_client_certificate /etc/nginx/example.com/certs/root.crt; #путь до корневого сертификата 
ssl_verify_client on;
keepalive_timeout 70;
#ниже необязательные параметры, можно их не указывать
fastcgi_param SSL_VERIFIED $ssl_client_verify; 
fastcgi_param SSL_CLIENT_SERIAL $ssl_client_serial;
fastcgi_param SSL_CLIENT_CERT $ssl_client_cert;
fastcgi_param SSL_DN $ssl_client_s_dn;
  1. В папке /etc/nginx/ssl/ открываем root.config, созданный ранее с необходимыми параметрами для автоматического выпуска сертификатов:

[ ca ]
        default_ca             = CA_CLIENT       
        
        
        [ CA_CLIENT ]
        dir                    = /etc/nginx/example.com/            
        certs                  = /etc/nginx/example.com/certs      
        new_certs_dir          = /etc/nginx/example.com/newcerts   

        database               = $dir/index.txt  
        
        serial                 = $dir/serial     
        
        
        certificate            = $dir/certs/root.crt        
        private_key            = $dir/certs/root.key        

        default_days           = 365 #срок действия пользовательских сертификатов            
        
        default_crl_days       = 7               
        default_md             = md5             

        policy                 = policy_anything 
        
        

        [ policy_anything ]
        countryName            = optional        
        stateOrProvinceName    = optional        
        localityName           = optional        
        organizationName       = optional        
        organizationalUnitName = supplied        
        commonName             = supplied        
        emailAddress           = supplied
  1. На этом настройка аутентификации закончена.

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

  1. Создаем закрытый ключ пользователя (нужно заполнить параметры в скобках):

openssl ecparam -out /etc/nginx/example.com/users_certs/{email пользователя}.key -name secp384r1 -genkey
  1. Создаем CSR сертификат пользователя (нужно заполнить параметры в скобках):

openssl req -new -key /etc/nginx/example.com/users_certs/{email пользователя}.key -subj /C={аббревиатура вашей страны}/ST={название вашего региона}/L={название вашего города}/OU={имя фамилия пользователя}/CN={название компании}/emailAddress={email пользователя} -out /etc/nginx/example.com/users_certs/{email пользователя}.csr
  1. Создаем CRT сертификат пользователя (нужно заполнить параметры в скобках):

openssl ca -config /etc/nginx/example.com/root.config -in /etc/nginx/example.com/users_certs/{email пользователя}.csr -out /etc/nginx/example.com/users_certs/{email пользователя}.crt -batch
  1. Создаем P12 сертификат, который непосредственно будем передавать пользователю ( (нужно заполнить параметры в скобках и задать пароль, который будет использоваться для установки сертификата пользователем):

Если не переживаете, что кто-то случайно удалит сертификаты пользователей, то вывод можно настроить сразу в общую папку, из которой будете их забирать по SFTP. Для этого можете подкорректировать следующий параметр:

-out /etc/nginx/example.com/agent/{email пользователя}.p12

openssl pkcs12 -export -clcerts -in /etc/nginx/example.com/users_certs/{email пользователя}.crt -inkey /etc/nginx/example.com/users_certs/{email пользователя}.key -out /etc/nginx/example.com/users_certs/{email пользователя}.p12 -passout pass:{пароль который хотите задать для сертификата}
  1. Готово. Теперь подключаемся к серверу любым SFTP клиентом и скачиваем сертификат с расширением .p12 и передаем его и пароль пользователю.

Чтобы было проще вот весь этот функционал в одном bash-скрипте, который нужно положить в директорию /etc/nginx/example.com:

#!/bin/bash


echo "Please, enter user name:"
read A 

Q=$(grep -rn $A index.txt | awk '{print $5}' | awk -F/ '{print $6}' | sed  's/OU=//g')

echo "Please, enter user email:"
read B

echo "Please, enter key pass:"
read P

if [[ "$A" = "$Q" ]]
then
echo "this user is already exist"
else 
openssl ecparam -out /etc/nginx/example.com/users_certs/$B.key -name secp384r1 -genkey &&

openssl req -new -key /etc/nginx/example.com/users_certs/{email пользователя}.key -subj /C={аббревиатура вашей страны}/ST={название вашего региона}/L={название вашего города}/OU={имя фамилия пользователя}/CN={название компании}/emailAddress={email пользователя} -out /etc/nginx/example.com/users_certs/{email пользователя}.csr &&

openssl ca -config /etc/nginx/example.com/root.config -in /etc/nginx/example.com/users_certs/$B.csr -out /etc/nginx/example.com/users_certs/$B.crt -batch &&

openssl pkcs12 -export -clcerts -in /etc/nginx/example.com/users_certs/$B.crt -inkey /etc/nginx/example.com/users_certs/$B.key -out /etc/nginx/example.com/users_certs/$B.p12 -passout pass:$P

fi

В итоге схема создания сертификата выглядит так:

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

Покажу на примере Google Chrome

  1. Переходим по следующим скриншотам и добавляем сертификат:

  1. Вводим пароль и нажимаем ОК:

  1. Переходим на целевой сайт, выбираем нужный сертификат в выпадающем окне и нажимаем ОК:

  1. Проверяем что все открылось:

Удаление сертификата

  1. Удалите созданные 4 сертификата пользователя из папки /etc/nginx/example.com/users_certs.

  2. Удалите строчку пользователя из /etc/nginx/example.com/index.txt.

  3. Удалите последний номер из файла /etc/nginx/example.com/serial.

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

Итог

Аутентификация готова, главное не забывать отзывать сертификаты, если пользователю они больше не нужны.

Теги:
Хабы:
Всего голосов 13: ↑13 и ↓0+13
Комментарии11

Публикации

Ближайшие события