Nginx ssl auth: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
(Новая: Авторизация клиентов в nginx посредством SSL сертификатов Blog by admin Введение: Потребовалось мне тут как-то...)
 
 
(не показано 12 промежуточных версий этого же участника)
Строка 1: Строка 1:
  +
[[Категория:nginx]]
  +
[[Категория:SSL]]
  +
  +
=Авторизация клиентов в nginx посредством SSL сертификатов=
   
Авторизация клиентов в nginx посредством SSL сертификатов
 
Blog by admin
 
 
Введение:
 
Введение:
 
Потребовалось мне тут как-то написать небольшой API, в котором необходимо было помимо обычных запросов принимать запросы с «высокой степенью секретности».
 
Потребовалось мне тут как-то написать небольшой API, в котором необходимо было помимо обычных запросов принимать запросы с «высокой степенью секретности».
 
Не я первый с этим столкнулся и мир давно уже использует для таких вещей SSL.
 
Не я первый с этим столкнулся и мир давно уже использует для таких вещей SSL.
  +
<BR>
 
 
Поскольку моём на сервере используется nginx, то был установлен модуль SSL
 
Поскольку моём на сервере используется nginx, то был установлен модуль SSL
 
Гугл не выдал ни одного работоспособного howto, но информация в сети есть по частям.
 
Гугл не выдал ни одного работоспособного howto, но информация в сети есть по частям.
  +
<BR>
 
 
Итак, пошаговое руководство по настройке nginx на авторизацию клиентов через SSL-сертификаты.
 
Итак, пошаговое руководство по настройке nginx на авторизацию клиентов через SSL-сертификаты.
 
Внимание! В статье для примера используются самоподписанные сертификаты!
 
Внимание! В статье для примера используются самоподписанные сертификаты!
Строка 19: Строка 21:
   
   
Шаг 1. Создание собственного самоподписанного доверенного сертификата.
+
==Создание собственного самоподписанного доверенного сертификата.==
  +
<BR>
 
 
Собственный доверенный сертификат (Certificate Authority или CA) необходим для подписи клиентских сертификатов и для их проверки при авторизации клиента веб-сервером.
 
Собственный доверенный сертификат (Certificate Authority или CA) необходим для подписи клиентских сертификатов и для их проверки при авторизации клиента веб-сервером.
 
С помощью приведенной ниже команды создается закрытый ключ и самоподписанный сертификат.
 
С помощью приведенной ниже команды создается закрытый ключ и самоподписанный сертификат.
  +
<PRE>
  +
openssl req -new -newkey rsa:1024 -nodes -keyout ca.key -x509 -days 500 -subj /C=RU/ST=Kharkov/L=Kharkov/O=MirantisInc/OU=User/CN=etc/emailAddress=sirmax@noname.com.ua -out ca.crt
  +
</PRE>
   
openssl req -new -newkey rsa:1024 -nodes -keyout ca.key -x509 -days 500 -subj /C=RU/ST=Moscow/L=Moscow/O=Companyname/OU=User/CN=etc/emailAddress=support@site.com -out ca.crt
 
   
  +
===Описание аргументов:===
   
  +
* req Запрос на создание нового сертификата.
 
  +
* -new Создание запроса на сертификат (Certificate Signing Request – далее CSR).
Описание аргументов:
 
  +
* -newkey rsa:1023 Автоматически будет создан новый закрытый RSA ключ длиной 1024 бита. Длину ключа можете настроить по своему усмотрению.
 
  +
* -nodes Не шифровать закрытый ключ.
req Запрос на создание нового сертификата.
 
  +
* -keyout ca.key Закрытый ключ сохранить в файл ca.key.
-new Создание запроса на сертификат (Certificate Signing Request – далее CSR).
 
  +
* -x509 Вместо создания CSR (см. опцию -new) создать самоподписанный сертификат.
-newkey rsa:1023 Автоматически будет создан новый закрытый RSA ключ длиной 1024 бита. Длину ключа можете настроить по своему усмотрению.
 
  +
