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;
}
}
}