Nginx mutual SSL with WSO2 ESB/API Manager
Prerequisite
- Nginx server 1.8 (version > 1.7.8, proxy_ssl_certificate directive is available from 1.7.8 only)
Installing nginx server 1.8 can be found here
https://www.jamescoyle.net/how-to/1678-install-nginx-on-debian-ubuntu
To uninstall the existing nginx ,execute following command
sudo apt-get purge nginx nginx-common nginx-full
- Environment -ubuntu
- wso2apim(or wso2esb/wso2appmanager)
- curl
STEP 1
Configure Nginx for One way ssl from Client to Nginx
(Client) ←One Way SSL → (Nginx Server)
- 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.
- Add certificate to Nginx
- 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
- Add configuration
Add following host map in /etc/hosts file
127.0.0.1 nginx.proxy.com
- Add following configuration to /etc/nginx/conf.d/default.conf
server {listen 443;
server_name nginx.proxy.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;#This location section is to test and verify the client to server ssl connection
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}}
- Verify
Restart the nginx
Execute : curl -k https://nginx.proxy.com
Result -
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p><p>For online documentation and support please refer to<a href=”http://nginx.org/">nginx.org</a>.<br/>Commercial support is available at<a href=”http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
STEP 2
Configure Nginx for mutual ssl/two way ssl between client and Nginx
(Client) ←Mutual SSL/TWO Way SSL → (Nginx Server)
- Create public and private key for client(here we use curl as client)
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 client.key -out client.crt
This will create client.key (private key) and client.crt(public key) files.
- Add client’s certificate to Nginx
- 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
- Add configuration to enable mutual ssl (nginx requests client certificate in SSL handshake)
Modify the configuration(/etc/nginx/conf.d/default.conf) done in STEP 1 by adding
#setting for mutual ssl with client
ssl_client_certificate /etc/nginx/ssl/trust/client.crt;
ssl_verify_client on;
Configuration after modification
server {listen 443;
server_name nginx.proxy.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/html;
index index.html index.htm;
}}
7. Verify
Restart the nginx
Execute command : curl -k https://nginx.proxy.com
Result :
<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>
Getting above message from server. Because server(Nginx) expecting the client’s certificate in SSL handshake, but curl doesn’t have the cert to provide.
So correct curl command should be like this ,
curl -k — key client.key — cert client.crt https://nginx.proxy.com
This will give success response as got in STEP 1
STEP 3
Configure Nginx for one way ssl from Nginx to backend server(upstream)
(Client) ←Mutual SSL → (Nginx Server) ←One way SSL →(Backend server)
- Create a inline prototype api for GET method in API Manager. We are going to invoke this api though nginx.
- Add configuration to Proxy the gateway
Modify the configuration(/etc/nginx/conf.d/default.conf) done in STEP 2 by adding
location /gateway/ {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://localhost:8243/;
proxy_redirect https://localhost:8243/ https://nginx.proxy.com/
gateway/;}
Configuration after modification
server {listen 443;
server_name nginx.proxy.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/html;
index index.html index.htm;}location /gateway/ {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://localhost:8243/;
proxy_redirect https://localhost:8243/ https://nginx.proxy.com/
gateway/;}}
3. Verify
Restart the nginx
If created api’s gateway url is https://nginx.proxy.com/gateway/test/1
Execute :curl -k — key client.key — cert client.crt https://nginx.proxy.com/gateway/test/1
Result : { “data” : “sample JSON”}
STEP 4
Configure Nginx for mutual ssl between Nginx and Backend server/upstream
(Client) ←Mutual SSL → (Nginx Server) ←Mutual →(Backend server)
- Modify the configuration(/etc/nginx/conf.d/default.conf) done in STEP 3 by adding
#setting for mutual ssl with upstream/backend server
proxy_ssl_certificate /etc/nginx/ssl/nginx/nginx.crt;
proxy_ssl_certificate_key /etc/nginx/ssl/nginx/nginx.key;
Configuration after modification
server {listen 443;
server_name nginx.proxy.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 /gateway/ {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://localhost:8243/;
proxy_redirect https://localhost:8243/ https://nginx.proxy.com
/gateway/;#setting for mutual ssl with upstream/backend server
proxy_ssl_certificate /etc/nginx/ssl/nginx/nginx.crt;
proxy_ssl_certificate_key /etc/nginx/ssl/nginx/nginx.key;}}
2. Configure API Manager for mutual ssl
- Enable mutual ssl in /repository/conf/axis2/axis2.xml by adding
<parameter name=”SSLVerifyClient”>require</parameter>
under https transportReceiver
- Import nginx certificate to wso2 server’s (nginx.crt) trust store
keytool -import -file nginx.crt -alias nginx -keystore client-truststore.jks
3. Verify
Restart the nginx and APIM
Execute :curl -k — key client.key — cert client.crt https://nginx.proxy.com/gateway/test/1
Result : { “data” : “sample JSON”}
Note : We use -k option in curl to access in insecure way . if not using this option need to point a trust store to curl and trust store should have the public cert we generated for nginx.
Also nigx access the backend in insecure way , to verify the back end’s certificate in SSL handshake following configuration should be added to upstream’s location section.
#verify server certificate in ssl handshake
proxy_ssl_verify on;
proxy_ssl_trusted_certificate etc/nginx/ssl/upstream/wso2carbon.pem;
Where backend servers certificate should be in pem format.
For openssl 1.1.0 this will not work on ubuntu since there is following bug
http://serverfault.com/questions/389197/ssl-routinesssl23-writessl-handshake-failure
Nginx — commands
sudo /etc/init.d/nginx startsudo /etc/init.d/nginx stopsudo /etc/init.d/nginx restartsudo /etc/init.d/nginx reload