Nginx-Mutual SSL/One way SSL with multiple clients
Use Case
- 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
- 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
- Navigate to /etc/nginx
- Create directory called ‘ssl’ if not exists. (sudo mkdir ssl)
- Create directory called nginx under ‘trust’ (sudo mkdir ssl/trust)
- 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
- Start/Restart the nginx
- 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>