* -days 500 Срок действия сертификата 500 дней. Размер периода действия можете настроить по своему усмотрению. Не рекомендуется вводить маленькие значения, так как этим сертификатом вы будете подписывать клиентские сертификаты.
-nodes Не шифровать закрытый ключ.
 
  +
* -subj /C=RU/ST=Kharkov/L=Kharkov/O=MirantisInc/OU=User/CN=etc/emailAddress=sirmax@noanme.com.ua
-keyout ca.key Закрытый ключ сохранить в файл ca.key.
 
-x509 Вместо создания CSR (см. опцию -new) создать самоподписанный сертификат.
 
-days 500 Срок действия сертификата 500 дней. Размер периода действия можете настроить по своему усмотрению. Не рекомендуется вводить маленькие значения, так как этим сертификатом вы будете подписывать клиентские сертификаты.
 
-subj /C=RU/ST=Moscow/L=Moscow/O=Companyname/OU=User/CN=etc/emailAddress=support@site.com
 
 
Данные сертификата, пары параметр=значение, перечисляются через ‘/’. Символы в значении параметра могут быть «подсечены» с помощью обратного слэша «\», например «O=My\ Inc». Также можно взять значение аргумента в кавычки, например, -subj «/xx/xx/xx».
 
Данные сертификата, пары параметр=значение, перечисляются через ‘/’. Символы в значении параметра могут быть «подсечены» с помощью обратного слэша «\», например «O=My\ Inc». Также можно взять значение аргумента в кавычки, например, -subj «/xx/xx/xx».
   
Шаг 2. Сертификат сервера
+
==Сертификат сервера==
 
Создадим сертификат для nginx и запрос для него
 
Создадим сертификат для nginx и запрос для него
  +
<PRE>
 
 
openssl genrsa -des3 -out server.key 1024
 
openssl genrsa -des3 -out server.key 1024
  +
</PRE>
  +
Пароль например q1w2e3
  +
<PRE>
 
openssl req -new -key server.key -out server.csr
 
openssl req -new -key server.key -out server.csr
  +
</PRE>
 
   
   
 
Подпишем сертификат нашей же собственной подписью
 
Подпишем сертификат нашей же собственной подписью
  +
<PRE>
 
 
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
 
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
  +
</PRE>
 
   
   
 
Чтобы nginx при перезагрузке не спрашивал пароль, сделаем для него беспарольную копию сертификата
 
Чтобы nginx при перезагрузке не спрашивал пароль, сделаем для него беспарольную копию сертификата
  +
<PRE>
 
 
openssl rsa -in server.key -out server.nopass.key
 
openssl rsa -in server.key -out server.nopass.key
  +
</PRE>
   
  +
==Конфиг nginx==
 
  +
<PRE>
 
Конфиг nginx
 
 
 
listen *:443;
 
listen *:443;
 
ssl on;
 
ssl on;
Строка 68: Строка 72:
 
ssl_client_certificate /path/to/nginx/ssl/ca.crt;
 
ssl_client_certificate /path/to/nginx/ssl/ca.crt;
 
ssl_verify_client on;
 
ssl_verify_client on;
  +
</PRE>
 
  +
Это уже по необходимости
  +
<PRE>
 
keepalive_timeout 70;
 
keepalive_timeout 70;
 
fastcgi_param SSL_VERIFIED $ssl_client_verify;
 
fastcgi_param SSL_VERIFIED $ssl_client_verify;
Строка 74: Строка 80:
 
fastcgi_param SSL_CLIENT_CERT $ssl_client_cert;
 
fastcgi_param SSL_CLIENT_CERT $ssl_client_cert;
 
fastcgi_param SSL_DN $ssl_client_s_dn;
 
fastcgi_param SSL_DN $ssl_client_s_dn;
  +
</PRE>
 
   
   
Строка 81: Строка 87:
   
 
Однако если вы попытаетесь зайти на сайт, он выдаст ошибку:
 
Однако если вы попытаетесь зайти на сайт, он выдаст ошибку:
  +
<PRE>
 
 
400 Bad Request
 
400 Bad Request
 
No required SSL certificate was sent
 
No required SSL certificate was sent
  +
</PRE>
 
   
   
 
Что ж, логично, в этом-то и вся соль!
 
Что ж, логично, в этом-то и вся соль!
   
Шаг 3. Создание клиентских сертификатов
+
==Создание клиентских сертификатов==
   
3.1 Подготовка CA
+
===Подготовка CA===
  +
Обратить внимаени - Common Name на клиенте не должно совпадать с серверным:
  +
<PRE>
  +
I had the same problem (under Nginx). Solution was to make my client common name something other than the server's certs common name. Originally I thought that my cert CN had to match the FQDN of the server cert.
  +
</PRE>
  +
Иначе - серетфикат работать на будет.
   
Создадим конфиг
 
nano ca.config
 
 
со следующим содержимым:
 
   
  +
Создадим конфиг ca.config со следующим содержимым:
  +
<PRE>
 
[ ca ]
 
[ ca ]
 
default_ca = CA_CLIENT # При подписи сертификатов # использовать секцию CA_CLIENT
 
default_ca = CA_CLIENT # При подписи сертификатов # использовать секцию CA_CLIENT
Строка 125: Строка 134:
 
commonName = optional
 
commonName = optional
 
emailAddress = optional
 
emailAddress = optional
  +
</PRE>
 
   
   
 
Далее надо подготовить структуру каталогов и файлов, соответсвующую описанной в конфигурационном файле
 
Далее надо подготовить структуру каталогов и файлов, соответсвующую описанной в конфигурационном файле
  +
<PRE>
 
 
mkdir db
 
mkdir db
 
mkdir db/certs
 
mkdir db/certs
Строка 135: Строка 144:
 
touch db/index.txt
 
touch db/index.txt
 
echo "01" > db/serial
 
echo "01" > db/serial
  +
</PRE>
   
  +
===Создание клиентского закрытого ключа и запроса на сертификат (CSR)===
 
 
3.2. Создание клиентского закрытого ключа и запроса на сертификат (CSR)
 
   
 
Для создания подписанного клиентского сертификата предварительно необходимо создать запрос на сертификат, для его последующей подписи. Аргументы команды полностью аналогичны аргументам использовавшимся при создании самоподписанного доверенного сертификата, но отсутсвует параметр -x509.
 
Для создания подписанного клиентского сертификата предварительно необходимо создать запрос на сертификат, для его последующей подписи. Аргументы команды полностью аналогичны аргументам использовавшимся при создании самоподписанного доверенного сертификата, но отсутсвует параметр -x509.
  +
<PRE>
 
openssl req -new -newkey rsa:1024 -nodes -keyout client01.key -subj /C=RU/ST=Moscow/L=Moscow/O=Companyname/OU=User/CN=etc/emailAddress=support@site.com -out client01.csr
+
openssl req -new -newkey rsa:1024 -nodes -keyout client01.key -subj /C=RU/ST=Kharkov/L=Kharkov/O=MirantisInc/OU=User/CN=etc/emailAddress=sirmax@noname.com.ua -out client01.csr
  +
</PRE>
 
   
   
 
В результате выполнения команды появятся два файла client01.key и client01.csr.
 
В результате выполнения команды появятся два файла client01.key и client01.csr.
   
3.3. Подпись запроса на сертификат (CSR) с помощью доверенного сертификата (CA).
+
===Подпись запроса на сертификат (CSR) с помощью доверенного сертификата (CA).===
   
 
При подписи запроса используются параметры заданные в файле ca.config
 
При подписи запроса используются параметры заданные в файле ca.config
  +
<PRE>
 
 
openssl ca -config ca.config -in client01.csr -out client01.crt -batch
 
openssl ca -config ca.config -in client01.csr -out client01.crt -batch
  +
</PRE>
 
   
   
Строка 160: Строка 168:
 
Для создания следующих сертификатов нужно повторять эти два шага.
 
Для создания следующих сертификатов нужно повторять эти два шага.
   
3.4. Создание сертификата в формате PKCS#12 для браузера клиента
+
===Создание сертификата в формате PKCS#12 для браузера клиента===
 
Это на тот случай, если к вашему серверу подключаются не бездушные машины, как в моём случае, а живые люди через браузер.
 
Это на тот случай, если к вашему серверу подключаются не бездушные машины, как в моём случае, а живые люди через браузер.
 
Запароленный файл PKCS#12 надо скормить браузеру, чтобы он смог посещать ваш сайт.
 
Запароленный файл PKCS#12 надо скормить браузеру, чтобы он смог посещать ваш сайт.
  +
<PRE>
 
 
openssl pkcs12 -export -in client01.crt -inkey client01.key -certfile ca.crt -out client01.p12 -passout pass:q1w2e3
 
openssl pkcs12 -export -in client01.crt -inkey client01.key -certfile ca.crt -out client01.p12 -passout pass:q1w2e3
  +
</PRE>
   
   
  +
===Подключение к полученному ssl cерверу с помощью curl===
 
  +
<PRE>
3.5 Подключение к полученному ssl cерверу с помощью curl
 
 
 
curl -k --key client.key --cert client1.crt --url "https://site.com"
 
curl -k --key client.key --cert client1.crt --url "https://site.com"
  +
</PRE>
 
   
   
 
Использована опция -k, потому что сертификат в примере самоподписанный
 
Использована опция -k, потому что сертификат в примере самоподписанный
  +
=Ссылки=
  +
* http://blog.nategood.com/client-side-certificate-authentication-in-ngi

Текущая версия на 16:30, 26 сентября 2022


Авторизация клиентов в nginx посредством SSL сертификатов

Введение: Потребовалось мне тут как-то написать небольшой API, в котором необходимо было помимо обычных запросов принимать запросы с «высокой степенью секретности». Не я первый с этим столкнулся и мир давно уже использует для таких вещей SSL.
Поскольку моём на сервере используется nginx, то был установлен модуль SSL Гугл не выдал ни одного работоспособного howto, но информация в сети есть по частям.
Итак, пошаговое руководство по настройке nginx на авторизацию клиентов через SSL-сертификаты. Внимание! В статье для примера используются самоподписанные сертификаты!

Перед стартом создадим папку в конфиге nginx, где будут плоды наших трудов:

cd /path/to/nginx/config/ mkdir ssl && cd ssl


Создание собственного самоподписанного доверенного сертификата.


Собственный доверенный сертификат (Certificate Authority или CA) необходим для подписи клиентских сертификатов и для их проверки при авторизации клиента веб-сервером. С помощью приведенной ниже команды создается закрытый ключ и самоподписанный сертификат.

openssl req -new -newkey rsa:1024 -nodes -keyout ca.key -x509 -days 500 -subj /C=RU/ST=Kharkov/L=Kharkov/O=MirantisInc/OU=User/CN=etc/emailAddress=sirmax@noname.com.ua -out ca.crt


Описание аргументов:

  • req Запрос на создание нового сертификата.
  • -new Создание запроса на сертификат (Certificate Signing Request – далее CSR).
  • -newkey rsa:1023 Автоматически будет создан новый закрытый RSA ключ длиной 1024 бита. Длину ключа можете настроить по своему усмотрению.
  • -nodes Не шифровать закрытый ключ.
  • -keyout ca.key Закрытый ключ сохранить в файл ca.key.
  • -x509 Вместо создания CSR (см. опцию -new) создать самоподписанный сертификат.
  • -days 500 Срок действия сертификата 500 дней. Размер периода действия можете настроить по своему усмотрению. Не рекомендуется вводить маленькие значения, так как этим сертификатом вы будете подписывать клиентские сертификаты.
  • -subj /C=RU/ST=Kharkov/L=Kharkov/O=MirantisInc/OU=User/CN=etc/emailAddress=sirmax@noanme.com.ua

Данные сертификата, пары параметр=значение, перечисляются через ‘/’. Символы в значении параметра могут быть «подсечены» с помощью обратного слэша «\», например «O=My\ Inc». Также можно взять значение аргумента в кавычки, например, -subj «/xx/xx/xx».

Сертификат сервера

Создадим сертификат для nginx и запрос для него

openssl genrsa -des3 -out server.key 1024

Пароль например q1w2e3

openssl req -new -key server.key -out server.csr


Подпишем сертификат нашей же собственной подписью

openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt


Чтобы nginx при перезагрузке не спрашивал пароль, сделаем для него беспарольную копию сертификата

openssl rsa -in server.key -out server.nopass.key

Конфиг nginx

listen *:443;
ssl on;
ssl_certificate /path/to/nginx/ssl/server.crt;
ssl_certificate_key /path/to/nginx/ssl/server.nopass.key;
ssl_client_certificate /path/to/nginx/ssl/ca.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;


теперь сервер готов принимать запросы на https. в переменных к бекенду появились переменные с информацией о сертификате, в первую очередь SSL_VERIFIED (принимает значение SUCCESS).

Однако если вы попытаетесь зайти на сайт, он выдаст ошибку:

400 Bad Request
No required SSL certificate was sent


Что ж, логично, в этом-то и вся соль!

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

Подготовка CA

Обратить внимаени - Common Name на клиенте не должно совпадать с серверным:

I had the same problem (under Nginx). Solution was to make my client common name something other than the server's certs common name. Originally I thought that my cert CN had to match the FQDN of the server cert.

Иначе - серетфикат работать на будет.


Создадим конфиг ca.config со следующим содержимым:

[ ca ]
default_ca = CA_CLIENT # При подписи сертификатов # использовать секцию CA_CLIENT

[ CA_CLIENT ]
dir = ./db # Каталог для служебных файлов
certs = $dir/certs # Каталог для сертификатов
new_certs_dir = $dir/newcerts # Каталог для новых сертификатов

database = $dir/index.txt # Файл с базой данных подписанных сертификатов
serial = $dir/serial # Файл содержащий серийный номер сертификата (в шестнадцатиричном формате)
certificate = ./ca.crt # Файл сертификата CA
private_key = ./ca.key # Файл закрытого ключа CA

default_days = 365 # Срок действия подписываемого сертификата
default_crl_days = 7 # Срок действия CRL
default_md = md5 # Алгоритм подписи

policy = policy_anything # Название секции с описанием политики в отношении данных сертификата

[ policy_anything ]
countryName = optional # Поля optional - не обязательны, supplied - обязательны
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = optional
emailAddress = optional


Далее надо подготовить структуру каталогов и файлов, соответсвующую описанной в конфигурационном файле

mkdir db
mkdir db/certs
mkdir db/newcerts
touch db/index.txt
echo "01" > db/serial

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

Для создания подписанного клиентского сертификата предварительно необходимо создать запрос на сертификат, для его последующей подписи. Аргументы команды полностью аналогичны аргументам использовавшимся при создании самоподписанного доверенного сертификата, но отсутсвует параметр -x509.

openssl req -new -newkey rsa:1024 -nodes -keyout client01.key -subj /C=RU/ST=Kharkov/L=Kharkov/O=MirantisInc/OU=User/CN=etc/emailAddress=sirmax@noname.com.ua -out client01.csr


В результате выполнения команды появятся два файла client01.key и client01.csr.

Подпись запроса на сертификат (CSR) с помощью доверенного сертификата (CA).

При подписи запроса используются параметры заданные в файле ca.config

openssl ca -config ca.config -in client01.csr -out client01.crt -batch


В результате выполнения команды появится файл клиентского сертификата client01.crt.

Для создания следующих сертификатов нужно повторять эти два шага.

Создание сертификата в формате PKCS#12 для браузера клиента

Это на тот случай, если к вашему серверу подключаются не бездушные машины, как в моём случае, а живые люди через браузер. Запароленный файл PKCS#12 надо скормить браузеру, чтобы он смог посещать ваш сайт.

openssl pkcs12 -export -in client01.crt -inkey client01.key -certfile ca.crt -out client01.p12 -passout pass:q1w2e3


Подключение к полученному ssl cерверу с помощью curl

curl -k --key client.key --cert client1.crt --url "https://site.com"


Использована опция -k, потому что сертификат в примере самоподписанный

Ссылки