Authorization of clients in nginx via SSL certificates
Introduction:
It took me here somehow to write a small API, in which, in addition to ordinary requests, it was necessary to accept requests with a "high degree of secrecy."
I was not the first to encounter this and the world has long been using SSL for such things .
Since nginx is used on my server, the Google SSL module was installed. It
didn’t give a single working howto, but the information on the network is in parts.
So, a step-by-step guide on configuring nginx to authorize clients through SSL certificates .
Attention! This article uses self-signed certificates as an example!
Before starting, create a folder in the nginx config, where the fruits of our labors will be:
cd /path/to/nginx/config/
mkdir ssl && cd ssl
Step 1. Create your own self-signed trusted certificate.
A personal trusted certificate (Certificate Authority or CA) is required for signing client certificates and for verifying them when authorizing a client with a web server.
Using the command below creates a private key and a self-signed certificate.
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
Description of the arguments:
req Request to create a new certificate.
-new Create a Certificate Signing Request (hereinafter CSR).
-newkey rsa: 1023 A new 1024-bit RSA private key will be automatically created. You can adjust the key length as you wish.
-nodes Do not encrypt private key.
-keyout ca.key Save the private key to the ca.key file.
-x509 Instead of creating a CSR (see the -new option) create a self-signed certificate.
-days 500 Validity of the certificate is 500 days. You can adjust the size of the validity period as you wish. It is not recommended to enter small values, because with this certificate you will sign client certificates.
-subj /C=RU/ST=Moscow/L=Moscow/O=Companyname/OU=User/CN=etc/emailAddress=support@site.com
Certificate data, parameter = value pairs, are listed through '/'. Characters in the parameter value can be "undercut" using the backslash "\", for example, "O = My \ Inc". You can also quote the value of the argument, for example, -subj “/ xx / xx / xx”.
Step 2. Server Certificate
Create a certificate for nginx and request for it
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
We will sign the certificate with our own signature
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
So that nginx does not ask for a password upon reboot, we will make a passwordless copy of the certificate for it
openssl rsa -in server.key -out server.nopass.key
Nginx config
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;
Now the server is ready to accept https requests.
variables with certificate information appeared in the variables for the backend, primarily SSL_VERIFIED (takes the value SUCCESS).
However, if you try to access the site, it will give an error:
400 Bad Request
No required SSL certificate was sent
Well, it’s logical that this is the whole point!
Step 3. Create client certificates
3.1 CA preparation
Create the
nano ca.config config
with the following contents:
[ 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
Next, you need to prepare the directory and file structure corresponding to that described in the configuration file
mkdir db
mkdir db/certs
mkdir db/newcerts
touch db/index.txt
echo "01" > db/serial
3.2. Creating a Client Private Key and Certificate Request (CSR)
To create a signed client certificate, you must first create a certificate request for its subsequent signing. The command arguments are completely similar to the arguments used to create the self-signed trusted certificate, but the -x509 parameter is missing.
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
As a result of the command, two files client01.key and client01.csr will appear.
3.3. Certificate Request Signing (CSR) using a trusted certificate (CA).
When signing the request, the parameters specified in the ca.config file are used
openssl ca -config ca.config -in client01.csr -out client01.crt -batch
As a result of the command, the client certificate file client01.crt will appear.
To create the following certificates, repeat these two steps.
3.4. Creating a PKCS # 12 certificate for a client browser
This is in case if not soulless machines are connected to your server, as in my case, but live people through a browser.
The password-protected PKCS # 12 file must be fed to the browser so that it can visit your site.
openssl pkcs12 -export -in client01.crt -inkey client01.key -certfile ca.crt -out client01.p12 -passout pass:q1w2e3
3.5 Connection to the received ssl server using curl
curl -k --key client.key --cert client1.crt --url "https://site.com"
The -k option is used because the certificate in the example is self-signed
Used software
Ubuntu Server 10.10 (Linux 2.6.35-22-server # 35-Ubuntu SMP x86_64 GNU / Linux)
nginx 0.9.3
OpenSSL 0.9.8o 01 Jun 2010
useful links
- OpenSSL on Ubuntu
- General SSL configuration for generating client certificates
- Setting up under ssl nginx'a (it didn’t work for me)
- ngx_http_ssl_module module
I hope it was useful to someone.
PS This post was my first publication on January 16, 2011, the old copy was deleted (at the request of the site administration and because it was not tied to my account).