Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up two-way SSL in Nginx for custom location?

I have a rails 4 project with some API.

This project runs with nginx v.1.6.3 and https on production.

Nginx configurations:

upstream app {
    # Path to Unicorn SOCK file, as defined previously
    server unix:/tmp/unicorn.my_domain.sock fail_timeout=0;
}

server {
       listen         80;
       server_name    my_domain.com;
       return         301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;

    ssl_certificate /etc/nginx/ssl/public.crt;
    ssl_certificate_key /etc/nginx/ssl/private.rsa;    

    server_name my_domain.com;

    root /var/www/current;

    location /assets {
        root /var/www/current/public;
        gzip_static on;
        expires max;
        add_header Cache-Control public;
    }

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

Problem

API requests (POST /api/some_path/create etc.) should be protected with two-way SSL.

Only one service will use this API (only 1 client with one certificate)

Question

  1. Does nginx able to handle two-way SSL?
  2. two-way SSL should be implemented on nginxlayer, not in web-application logic. am I right?
  3. How to set up nginx to catch clients which sends requests to /api/... url and authenticate them with two-way SSL?

I just need a basic example, to understand how it should work.

like image 313
bmalets Avatar asked Feb 23 '16 10:02

bmalets


1 Answers

  1. Yes (see the ssl_client_certificate and ssl_verify_client directives).
  2. Depends on your application, but in this case where you only need to verify that the certificate was signed by a certain CA, that's correct.
  3. You would need to create a CA and a client certificate signed by said CA and use that CA for verifying the client certificate on the server side.

    Now, what you need to consider is how you will solve the problem that the ssl_client_certificate and ssl_verify_client directives doesn't support being used in a location block (e.g. they can only be used in a http or server block).

    I would suggest creating an own subdomain for the API (e.g. api.my_domain.com) and access the API from the service with that address.

Example configuration:

server {
    listen 443 ssl;

    ssl_certificate /etc/nginx/ssl/public.crt;
    ssl_certificate_key /etc/nginx/ssl/private.rsa;

    ssl_client_certificate /etc/nginx/ssl/client_ca.pem;
    ssl_verify_client on;

    server_name api.my_domain.com;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app/api;
    }
}
like image 139
Lochnair Avatar answered Oct 02 '22 13:10

Lochnair