Nginx-Mutual SSL/One way SSL with multiple clients

Use Case

Jenananthan
3 min readJun 8, 2016
  • Nginx acts as reverse proxy for two web services
  • To access one web service mutual ssl(two way ssl) is required between client and nginx
  • Other web service can be access through normal ssl(one way ssl)

Step 1 — Add host mappings

Add host mappings in /etc/hosts file

127.0.0.1 nginx.ssl.com
127.0.0.1 ningx.mssl.com

Step 2 — Configure keystore and truststore in Nginx for mutual SSL

  1. Create public and private key for Nginx

Execute the following command and create the public and private key by providing Necessary information.

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout nginx.key -out nginx.crt

This will create nginx.key (private key) and ninx.crt(public key) files.

2. Add certificate to Nginx (keystore)

  • Navigate to /etc/nginx
  • Create directory called ‘ssl’ if not exists. (sudo mkdir ssl)
  • Create directory called nginx under ‘ssl’ (sudo mkdir ssl/nginx)
  • Copy the nginx.crt and nginx.key files to nginx directory

3. Create certificate bundle(trust store) which contains trusted client certificates

  • Create file client.crt.
  • Copy client certificates in PEM format ( — — BEGIN CERTIFICATE — — ) to client.crt.
    E.g content of client.crt would as follow with multiple certificates of clients.
----BEGIN CERTIFICATE----
MIID1zCCAr+gAwIBAgIJAOionwNR1+i5MA0GCSqGSIb3DQEBCwUAMIGBMQswCQYDdDLBGx02puZ4dcnMGxNVdhfthTgeQZWbjSz60ynf2BuAluPnEB/dewE3g7+7iX3JwP/srv+nn/Afbd2qcKxDoa30fdY2Dn+D2aqz
----END CERTIFICATE ----
----BEGIN CERTIFICATE ----
MIID0TCCArmgAwIBAgIJAIyACy6aDchHMA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNVhhuXl1223sNZa2nbcioJ32ihJ2q4sT7xcpv8lLJ/R0jhdOzB+W7EN1I9MuLbDBxkljtCLv+PMCLAw2gzgsAr/s2xSVFQ
----END CERTIFICATE ----
  • Add client’s’ certificate(certificate bundle client.crt) to Nginx as trust store
  1. Navigate to /etc/nginx
  2. Create directory called ‘ssl’ if not exists. (sudo mkdir ssl)
  3. Create directory called nginx under ‘trust’ (sudo mkdir ssl/trust)
  4. Copy the client.crt file to nginx directory

Step 3 -Add nginx virtual server configuration

We need two virtual server to handle two different requests(mutual ssl and one way ssl).

Navigate to /etc/nginx/conf.d and add following configuration

  • mutualssl.conf(Nginx virtual server configuration for mutual ssl)
server {listen 443;
server_name nginx.mssl.com;
ssl on;
ssl_certificate /etc/nginx/ssl/nginx/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx/nginx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#setting for mutual ssl with client
ssl_client_certificate /etc/nginx/ssl/trust/client.crt;
ssl_verify_client on;
location / {
root /usr/share/nginx/mssl;
index index.html index.htm;
}
}
  • onewayssl.conf (Nginx virtual server configuration for one way ssl)
server {listen 443;
server_name nginx.ssl.com;
ssl on;
ssl_certificate /etc/nginx/ssl/nginx/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx/nginx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}

Step 4 -Setting Up upstream for test the use cases

For mutual ssl nginx configuration upstream is configured as follow where it points to an index.html in /usr/share/nginx/mssl

 location / {
root /usr/share/nginx/mssl;
index.html index.htm;
}

Create the sample upstream for mutual ssl use case

  • Navigate to /usr/share/nginx/ and create a directory called “mssl”
  • Create index.html with following content in directory “mssl”
<html><body><h1>Welcome to nginx!-mutual ssl test</h1></body></html>

Create the sample upstream for one way ssl use case

For one way ssl nginx configuration upstream is configured as follow where it points to an index.html in /usr/share/nginx/html

location / {
root /usr/share/nginx/html;
index index.html index.htm;
}

Create the sample upstream for mutual ssl use case

  • Navigate to /usr/share/nginx/ and create a directory called “html”
  • Create index.html with following content in directory “html”
<html><body><h1>Welcome to nginx!- one way ssl test</h1></body></html>

Step 5 -Verify

  1. Start/Restart the nginx
  2. Verify one way ssl

Invoke
curl -k https://nginx.ssl.com

This called will be hit the virtual server defined in the onewayssl.conf

Response :

 <html><body><h1>Welcome to nginx!- one way ssl test</h1></body></html>

3. Verify mutual ssl

Invoke curl -k https://nginx.mssl.com

This called will be hit the virtual server defined in the mutualssl.conf

Response:


<html>
<head><title>400 No required SSL certificate was sent</title></head><body bgcolor=”white”><center><h1>400 Bad Request</h1></center><center>No required SSL certificate was sent</center><hr><center>nginx/1.8.1</center></body></html>

You will get this response because in the curl command we have not specified the client’s key and certificate.But for mutual ssl nginx needs client certificate in ssl handshake. So it will return above error response.

So actual call should be as follow ,where cleint.crt should be in the trust store of nginx.

(client.key -> client’s private key,client.crt-> clients public certificate)

curl -v -k -key client.key -cert client.crt https://nginx.mssl.com

Response:

<html><body><h1>Welcome to nginx!- -mutual ssl test</h1></body></html>

Reference

https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms

--

--