I'm currently trying to set up nginx as a proxy for a website which requires certificate authentication.
The following curl command works perfectly:
curl --cacert ca-cert.pem -v --key client.key --cert client.pem https://example.com:443
However, the following nginx configuration seems to be rejected by the server:
server {
listen 80;
location / {
proxy_pass https://example.com;
proxy_set_header Host example.com;
proxy_ssl_certificate /etc/nginx/client.pem;
proxy_ssl_certificate_key /etc/nginx/client.key;
proxy_ssl_trusted_certificate /etc/nginx/ca-cert.pem;
proxy_ssl_verify off;
}
}
The full error from the nginx logs is:
2021/03/08 20:43:06 [error] 29#29: *1 SSL_do_handshake() failed (SSL: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:SSL alert number 48) while SSL handshaking to upstream, client: 172.17.0.1, server: , request: "GET / HTTP/1.1", upstream: "https://x.x.x.x:443/", host: "localhost:80"
Does anyone know what's going on? Isn't the nginx config equivalent to the curl command?
Best Answer
The upstream server can not validate the send client certificate since it is missing intermediate certificates. Therefore it sends back to nginx the cause of the problem as an alert. The fix is probably to add the necessary intermediate certificates to
client.pem
in the right order (i.e. leaf certificate first, then what signed leaf certificate etc).But why did it work with curl then: Depending on which TLS stack is used with curl and maybe depending on the version of curl it will automatically combine the certificate given with
--cert
with matching intermediate certificates given in--cacert
and send the full chain to the server as part of the client certificate. If this is done then the server can successfully validate the client certificate.