I was excited to see proxy_ssl_certificate and friends land in Nginx 1.7.8, and decided to revisit Nginx as a candidate for proxy caching an upstream server requiring client authentication. I've included the debugging configuration I've been playing around with at the end of this post.
This particular upstream server does not trigger client authentication for all endpoints. For example, I can issue
-----
http http://NGINX_PROXY_IP/test/path Host:UPSTREAM_SERVER
-----
and get back the proxied response without error. However, for endpoints that require client authentication (triggered by the server after it examines the request path), nginx never gets a response. I've verified that the upstream server is working as expected using both wget:
-----
wget --verbose --debug --save-headers -O - --ca-certificate=PATH_TO_SERVER_CERTFICATE --certificate=PATH_TO_CLIENT_CERTIFICATE --private-key=PATH_TO_CLIENT_PRIVATE_KEY https://UPSTREAM_SERVER/path/requiring/client/authentication
-----
and openssl's s_client:
-----
echo -e "GET https://UPSTREAM_SERVER/path/requiring/client/authentication HTTP/1.0\r\n\r\n" | openssl s_client -ign_eof -connect UPSTREAM_SERVER:443 -state -debug -cert PATH_TO_CLIENT_CERTIFICATE -key PATH_TO_CLIENT_PRIVATE_KEY
-----
In the latter case, it's apparent that the server triggers renegotiation after seeing the requested path, and openssl's s_client responds accordingly by sending the client certificate, completing the exchange moments later. However, when invoking the same via the Nginx proxy:
-----
http http://NGINX_PROXY_IP/ Host:UPSTREAM_SERVER/path/requiring/client/authentication
-----
the upstream connection eventually closes after sending no data -- the same behaviour it exhibits when no client certificates are provided via wget or openssl's s_client.
I'm using nginx.debug and have verified that the client certificate files are read (throwing errors if the wrong path is specified). I've also used ltrace and verified that Nginx appears to inject the client certificate via SSL_CTX_use_certificate (taking a somewhat different path than wget's SSL_CTX_use_certificate_file).
Have I failed to configure Nginx with the requisite client certificates? Is there anyway to see the level of debugging from openssl's s_client but via Nginx?
Here's the configuration in question:
-----
user nginx;
worker_processes 1;
daemon off;
error_log /var/log/nginx/error.log debug;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
proxy_cache_methods GET HEAD;
proxy_cache_min_uses 1;
server {
listen 80;
proxy_http_version 1.1;
proxy_ssl_protocols 'TLSv1.2';
proxy_ssl_certificate PATH_TO_CLIENT_CERTIFICATE;
proxy_ssl_certificate_key PATH_TO_CLIENT_PRIVATE_KEY;
proxy_ssl_session_reuse off;
proxy_ssl_trusted_certificate PATH_TO_SERVER_CERTFICATE;
proxy_ssl_verify on;
location / {
resolver 8.8.8.8;
proxy_pass https://$host$request_uri;
proxy_cache rest-cache;
add_header rt-Fastcgi-Cache $upstream_cache_status;
proxy_set_header Host $host;
proxy_ignore_headers Set-Cookie;
}
}
}
-----