1

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?

1

...ssl3_read_bytes:tlsv1 alert unknown ca

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.

1
  • Thank you very much, I just pasted the intermediate certificate into the client.pem, and this solved the issue. – nett_hier Mar 10 at 13:15
0

There may be a difference if the http server at https://example.com serves multiple ("virtual") hosts and replies even if none was specified during SSL handshake.

Modern curl versions default to sending using server name indication (SNI), whereas nginx needs that to be explicitly enabled.

Try the same after adding proxy_ssl_server_name on; to your nginx conf.

Or look into the server logs of the upstream http server - they would note a connection for the default host (instead of a connection for example.com).

0

This error means that nginx could not verify the upstream server's TLS server certificate using the CA certificate you provided in proxy_ssl_trusted_certificate. Check that you have actually supplied the CA certificate that signed the server's certificate.

2
  • 2
    I would interpret the message more that the upstream server can not validate the client certificate and therefore sends a "unknown ca" alert back - which then gets logged by nginx. Thus the error is more likely that proxy_ssl_certificate is missing the chain certicates. – Steffen Ullrich Mar 8 at 21:08
  • I have almost identical issue I posted here: stackoverflow.com/questions/67295805/… I am tempted to say its the same solution Steffen wrote, but I am too much of server noob to figure it out – TDawg Apr 28 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.