Authorization of clients in nginx via SSL certificates


    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/ -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/
    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/ -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 ""

    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

    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).

    Also popular now: