Skip to content

Instantly share code, notes, and snippets.

@eugene-taylashev
Last active January 26, 2023 19:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eugene-taylashev/64738f60d25bcd4ba2b87a1975c6ac49 to your computer and use it in GitHub Desktop.
Save eugene-taylashev/64738f60d25bcd4ba2b87a1975c6ac49 to your computer and use it in GitHub Desktop.
mini How-To: two-way TLS v1.3 for a Nginx server

TLS for Nginx

Purpose: describe steps to configure a Nginx server and cURL as clients for a two-way verification over TLS v1.3

Updated on: Apr 18, 2020

Prerequisites:

  • A server's private key, a CA chain certificate and a server's X.509 certificate with Extended Key Usage (EKU) 'TLS Web Server Authentication' and proper 'Subject Alternative Name' like 'DNS:srv.example.com'.

  • A client's private key and X.509 certificate with EKU 'TLS Web Client Authentication'

Out of Scope: The following will not be covered

  • Generating a server and a client X.509 certificates. See miniPKI
  • Installing and starting a Nginx server

Test environment: This mini How-To has been tested with the following:

  • Nginx/1.14.0 on Ubuntu 18.04.4 LTS
  • curl 7.69.1 with OpenSSL/1.1.1f

Preparation

Step 1: Combine the server's certificate with CA chain certs. The server certificate is the first:

#cat ./srv.crt ./ca-chain.pem >srv-chain.crt

Step 2: Copy the server's private key, the combined X.509 certificate to your OpenSSL's directories. You can find the OpenSSL root directory for your distribution with the command $openssl version -d But typically it is /etc/ssl/. Run the following as root:

#mv ./srv.key /etc/ssl/private/
#mv ./srv-chain.crt /etc/ssl/certs/
#mv ./ca-chain.pem /etc/ssl/certs/

Step 3: Verify ownership and permission (the group ssl-cert for certificate management could be different for your distro):

#chown root:ssl-cert /etc/ssl/private/srv.key
#chmod 440 /etc/ssl/private/srv.key
#chown root:ssl-cert /etc/ssl/certs/srv-chain.crt /etc/ssl/certs/ca-chain.pem
#chmod 644 /etc/ssl/certs/srv-chain.crt /etc/ssl/certs/ca-chain.pem

Step 4: Add a custom log format to /etc/nginx/nginx.conf:

http {
    ...
    log_format ssl_client
    '$remote_addr - $remote_user [$time_local] '
    '"$request" $status $body_bytes_sent '
    '"Client fingerprint" $ssl_client_fingerprint '
    '"Client DN" $ssl_client_s_dn';
    ...

Case 1: A client verifies the server (one-way TLS v1.3)

Step 5: Configure the TLS server by creating the file /etc/nginx/conf.d/site-tls.conf with the content:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name srv.example.com;
    root /var/www/tls;

    # Using the custom log format:
     access_log /var/log/nginx/ssl.log ssl_client;
   
    ssl_certificate /etc/ssl/certs/srv-chain.crt;
    ssl_certificate_key /etc/ssl/private/srv.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    }

Step 6: Start the server: #systemctl start nginx

Step 7: From another host verify the TLS connectivity using OpenSSL: openssl s_client -showcerts -connect srv.example.com:443

Connect with cURL : curl -v --cacert /etc/ssl/certs/ca-chain.pem https://srv

Case 2: A client and the server verify each other (two-way TLS v1.3)

Step 8: For client authentication add to the file /etc/nginx/conf.d/site-tls.conf the following:

server {
    ....
    ssl_client_certificate /etc/ssl/certs/ca-chain.pem;
    ssl_verify_client on;
    ssl_verify_depth 10;     
    ....
    }
  • For more granular access control add to the file /etc/nginx/conf.d/site-tls.conf the following:
server {
    ....
    # Access control -- the if needs to be outside of the location sections
    # Note https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
    if ($ssl_client_fingerprint != "d2818c5263a98ca63ce0cad359f912736cc3a0ce") {
        return 403;
        }
    ....
    }
  • To get the client’s certificate fingerprint: openssl x509 -in clnt.crt -noout -fingerprint

Step 9: From another host verify the two-way TLS connectivity using cURL:

curl -v --cacert /etc/ssl/certs/ca-chain.pem \
--key /etc/ssl/private/client.key --cert /etc/ssl/certs/client.crt \
https://srv

See Also:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment