Авторизация в Nginx клиентским сертификатом
1. Аутентификация в Nginx при помощи клиентского сертификата
Аутентификация в Nginx предназначена для ограничения доступа к web-ресурсу. Аутентификация бывает Базовая (при помощи пары "логин/пароль"). В статье рассматривается вариант аутентификации сертификатом.
Аутентификация сертификатом
Сертификат клиента (client-side certificate) - это механизм аутентификации транспортного уровня, который позволяет проверить пользователя до перехода на уровень приложений.
Удостоверяющий центр
Для выпуска клиентский сертификатов необходимо создать ключ Удостоверяющего центра (Certificate Authority), который будет использоваться для создания сертификата сервера (server-side certificate):
openssl genrsa -des3 -out ca.key 4096
При создании ключа будет запрошена ключевая фраза, которую необходимо запомнить. Она потребуется каждый раз при создании нового сертификата или подписывании запроса клиентского сертификата.
Сертификат Удостоверяющего центра
Далее необходимо создать сертификат Удостоверяющего центра (CA Certificate) - это серверный сертификат, который будет направляться клиенту через TLS.
Этот сертификат не является заменой TLS сертификата Nginx.
openssl req -new -x509 -days 1095 -key ca.key -out ca.crt
Здесь нужно будет ответить на вопросы: Страна, Область, Город, Организация.
Рекомендуется пропустить общее имя сертификата (Common Name - CN).
Для обновления сертификата необходимо запустить такую же команду и также ответить на вопросы. Чтобы посмотреть, что входит в изданный сертификат, можно воспользоваться командой:
openssl x509 -in ca.crt -noout -text
Сертификат Клиента
Сертификат клиента по сути является "паролем" и выпускается для "устройства". Для выпуска понадобится ключ клиента, сгенерированный также, как ключ Удостоверяющего центра.
openssl genrsa -des3 -out user.key 4096
Из которого сформировать запрос на подпись сертификата (Certificate Signing Request, CSR)
openssl req -new -key user.key -out user.csr
Подпись запроса на сертификат
Сформированный запрос сертификата должен быть подписан Удостоверяющим центром, что подтверждает личность пользователя или устройства:
openssl x509 -req -days 365 -in user.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out user.crt
Обычно лучше увеличивать значения счетчика serial
при подписывании каждого нового сертификата.
Когда сертификат заканчивается, не нужно создавать новый запрос на сертификат, тот же запрос можно подписать, что создаст новый сертификат, привязанный к тому же публичному ключу.
Подписанный сертификат необходимо передать пользователю вместе с сертификатом удостоверяющего центра (не приватным ключом!) для установки на устройство пользователя.
Собрать связку PKCS #12 (PFX)
Для установки подписанного сертификата на устройства пользователей, его обычно собирают в связку (bundle), содержащую клиентский сертификат, его ключ, и сертификат удостоверяющего центра.
openssl pkcs12 -export -out user.pfx -inkey user.key -in user.crt -certfile ca.crt
Здесь появится запрос пароля, который нужно вводить каждый раз при использовании его на устройстве клиента. Можно оставить пустым.
Установка сертификата на устройство клиента
Настройка Nginx
Для проверки пользователей по сертификатам на обратном прокси необходимо добавить несколько строк в конфигурационный файл.
server { listen 80; server_name antroot.ru; return 301 https://antroot.ru$request_uri; } server { listen 443 ssl http2; server_name antroot.ru; access_log /var/log/nginx/antroot.ru.access.log; ssl_protocols TLSv1.2 TLSv1.3; # letsencrypt certificate ssl_certificate /etc/letsencrypt/live/antroot.ru/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/antroot.ru/privkey.pem; # client certificate ssl_client_certificate /etc/nginx/client_certs/ca.crt; # можно включить проверку опционально и обрабатывать далее, возвращая 403 ssl_verify_client optional; # либо обязательная проверка сертификата # ssl_verify_client on; location / { # вывод 403 при ошибке проверки сертификата клиента if ($ssl_client_verify != SUCCESS) { return 403; } proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://antroot.local:8080; proxy_read_timeout 90; # web sockets proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect http://antroot.local:8080 https://antroot.ru; } }
В целом, готово. Оставляем одну из директив в конфигурации Nginx ssl_verify_client
- включено или опционально и пользуемся.
2. Вариант с самоподписанным сертификатом
Создать сертификат Удостоверяющего центра
openssl req -new -newkey rsa:1024 -nodes -keyout ca.key -x509 -days 500 -subj /C=RU/ST=Moscow/L=Moscow/O=antroot/OU=User/CN=etc/emailAddress=support@antroot.ru -out ca.crt
Выпустить сертификат сервера, запрос на подпись, и подписать его
openssl genrsa -des3 -out server.key 1024 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
openssl rsa -in server.key -out server.nopass.key
ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.nopass.key; ssl_client_certificate /etc/nginx/ssl/ca.crt; ssl_verify_client on; keepalive_timeout 70; fastcgi_param SSL_VERIFIED $ssl_client_verify;
Для упрощения выпуска клиентских сертификатов сделаем конфиг:
[ 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 private_key = ./ca.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 = optional commonName = optional emailAddress = supplied
Создать клиентский ключ и запрос на сертификат и подписать запрос Удостоверяющим центром (повторяется для каждого следующего сертификата клиента):
openssl req -new -newkey rsa:1024 -nodes -keyout client01.key -subj /C=RU/ST=Moscow/L=Moscow/O=antroot/OU=User/CN=etc/emailAddress=support@antroot.ru -out client01.csr openssl ca -config ca.config -in client01.csr -out client01.crt -batch
Собрать в связку сертификат, ключ, промежуточный сертификат:
openssl pkcs12 -export -in client01.crt -inkey client01.key -certfile ca.crt -out client01.p12 -passout pass:123456qwerty
Проверка сертификата с помощью curl:
curl -k --key client.key --cert client1.crt --url "https://antroot.ru"