I need some help in nginx.conf. I need to protect resources starting from /devices using client certificate authentication. The other resources are over https but don't need client certificate.
I installed nginx on ubuntu 16.04 using repository. Then I create a file called dozee.conf inside /etc/nginx/conf.d/ and pasted the content from an serverfault Q&A (https://serverfault.com/a/721704/80340) and modified it as required.
The configuration inside dozee.conf looks like
server {
listen *:443 ssl;
server_name localhost;
ssl on;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
ssl_client_certificate /etc/nginx/ca.crt;
ssl_verify_client on;
location /device {
proxy_pass http://localhost:8080/device;
proxy_read_timeout 90;
#proxy_redirect http://localhost/ $scheme://$host:$server_port/;
}
}
server {
listen *:443 ssl;
ssl on;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
ssl_client_certificate /etc/nginx/ca.crt;
ssl_verify_client off;
location / {
proxy_pass http://localhost:8080/;
proxy_read_timeout 90;
#proxy_redirect http://localhost/ $scheme://$host:$server_port/;
}
}
The issue I am facing here is that the behaviour of the nginx is dominated by second server block.
If I change ssl_verify_client off;
in second server block to ssl_verify_client on;
both the paths /
& /device
start asking client certificate.
If I keeps ssl_verify_client
as off
none of them needs a client certificate.
What I am doing wrong here?
Your first
server
block matches only requests likehttps://localhost/some/url
. All other requests are processed by the secondserver
block.However, it might be that nginx cannot be used for the use case you want. When the TLS connection is initialised, there is no information about the upper layer HTTP request for nginx to decide if it should require a client certificate from the client or not. It can only do this based on the virtual host name information, which is passed with SNI on the TLS connection setup.
In Apache, one can force a TLS re-negotiation based on the URL path, where Apache then requests a client certificate. I haven't found similar option in nginx.
Therefore your only option with nginx might be to use another virtual host (eg. devices.example.com) for your devices. And this is the actual solution that the answer had where you copy-pasted the configuration.